From 96cdb4549b59040ccb6f2bd7a4cc34076459a8ed Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Sat, 17 Oct 2026 11:34:26 +0200 Subject: [PATCH] compiler: fix endless loop on syntax errors in template placeholders When the expression within a template literal placeholder is cut short by a syntax error, e.g. `${ 1 2 }`, or by the end of the source, the statement end marker of the placeholder expression has already advanced the source position beyond the last token of the expression when the instruction storing the result is emitted for that token. Since source positions are encoded as unsigned deltas, the position going backwards turned into an enormous offset which uc_chunk_add() spent nearly forever and a lot of memory on, as the assertion guarding the invariant is compiled out in release builds. Tolerate positions in front of the current one once a syntax error has occurred, the generated code is discarded anyway. Signed-off-by: Jo-Philipp Wich --- compiler.c | 10 +++- .../60_template_placeholder_syntax_error_hang | 49 +++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 tests/custom/99_bugs/60_template_placeholder_syntax_error_hang diff --git a/compiler.c b/compiler.c index ee70961c..46e07622 100644 --- a/compiler.c +++ b/compiler.c @@ -237,7 +237,15 @@ uc_compiler_set_srcpos(uc_compiler_t *compiler, size_t srcpos) size_t delta; /* ensure that lines counts are strictly increasing */ - assert(srcpos == 0 || srcpos >= compiler->current_srcpos); + assert(srcpos == 0 || srcpos >= compiler->current_srcpos || + compiler->parser->error); + + /* after a syntax error, code may be emitted for tokens in front of the + * current position, e.g. after the expression of a template literal + * placeholder has been terminated prematurely. The generated code is + * discarded, but a negative offset would be taken for an enormous one */ + if (srcpos < compiler->current_srcpos) + srcpos = 0; delta = srcpos ? srcpos - compiler->current_srcpos : 0; compiler->current_srcpos += delta; diff --git a/tests/custom/99_bugs/60_template_placeholder_syntax_error_hang b/tests/custom/99_bugs/60_template_placeholder_syntax_error_hang new file mode 100644 index 00000000..842402ed --- /dev/null +++ b/tests/custom/99_bugs/60_template_placeholder_syntax_error_hang @@ -0,0 +1,49 @@ +A syntax error within the expression of a template literal placeholder +made the compiler spin until it ran out of memory. The statement +terminating the placeholder expression had advanced the source position +beyond the last token of the expression, and instructions emitted for +that token afterwards moved the position backwards. The negative offset +was taken for an enormous one when recording the source position of the +instruction, which then took practically forever and a lot of memory. + +1. Excess token in a placeholder. + +-- Testcase -- +x = `a${ 1 2 }`; +-- End -- + +-- Args -- +-R +-- End -- + +-- Expect stderr -- +Syntax error: Unexpected token +Expecting '}' +In line 1, byte 12: + + `x = `a${ 1 2 }`;` + ~~~~~~~~~~~^ + + +-- End -- + + +2. Unterminated placeholder at the end of the source. + +-- Testcase -- +x = `tpl${ +-- End -- + +-- Args -- +-R +-- End -- + +-- Expect stderr -- +Syntax error: Expecting expression +In line 2, byte 1: + + `x = `tpl${` + ^-- Near here + + +-- End --