From c8d22e321bf679505bfd9e2bcdeb8fac5083bd5f Mon Sep 17 00:00:00 2001 From: Nicolas Hake Date: Sun, 17 Feb 2019 11:34:35 +0100 Subject: [PATCH 1/2] Aul: Throw correct exception on parameter-less warning pragma When no parameter followed the "#warning" pragma, because the end iterator would be located before the begin iterator, basic_string's constructor would throw std::length_error. Check for this case beforehand so we can throw the expected C4ParseError instead. --- src/script/C4AulParse.cpp | 9 +++------ tests/aul/AulSyntaxTest.cpp | 8 ++++++++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/script/C4AulParse.cpp b/src/script/C4AulParse.cpp index a7f5c4f7a..42a22138c 100644 --- a/src/script/C4AulParse.cpp +++ b/src/script/C4AulParse.cpp @@ -778,12 +778,9 @@ void C4AulParse::UnexpectedToken(const char * Expected) void C4AulParse::Parse_WarningPragma() { assert(SEqual2(TokenSPos, C4AUL_Warning)); - assert(std::isspace(TokenSPos[sizeof(C4AUL_Warning) - 1])); - - - // Read parameters in to string buffer. The sizeof() includes the terminating \0, but - // that's okay because we need to skip (at least) one whitespace character anyway. - std::string line(TokenSPos + sizeof(C4AUL_Warning), SPos); + + // Read parameters in to string buffer. + std::string line(TokenSPos + sizeof(C4AUL_Warning) - 1, SPos); auto end = line.end(); auto cursor = std::find_if_not(begin(line), end, IsWhiteSpace); diff --git a/tests/aul/AulSyntaxTest.cpp b/tests/aul/AulSyntaxTest.cpp index 52d7d445c..7dab56a92 100644 --- a/tests/aul/AulSyntaxTest.cpp +++ b/tests/aul/AulSyntaxTest.cpp @@ -88,6 +88,14 @@ TEST(AulSyntaxTest, ParseSyntaxErrors) EXPECT_THROW(ParseStatement("func Main() {}"), C4AulParseError); } +TEST(AulSyntaxTest, PragmaWarningWithInsufficientData) +{ + EXPECT_THROW(ParseScript("#warning"), C4AulParseError); + EXPECT_THROW(ParseScript("#warning\n"), C4AulParseError); + EXPECT_THROW(ParseScript("#warning "), C4AulParseError); + EXPECT_THROW(ParseScript("#warning \n"), C4AulParseError); +} + using namespace ::aul::ast; TEST(AulSyntaxTest, ParseLiterals) { From a0c9bfd931e42ab6ef95e12b24be1d072cf5b3a6 Mon Sep 17 00:00:00 2001 From: Nicolas Hake Date: Sun, 17 Feb 2019 11:37:25 +0100 Subject: [PATCH 2/2] Aul: Correctly check for enable/disable keywords in warning pragma The parser was only checking that the passed setting matched the beginning of the expected keyword, instead of checking for the full length. This way, users could write "#warning e" instead of the expected "#warning enable" and still have it work. --- src/script/C4AulParse.cpp | 4 ++-- tests/aul/AulSyntaxTest.cpp | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/script/C4AulParse.cpp b/src/script/C4AulParse.cpp index 42a22138c..3071709a8 100644 --- a/src/script/C4AulParse.cpp +++ b/src/script/C4AulParse.cpp @@ -791,11 +791,11 @@ void C4AulParse::Parse_WarningPragma() auto start = cursor; cursor = std::find_if(start, end, IsWhiteSpace); bool enable_warning = false; - if (std::equal(start, cursor, C4Aul_Warning_enable)) + if (cursor - start == sizeof(C4Aul_Warning_enable) - 1 && std::equal(start, cursor, C4Aul_Warning_enable)) { enable_warning = true; } - else if (std::equal(start, cursor, C4Aul_Warning_disable)) + else if (cursor - start == sizeof(C4Aul_Warning_disable) - 1 && std::equal(start, cursor, C4Aul_Warning_disable)) { enable_warning = false; } diff --git a/tests/aul/AulSyntaxTest.cpp b/tests/aul/AulSyntaxTest.cpp index 7dab56a92..fecfa48dc 100644 --- a/tests/aul/AulSyntaxTest.cpp +++ b/tests/aul/AulSyntaxTest.cpp @@ -94,6 +94,10 @@ TEST(AulSyntaxTest, PragmaWarningWithInsufficientData) EXPECT_THROW(ParseScript("#warning\n"), C4AulParseError); EXPECT_THROW(ParseScript("#warning "), C4AulParseError); EXPECT_THROW(ParseScript("#warning \n"), C4AulParseError); + EXPECT_THROW(ParseScript("#warning e"), C4AulParseError); + EXPECT_THROW(ParseScript("#warning enabl"), C4AulParseError); + EXPECT_THROW(ParseScript("#warning d"), C4AulParseError); + EXPECT_THROW(ParseScript("#warning disabl"), C4AulParseError); } using namespace ::aul::ast;