From 36eef302c0b8ecb992c5d4b01562bcaef543b6fc Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Tue, 13 Aug 2013 13:32:27 +0200 Subject: [PATCH] Genex: Fix segfault when parsing ends with parameter expectation. The extendResult method expects a non-empty parameters vector, as assured by the normal case. Avoid calling the method when the parser finds an incomplete generator expression, but has already entered the state of expecting to find parameters. --- Source/cmGeneratorExpressionParser.cxx | 20 +++++++++++++++++++- Tests/GeneratorExpression/CMakeLists.txt | 2 ++ Tests/GeneratorExpression/check-part3.cmake | 2 ++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/Source/cmGeneratorExpressionParser.cxx b/Source/cmGeneratorExpressionParser.cxx index a619cecd0..e1fb8f1de 100644 --- a/Source/cmGeneratorExpressionParser.cxx +++ b/Source/cmGeneratorExpressionParser.cxx @@ -126,6 +126,9 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression( std::vector::const_iterator> commaTokens; std::vector::const_iterator colonToken; + + bool emptyParamTermination = false; + if (this->it != this->Tokens.end() && this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator) { @@ -133,6 +136,10 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression( parameters.resize(parameters.size() + 1); assert(this->it != this->Tokens.end()); ++this->it; + if(this->it == this->Tokens.end()) + { + emptyParamTermination = true; + } while (this->it != this->Tokens.end() && this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator) @@ -141,6 +148,10 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression( parameters.resize(parameters.size() + 1); assert(this->it != this->Tokens.end()); ++this->it; + if(this->it == this->Tokens.end()) + { + emptyParamTermination = true; + } } while (this->it != this->Tokens.end() && this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator) @@ -164,6 +175,10 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression( parameters.resize(parameters.size() + 1); assert(this->it != this->Tokens.end()); ++this->it; + if(this->it == this->Tokens.end()) + { + emptyParamTermination = true; + } } while (this->it != this->Tokens.end() && this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator) @@ -203,7 +218,10 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression( assert(parameters.size() > commaTokens.size()); for ( ; pit != pend; ++pit, ++commaIt) { - extendResult(result, *pit); + if (!pit->empty() && !emptyParamTermination) + { + extendResult(result, *pit); + } if (commaIt != commaTokens.end()) { extendText(result, *commaIt); diff --git a/Tests/GeneratorExpression/CMakeLists.txt b/Tests/GeneratorExpression/CMakeLists.txt index 9ee4fc5d3..4d8d7ed25 100644 --- a/Tests/GeneratorExpression/CMakeLists.txt +++ b/Tests/GeneratorExpression/CMakeLists.txt @@ -184,6 +184,8 @@ add_custom_target(check-part3 ALL -Dtest_alias_file_exe=$,$> -Dtest_alias_file_lib=$,$> -Dtest_alias_target_name=$,$> + -Dtest_early_termination_1=$<$<1:>: + -Dtest_early_termination_2=$<$<1:>:, -P ${CMAKE_CURRENT_SOURCE_DIR}/check-part3.cmake COMMAND ${CMAKE_COMMAND} -E echo "check done (part 3 of 3)" VERBATIM diff --git a/Tests/GeneratorExpression/check-part3.cmake b/Tests/GeneratorExpression/check-part3.cmake index 5a6a441a0..74a596c3a 100644 --- a/Tests/GeneratorExpression/check-part3.cmake +++ b/Tests/GeneratorExpression/check-part3.cmake @@ -24,3 +24,5 @@ endforeach() check(test_alias_file_exe "1") check(test_alias_file_lib "1") check(test_alias_target_name "1") +check(test_early_termination_1 "$<:") +check(test_early_termination_2 "$<:,")