cmGeneratorExpressionEvalFuzzer: Fix crash on unclosed genex

When an expression is never closed, `extendResult` called `.front()`
without checking whether the `contents` vector was empty.

The previous check using `emptyParamTermination` was an attempt at
addressing such a case, but obviously had a gap. Since the new approach
covers this, it can be dropped.
This commit is contained in:
Tyler Yankee committed 2026-10-26 15:48:49 -04:00
1 parent 2f0da06e90
commit d7a9711b4f
3 files changed
+9 -14

No files matched your search

+3 -14
View File
@@ -48,7 +48,7 @@ static void extendResult(
cmGeneratorExpressionParser::cmGeneratorExpressionEvaluatorVector& result,
cmGeneratorExpressionParser::cmGeneratorExpressionEvaluatorVector&& contents)
{
if (!result.empty() &&
if (!result.empty() && !contents.empty() &&
(*(result.end() - 1))->GetType() ==
cmGeneratorExpressionEvaluator::Text &&
contents.front()->GetType() == cmGeneratorExpressionEvaluator::Text) {
@@ -101,28 +101,19 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression(
commaTokens;
std::vector<cmGeneratorExpressionToken>::const_iterator colonToken;
bool emptyParamTermination = false;
if (this->it != this->Tokens.end() &&
this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator) {
colonToken = this->it;
parameters.resize(parameters.size() + 1);
assert(this->it != this->Tokens.end());
++this->it;
if (this->it == this->Tokens.end()) {
emptyParamTermination = true;
}
auto handleCommaOrColon = [this, &commaTokens, &parameters,
&emptyParamTermination]() -> void {
auto handleCommaOrColon = [this, &commaTokens, &parameters]() -> void {
if (this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator) {
commaTokens.push_back(this->it);
parameters.resize(parameters.size() + 1);
assert(this->it != this->Tokens.end());
++this->it;
if (this->it == this->Tokens.end()) {
emptyParamTermination = true;
}
} else if (this->it->TokenType ==
cmGeneratorExpressionToken::ColonSeparator) {
extendText(*(parameters.end() - 1), this->it);
@@ -172,9 +163,7 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression(
auto commaIt = commaTokens.begin();
assert(parameters.size() > commaTokens.size());
for (; pit != pend; ++pit, ++commaIt) {
if (!pit->empty() && !emptyParamTermination) {
extendResult(result, std::move(*pit));
}
extendResult(result, std::move(*pit));
if (commaIt != commaTokens.end()) {
extendText(result, *commaIt);
} else {
+3
View File
@@ -146,6 +146,9 @@ add_custom_target(check-part2 ALL
-Dtest_incomplete_21=$<BOOL:something$<ANGLE-R>
-Dtest_incomplete_22=$<1:a>$<
-Dtest_incomplete_23=$<1:a>$<1:$<
-Dtest_incomplete_24=$<1:a>$<:x
-Dtest_incomplete_25=$<1:a>$<x:y,
-Dtest_incomplete_26=$<1:a>$<x:y,z,
-Dtest_build_interface=$<BUILD_INTERFACE:build>
-Dtest_install_interface=$<INSTALL_INTERFACE:install>
-Dtest_target_name_1=$<TARGET_NAME:tgt,ok>
@@ -24,6 +24,9 @@ check(test_incomplete_20 "$<CONFIGURATION>")
check(test_incomplete_21 "$<BOOL:something>")
check(test_incomplete_22 "a$<")
check(test_incomplete_23 "a$<1:$<")
check(test_incomplete_24 "a$<:x")
check(test_incomplete_25 "a$<x:y,")
check(test_incomplete_26 "a$<x:y,z,")
check(test_build_interface "build")
check(test_install_interface "")
check(test_target_name_1 "tgt,ok")