Fix infinite loop when parsing "a="

Typing that command in an interactive prompt would make the highlighter thread
eat up CPU and memory.  Probably not the right fix; I think the token should
already have been consumed when the error is detected, then there is no need
to consume it when unwinding.
This commit is contained in:
Johannes Altmanninger 2020-07-05 13:11:49 +02:00
parent ada03d3509
commit 1ca05d32d3

View file

@ -749,6 +749,10 @@ class ast_t::populator_t {
return; return;
} }
// HACK We sometimes unwind after not consuming anything, for example on "a=".
// To avoid an infinite loop, remember the current token to be able to detect this case.
uint32_t first_token = peek_token().range().start;
for (;;) { for (;;) {
// If we are unwinding, then either we recover or we break the loop, dependent on the // If we are unwinding, then either we recover or we break the loop, dependent on the
// loop type. // loop type.
@ -756,12 +760,14 @@ class ast_t::populator_t {
if (!list_type_stops_unwind(ListType)) { if (!list_type_stops_unwind(ListType)) {
break; break;
} }
bool consume_first = peek_token().range().start == first_token;
// We are going to stop unwinding. // We are going to stop unwinding.
// Rather hackish. Just chomp until we get to a string or end node. // Rather hackish. Just chomp until we get to a string or end node.
for (auto type = peek_type(); for (auto type = peek_type();
type != parse_token_type_string && type != parse_token_type_terminate && (consume_first || type != parse_token_type_string) &&
type != parse_token_type_end; type != parse_token_type_terminate && type != parse_token_type_end;
type = peek_type()) { type = peek_type()) {
consume_first = false;
parse_token_t tok = tokens_.pop(); parse_token_t tok = tokens_.pop();
ast_->extras_.errors.push_back(tok.range()); ast_->extras_.errors.push_back(tok.range());
FLOGF(ast_construction, L"%*schomping range %u-%u", spaces(), "", FLOGF(ast_construction, L"%*schomping range %u-%u", spaces(), "",