spirv-as: Avoid recursion when skipping whitespace (#4866)

Excessive whitespace can lead to stack overflow during parsing as each
character of skipped whitespace involves a recursive call. An
iterative solution avoids this.

Fixes #4729.
This commit is contained in:
Alastair Donaldson 2022-07-26 15:56:04 +01:00 committed by GitHub
parent e4cfa190df
commit 388ce0ee64
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 21 deletions

View File

@ -62,28 +62,29 @@ spv_result_t advanceLine(spv_text text, spv_position position) {
// parameters, its the users responsibility to ensure these are non null.
spv_result_t advance(spv_text text, spv_position position) {
// NOTE: Consume white space, otherwise don't advance.
if (position->index >= text->length) return SPV_END_OF_STREAM;
switch (text->str[position->index]) {
case '\0':
return SPV_END_OF_STREAM;
case ';':
if (spv_result_t error = advanceLine(text, position)) return error;
return advance(text, position);
case ' ':
case '\t':
case '\r':
position->column++;
position->index++;
return advance(text, position);
case '\n':
position->column = 0;
position->line++;
position->index++;
return advance(text, position);
default:
break;
while (true) {
if (position->index >= text->length) return SPV_END_OF_STREAM;
switch (text->str[position->index]) {
case '\0':
return SPV_END_OF_STREAM;
case ';':
if (spv_result_t error = advanceLine(text, position)) return error;
continue;
case ' ':
case '\t':
case '\r':
position->column++;
position->index++;
continue;
case '\n':
position->column = 0;
position->line++;
position->index++;
continue;
default:
return SPV_SUCCESS;
}
}
return SPV_SUCCESS;
}
// Fetches the next word from the given text stream starting from the given

View File

@ -130,5 +130,14 @@ TEST(TextAdvance, SkipOverCRLFs) {
EXPECT_EQ(2u, pos.line);
EXPECT_EQ(4u, pos.index);
}
TEST(TextAdvance, HandleLotsOfWhitespace) {
std::string lots_of_spaces(10000, ' ');
lots_of_spaces += "Word";
const auto pos = PositionAfterAdvance(lots_of_spaces.c_str());
EXPECT_EQ(10000u, pos.column);
EXPECT_EQ(0u, pos.line);
EXPECT_EQ(10000u, pos.index);
}
} // namespace
} // namespace spvtools