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:
Родитель
e4cfa190df
Коммит
388ce0ee64
|
@ -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.
|
// parameters, its the users responsibility to ensure these are non null.
|
||||||
spv_result_t advance(spv_text text, spv_position position) {
|
spv_result_t advance(spv_text text, spv_position position) {
|
||||||
// NOTE: Consume white space, otherwise don't advance.
|
// NOTE: Consume white space, otherwise don't advance.
|
||||||
if (position->index >= text->length) return SPV_END_OF_STREAM;
|
while (true) {
|
||||||
switch (text->str[position->index]) {
|
if (position->index >= text->length) return SPV_END_OF_STREAM;
|
||||||
case '\0':
|
switch (text->str[position->index]) {
|
||||||
return SPV_END_OF_STREAM;
|
case '\0':
|
||||||
case ';':
|
return SPV_END_OF_STREAM;
|
||||||
if (spv_result_t error = advanceLine(text, position)) return error;
|
case ';':
|
||||||
return advance(text, position);
|
if (spv_result_t error = advanceLine(text, position)) return error;
|
||||||
case ' ':
|
continue;
|
||||||
case '\t':
|
case ' ':
|
||||||
case '\r':
|
case '\t':
|
||||||
position->column++;
|
case '\r':
|
||||||
position->index++;
|
position->column++;
|
||||||
return advance(text, position);
|
position->index++;
|
||||||
case '\n':
|
continue;
|
||||||
position->column = 0;
|
case '\n':
|
||||||
position->line++;
|
position->column = 0;
|
||||||
position->index++;
|
position->line++;
|
||||||
return advance(text, position);
|
position->index++;
|
||||||
default:
|
continue;
|
||||||
break;
|
default:
|
||||||
|
return SPV_SUCCESS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return SPV_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetches the next word from the given text stream starting from the given
|
// Fetches the next word from the given text stream starting from the given
|
||||||
|
|
|
@ -130,5 +130,14 @@ TEST(TextAdvance, SkipOverCRLFs) {
|
||||||
EXPECT_EQ(2u, pos.line);
|
EXPECT_EQ(2u, pos.line);
|
||||||
EXPECT_EQ(4u, pos.index);
|
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
|
||||||
} // namespace spvtools
|
} // namespace spvtools
|
||||||
|
|
Загрузка…
Ссылка в новой задаче