aboutsummaryrefslogtreecommitdiffstats
path: root/lib/syntax_tools/src/merl_transform.erl
diff options
context:
space:
mode:
authorPéter Gömöri <[email protected]>2016-07-09 17:21:27 +0200
committerPéter Gömöri <[email protected]>2016-07-09 17:21:27 +0200
commitfee45935eb7f5a098cbbbaf1c8d1a8f9a77ce418 (patch)
treee5223681e9729194ed05c63eda92478a1c14d42d /lib/syntax_tools/src/merl_transform.erl
parentca4000874a198b218fd62b90e842475d2a0bb8c7 (diff)
downloadotp-fee45935eb7f5a098cbbbaf1c8d1a8f9a77ce418.tar.gz
otp-fee45935eb7f5a098cbbbaf1c8d1a8f9a77ce418.tar.bz2
otp-fee45935eb7f5a098cbbbaf1c8d1a8f9a77ce418.zip
Fix infinite loop in merl_transform
This can happen when a syntactically incorrect text is passed to a merl:qquote/2,/3 call. The parse transform optimizes calls to some functions in merl by converting strings into templates at compile time. If this evaluation fails (in eval_call/4 - for example because of a sytanx error in the parsed text) the original function call should be kept unchanged. However in case of qquote/3 the call is converted into a combination of quote/2 and subst/2, but upon failure the original qquote/3 call is substituted into the wrong place. E.g.: this expression merl:qquote(Pos, Text, Env) is first converted to merl:subst(merl:quote(Pos, Text), Env) then if evaluating the quote call fails into merl:subst(merl:qquote(Pos, Text, Env), Env) and the expansion is run again on the internal qquote/3 argument resulting in an infinite loop. This is now fixed so in case of failure the original qquote/3 call is kept.
Diffstat (limited to 'lib/syntax_tools/src/merl_transform.erl')
-rw-r--r--lib/syntax_tools/src/merl_transform.erl13
1 files changed, 9 insertions, 4 deletions
diff --git a/lib/syntax_tools/src/merl_transform.erl b/lib/syntax_tools/src/merl_transform.erl
index fe58b6a122..497baddd0a 100644
--- a/lib/syntax_tools/src/merl_transform.erl
+++ b/lib/syntax_tools/src/merl_transform.erl
@@ -104,10 +104,15 @@ expand_qquote([Text, Env], T, Line) ->
case erl_syntax:is_literal(Text) of
true ->
As = [Line, erl_syntax:concrete(Text)],
- %% expand further if possible
- expand(merl:qquote(Line, "merl:subst(_@tree, _@env)",
- [{tree, eval_call(Line, quote, As, T)},
- {env, Env}]));
+ case eval_call(Line, quote, As, failed) of
+ failed ->
+ T;
+ T1 ->
+ %% expand further if possible
+ expand(merl:qquote(Line, "merl:subst(_@tree, _@env)",
+ [{tree, T1},
+ {env, Env}]))
+ end;
false ->
T
end;