From fee45935eb7f5a098cbbbaf1c8d1a8f9a77ce418 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20G=C3=B6m=C3=B6ri?= Date: Sat, 9 Jul 2016 17:21:27 +0200 Subject: 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. --- lib/syntax_tools/src/merl_tests.erl | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'lib/syntax_tools/src/merl_tests.erl') diff --git a/lib/syntax_tools/src/merl_tests.erl b/lib/syntax_tools/src/merl_tests.erl index c1aae3100e..27db594050 100644 --- a/lib/syntax_tools/src/merl_tests.erl +++ b/lib/syntax_tools/src/merl_tests.erl @@ -48,6 +48,21 @@ parse_error_test_() -> f(merl:quote("{"))) ]. +transform_parse_error_test_() -> + [?_assertEqual("merl:quote(\"{\")", + f(merl_transform:parse_transform( + [?Q("merl:quote(\"{\")")], []))), + ?_assertEqual("merl:quote(2, \"{\")", + f(merl_transform:parse_transform( + [?Q("merl:quote(2, \"{\")")], []))), + ?_assertEqual("merl:qquote(\"{\", [{var, V}])", + f(merl_transform:parse_transform( + [?Q("merl:qquote(\"{\", [{var, V}])")], []))), + ?_assertEqual("merl:qquote(2, \"{\", [{var, V}])", + f(merl_transform:parse_transform( + [?Q("merl:qquote(2, \"{\", [{var, V}])")], []))) + ]. + term_test_() -> [?_assertEqual(tuple, erl_syntax:type(merl:term({}))), ?_assertEqual("{foo, 42}", f(merl:term({foo, 42}))) -- cgit v1.2.3