Fix #11515 internalAstError with chain of ternary operators (#4742)

This commit is contained in:
chrchr-github 2023-01-26 20:12:39 +01:00 committed by GitHub
parent c50339804b
commit 84fdc08853
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 129 additions and 57 deletions

View File

@ -42,7 +42,7 @@
// How many compileExpression recursions are allowed? // How many compileExpression recursions are allowed?
// For practical code this could be endless. But in some special torture test // For practical code this could be endless. But in some special torture test
// there needs to be a limit. // there needs to be a limit.
static const int AST_MAX_DEPTH = 100; static const int AST_MAX_DEPTH = 150;
TokenList::TokenList(const Settings* settings) : TokenList::TokenList(const Settings* settings) :
@ -739,6 +739,8 @@ static void compileBinOp(Token *&tok, AST_state& state, void (*f)(Token *&tok, A
state.depth++; state.depth++;
if (tok && state.depth <= AST_MAX_DEPTH) if (tok && state.depth <= AST_MAX_DEPTH)
f(tok, state); f(tok, state);
if (state.depth > AST_MAX_DEPTH)
throw InternalError(tok, "maximum AST depth exceeded", InternalError::AST);
state.depth--; state.depth--;
} }

View File

@ -6022,7 +6022,7 @@ private:
void astexpr2() { // limit for large expressions void astexpr2() { // limit for large expressions
// #7724 - wrong AST causes hang // #7724 - wrong AST causes hang
// Ideally a proper AST is created for this code. // Ideally a proper AST is created for this code.
const char code[] = "const char * a(int type) {\n" const char* code = "const char * a(int type) {\n"
" return (\n" " return (\n"
" (type == 1) ? \"\"\n" " (type == 1) ? \"\"\n"
" : (type == 2) ? \"\"\n" " : (type == 2) ? \"\"\n"
@ -6079,6 +6079,76 @@ private:
"}\n"; "}\n";
// Ensure that the AST is validated for the simplified token list // Ensure that the AST is validated for the simplified token list
TODO_ASSERT_THROW(tokenizeAndStringify(code), InternalError); // this should not crash/hang TODO_ASSERT_THROW(tokenizeAndStringify(code), InternalError); // this should not crash/hang
code = "template<uint64_t kInput>\n" // #11515
"struct ConstCTZ {\n"
" static constexpr uint32_t value =\n"
" (kInput & (uint64_t(1) << 0)) ? 0 :\n"
" (kInput & (uint64_t(1) << 1)) ? 1 :\n"
" (kInput & (uint64_t(1) << 2)) ? 2 :\n"
" (kInput & (uint64_t(1) << 3)) ? 3 :\n"
" (kInput & (uint64_t(1) << 4)) ? 4 :\n"
" (kInput & (uint64_t(1) << 5)) ? 5 :\n"
" (kInput & (uint64_t(1) << 6)) ? 6 :\n"
" (kInput & (uint64_t(1) << 7)) ? 7 :\n"
" (kInput & (uint64_t(1) << 8)) ? 8 :\n"
" (kInput & (uint64_t(1) << 9)) ? 9 :\n"
" (kInput & (uint64_t(1) << 10)) ? 10 :\n"
" (kInput & (uint64_t(1) << 11)) ? 11 :\n"
" (kInput & (uint64_t(1) << 12)) ? 12 :\n"
" (kInput & (uint64_t(1) << 13)) ? 13 :\n"
" (kInput & (uint64_t(1) << 14)) ? 14 :\n"
" (kInput & (uint64_t(1) << 15)) ? 15 :\n"
" (kInput & (uint64_t(1) << 16)) ? 16 :\n"
" (kInput & (uint64_t(1) << 17)) ? 17 :\n"
" (kInput & (uint64_t(1) << 18)) ? 18 :\n"
" (kInput & (uint64_t(1) << 19)) ? 19 :\n"
" (kInput & (uint64_t(1) << 20)) ? 20 :\n"
" (kInput & (uint64_t(1) << 21)) ? 21 :\n"
" (kInput & (uint64_t(1) << 22)) ? 22 :\n"
" (kInput & (uint64_t(1) << 23)) ? 23 :\n"
" (kInput & (uint64_t(1) << 24)) ? 24 :\n"
" (kInput & (uint64_t(1) << 25)) ? 25 :\n"
" (kInput & (uint64_t(1) << 26)) ? 26 :\n"
" (kInput & (uint64_t(1) << 27)) ? 27 :\n"
" (kInput & (uint64_t(1) << 28)) ? 28 :\n"
" (kInput & (uint64_t(1) << 29)) ? 29 :\n"
" (kInput & (uint64_t(1) << 30)) ? 30 :\n"
" (kInput & (uint64_t(1) << 31)) ? 31 :\n"
" (kInput & (uint64_t(1) << 32)) ? 32 :\n"
" (kInput & (uint64_t(1) << 33)) ? 33 :\n"
" (kInput & (uint64_t(1) << 34)) ? 34 :\n"
" (kInput & (uint64_t(1) << 35)) ? 35 :\n"
" (kInput & (uint64_t(1) << 36)) ? 36 :\n"
" (kInput & (uint64_t(1) << 37)) ? 37 :\n"
" (kInput & (uint64_t(1) << 38)) ? 38 :\n"
" (kInput & (uint64_t(1) << 39)) ? 39 :\n"
" (kInput & (uint64_t(1) << 40)) ? 40 :\n"
" (kInput & (uint64_t(1) << 41)) ? 41 :\n"
" (kInput & (uint64_t(1) << 42)) ? 42 :\n"
" (kInput & (uint64_t(1) << 43)) ? 43 :\n"
" (kInput & (uint64_t(1) << 44)) ? 44 :\n"
" (kInput & (uint64_t(1) << 45)) ? 45 :\n"
" (kInput & (uint64_t(1) << 46)) ? 46 :\n"
" (kInput & (uint64_t(1) << 47)) ? 47 :\n"
" (kInput & (uint64_t(1) << 48)) ? 48 :\n"
" (kInput & (uint64_t(1) << 49)) ? 49 :\n"
" (kInput & (uint64_t(1) << 50)) ? 50 :\n"
" (kInput & (uint64_t(1) << 51)) ? 51 :\n"
" (kInput & (uint64_t(1) << 52)) ? 52 :\n"
" (kInput & (uint64_t(1) << 53)) ? 53 :\n"
" (kInput & (uint64_t(1) << 54)) ? 54 :\n"
" (kInput & (uint64_t(1) << 55)) ? 55 :\n"
" (kInput & (uint64_t(1) << 56)) ? 56 :\n"
" (kInput & (uint64_t(1) << 57)) ? 57 :\n"
" (kInput & (uint64_t(1) << 58)) ? 58 :\n"
" (kInput & (uint64_t(1) << 59)) ? 59 :\n"
" (kInput & (uint64_t(1) << 60)) ? 60 :\n"
" (kInput & (uint64_t(1) << 61)) ? 61 :\n"
" (kInput & (uint64_t(1) << 62)) ? 62 :\n"
" (kInput & (uint64_t(1) << 63)) ? 63 : 64;\n"
"};\n";
ASSERT_NO_THROW(tokenizeAndStringify(code));
} }
void astnewdelete() { void astnewdelete() {
@ -6631,7 +6701,7 @@ private:
preprocessor.preprocess(fin, filedata, configurations, emptyString, settings0.includePaths); preprocessor.preprocess(fin, filedata, configurations, emptyString, settings0.includePaths);
const std::string code = preprocessor.getcode(filedata, emptyString, emptyString); const std::string code = preprocessor.getcode(filedata, emptyString, emptyString);
tokenizeAndStringify(code.c_str()); // just survive... ASSERT_THROW(tokenizeAndStringify(code.c_str()), InternalError);
} }
#define isStartOfExecutableScope(offset, code) isStartOfExecutableScope_(offset, code, __FILE__, __LINE__) #define isStartOfExecutableScope(offset, code) isStartOfExecutableScope_(offset, code, __FILE__, __LINE__)