Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/KhronosGroup/SPIRV-Tools.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlastair Donaldson <alastair.donaldson@imperial.ac.uk>2022-07-26 17:56:04 +0300
committerGitHub <noreply@github.com>2022-07-26 17:56:04 +0300
commit388ce0ee64b393c02843fb7469647069c89ab5da (patch)
tree17d2c0d0cabe1c8629b807590c4ea61712321213
parente4cfa190dfa144f1db5bcca2a6b11a6ba429824d (diff)
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.
-rw-r--r--source/text_handler.cpp43
-rw-r--r--test/text_advance_test.cpp9
2 files changed, 31 insertions, 21 deletions
diff --git a/source/text_handler.cpp b/source/text_handler.cpp
index fe12a26e3..15c1741f6 100644
--- a/source/text_handler.cpp
+++ b/source/text_handler.cpp
@@ -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
diff --git a/test/text_advance_test.cpp b/test/text_advance_test.cpp
index 9de77a836..0d23ab1c1 100644
--- a/test/text_advance_test.cpp
+++ b/test/text_advance_test.cpp
@@ -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