diff options
author | Péter Gömöri <[email protected]> | 2016-07-09 17:21:27 +0200 |
---|---|---|
committer | Péter Gömöri <[email protected]> | 2016-07-09 17:21:27 +0200 |
commit | fee45935eb7f5a098cbbbaf1c8d1a8f9a77ce418 (patch) | |
tree | e5223681e9729194ed05c63eda92478a1c14d42d /lib/syntax_tools/test/merl_SUITE.erl | |
parent | ca4000874a198b218fd62b90e842475d2a0bb8c7 (diff) | |
download | otp-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/test/merl_SUITE.erl')
-rw-r--r-- | lib/syntax_tools/test/merl_SUITE.erl | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/lib/syntax_tools/test/merl_SUITE.erl b/lib/syntax_tools/test/merl_SUITE.erl index 945972d405..52bbd9b3b8 100644 --- a/lib/syntax_tools/test/merl_SUITE.erl +++ b/lib/syntax_tools/test/merl_SUITE.erl @@ -29,12 +29,14 @@ init_per_group/2,end_per_group/2]). %% Test cases --export([merl_smoke_test/1]). +-export([merl_smoke_test/1, + transform_parse_error_test/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [merl_smoke_test]. + [merl_smoke_test, + transform_parse_error_test]. groups() -> []. @@ -84,6 +86,21 @@ merl_smoke_test(Config) when is_list(Config) -> end)), ok. +transform_parse_error_test(_Config) -> + ?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}])")], []))), + ok. + %% utilities f(Ts) when is_list(Ts) -> |