Skip to content

Commit 2a05c59

Browse files
authored
Fix a problem where having duplicated blocks could result in endless recursion (#55)
1 parent e992412 commit 2a05c59

File tree

3 files changed

+51
-8
lines changed

3 files changed

+51
-8
lines changed

src/template_compiler.erl

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -423,18 +423,33 @@ cs(Module, Filename, Options, Context) ->
423423

424424
compile_tokens({ok, {extends, {string_literal, _, Extend}, Elements}}, CState, _Options) ->
425425
Blocks = find_blocks(Elements),
426-
{Ws, BlockAsts} = compile_blocks(Blocks, CState),
427-
{ok, {Extend, Ws#ws.includes, BlockAsts, undefined, Ws#ws.is_autoid_var}};
426+
case check_duplicate_blocks(Blocks) of
427+
ok ->
428+
{Ws, BlockAsts} = compile_blocks(Blocks, CState),
429+
{ok, {Extend, Ws#ws.includes, BlockAsts, undefined, Ws#ws.is_autoid_var}};
430+
{error, _} = Error ->
431+
Error
432+
end;
428433
compile_tokens({ok, {overrules, Elements}}, CState, _Options) ->
429434
Blocks = find_blocks(Elements),
430-
{Ws, BlockAsts} = compile_blocks(Blocks, CState),
431-
{ok, {overrules, Ws#ws.includes, BlockAsts, undefined, Ws#ws.is_autoid_var}};
435+
case check_duplicate_blocks(Blocks) of
436+
ok ->
437+
{Ws, BlockAsts} = compile_blocks(Blocks, CState),
438+
{ok, {overrules, Ws#ws.includes, BlockAsts, undefined, Ws#ws.is_autoid_var}};
439+
{error, _} = Error ->
440+
Error
441+
end;
432442
compile_tokens({ok, {base, Elements}}, CState, _Options) ->
433443
Blocks = find_blocks(Elements),
434-
{Ws, BlockAsts} = compile_blocks(Blocks, CState),
435-
CStateElts = CState#cs{blocks = BlockAsts},
436-
{Ws1, TemplateAsts} = template_compiler_element:compile(Elements, CStateElts, Ws),
437-
{ok, {undefined, Ws1#ws.includes, BlockAsts, TemplateAsts, Ws1#ws.is_autoid_var}};
444+
case check_duplicate_blocks(Blocks) of
445+
ok ->
446+
{Ws, BlockAsts} = compile_blocks(Blocks, CState),
447+
CStateElts = CState#cs{blocks = BlockAsts},
448+
{Ws1, TemplateAsts} = template_compiler_element:compile(Elements, CStateElts, Ws),
449+
{ok, {undefined, Ws1#ws.includes, BlockAsts, TemplateAsts, Ws1#ws.is_autoid_var}};
450+
{error, _} = Error ->
451+
Error
452+
end;
438453
compile_tokens({error, {Loc, template_compiler_parser, Msg}}, #cs{ filename = Filename }, Options) ->
439454
% Try format the Yecc error
440455
Err = split_loc(Loc),
@@ -522,6 +537,20 @@ block_elements({filter, _, Elts}) -> Elts;
522537
block_elements(_) -> [].
523538

524539

540+
check_duplicate_blocks(Blocks) ->
541+
check_duplicate_blocks_1(Blocks, #{}).
542+
543+
check_duplicate_blocks_1([], _Acc) ->
544+
ok;
545+
check_duplicate_blocks_1([{block, {identifier, _Pos, Name}, _Elements}|Blocks], Acc) ->
546+
case maps:is_key(Name, Acc) of
547+
true ->
548+
{error, {duplicate_block, Name}};
549+
false ->
550+
check_duplicate_blocks_1(Blocks, Acc#{ Name => true })
551+
end.
552+
553+
525554
%% @doc Optionally drop text before {% extends %} or {% overrules %}.
526555
maybe_drop_text([{text, _SrcRef, _Text}|Rest], OrgTks) ->
527556
maybe_drop_text(Rest, OrgTks);

test/template_compiler_basic_SUITE.erl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ groups() ->
2323
,hello_world_block2_test
2424
,hello_world_block3_test
2525
,hello_world_comment_test
26+
,block_nested_error_test
2627
,block_render_test
2728
,raw_test
2829
]}].
@@ -72,6 +73,10 @@ hello_world_comment_test(_Config) ->
7273
<<"Hello World!">> = iolist_to_binary(Bin),
7374
ok.
7475

76+
block_nested_error_test(_Config) ->
77+
{error, {duplicate_block, <<"main">>}} = template_compiler:render("block_nested_error.tpl", #{}, [], undefined),
78+
ok.
79+
7580
block_render_test(_Config) ->
7681
{ok, BinA} = template_compiler:render_block(a, "block_render.tpl", #{}, [], undefined),
7782
<<"A">> = iolist_to_binary(BinA),
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{% block main %}
2+
Hallo
3+
{% block test %}
4+
Daar
5+
{% block main %}
6+
oops - a block with the same name
7+
{% endblock %}
8+
{% endblock %}
9+
{% endblock%}

0 commit comments

Comments
 (0)