preprocessor: Fix negative shift with bad ids.
Fix this by producing an error on undefined or negative shifts.
BUG=629518
Change-Id: Idfca5ed3fc8e557f6178408f3426a5ef2ce7cf14
Reviewed-on: https://chromium-review.googlesource.com/362020
Reviewed-by: Antoine Labour <piman@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
diff --git a/src/compiler/preprocessor/DiagnosticsBase.cpp b/src/compiler/preprocessor/DiagnosticsBase.cpp
index 68c6e9c..9f62a9e 100644
--- a/src/compiler/preprocessor/DiagnosticsBase.cpp
+++ b/src/compiler/preprocessor/DiagnosticsBase.cpp
@@ -115,6 +115,8 @@
return "invalid line directive";
case PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL3:
return "extension directive must occur before any non-preprocessor tokens in ESSL3";
+ case PP_UNDEFINED_SHIFT:
+ return "shift exponent is negative or undefined";
// Errors end.
// Warnings begin.
case PP_EOF_IN_DIRECTIVE:
diff --git a/src/compiler/preprocessor/DiagnosticsBase.h b/src/compiler/preprocessor/DiagnosticsBase.h
index d26c174..a089920 100644
--- a/src/compiler/preprocessor/DiagnosticsBase.h
+++ b/src/compiler/preprocessor/DiagnosticsBase.h
@@ -65,6 +65,7 @@
PP_INVALID_FILE_NUMBER,
PP_INVALID_LINE_DIRECTIVE,
PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL3,
+ PP_UNDEFINED_SHIFT,
PP_ERROR_END,
PP_WARNING_BEGIN,
diff --git a/src/compiler/preprocessor/ExpressionParser.cpp b/src/compiler/preprocessor/ExpressionParser.cpp
index 193b150..b765c64 100644
--- a/src/compiler/preprocessor/ExpressionParser.cpp
+++ b/src/compiler/preprocessor/ExpressionParser.cpp
@@ -498,12 +498,9 @@
#if YYDEBUG
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
-static const yytype_uint16 yyrline[] =
-{
- 0, 110, 110, 117, 118, 129, 129, 150, 150, 171,
- 174, 177, 180, 183, 186, 189, 192, 195, 198, 201,
- 204, 207, 210, 230, 250, 253, 256, 259, 262, 265
-};
+static const yytype_uint16 yyrline[] = {0, 110, 110, 117, 118, 129, 129, 150, 150, 171,
+ 174, 177, 180, 183, 186, 189, 192, 195, 198, 218,
+ 238, 241, 244, 264, 284, 287, 290, 293, 296, 299};
#endif
#if YYDEBUG || YYERROR_VERBOSE || 0
@@ -1495,7 +1492,23 @@
case 18:
{
- (yyval) = (yyvsp[-2]) >> (yyvsp[0]);
+ if ((yyvsp[0]) < 0)
+ {
+ if (!context->isIgnoringErrors())
+ {
+ std::ostringstream stream;
+ stream << (yyvsp[-2]) << " >> " << (yyvsp[0]);
+ std::string text = stream.str();
+ context->diagnostics->report(pp::Diagnostics::PP_UNDEFINED_SHIFT,
+ context->token->location, text.c_str());
+ *(context->valid) = false;
+ }
+ (yyval) = static_cast<YYSTYPE>(0);
+ }
+ else
+ {
+ (yyval) = (yyvsp[-2]) >> (yyvsp[0]);
+ }
}
break;
@@ -1503,7 +1516,23 @@
case 19:
{
- (yyval) = (yyvsp[-2]) << (yyvsp[0]);
+ if ((yyvsp[0]) < 0)
+ {
+ if (!context->isIgnoringErrors())
+ {
+ std::ostringstream stream;
+ stream << (yyvsp[-2]) << " << " << (yyvsp[0]);
+ std::string text = stream.str();
+ context->diagnostics->report(pp::Diagnostics::PP_UNDEFINED_SHIFT,
+ context->token->location, text.c_str());
+ *(context->valid) = false;
+ }
+ (yyval) = static_cast<YYSTYPE>(0);
+ }
+ else
+ {
+ (yyval) = (yyvsp[-2]) << (yyvsp[0]);
+ }
}
break;
diff --git a/src/compiler/preprocessor/ExpressionParser.y b/src/compiler/preprocessor/ExpressionParser.y
index 7b5d9e9..dc0080e 100644
--- a/src/compiler/preprocessor/ExpressionParser.y
+++ b/src/compiler/preprocessor/ExpressionParser.y
@@ -196,10 +196,44 @@
$$ = $1 < $3;
}
| expression TOK_OP_RIGHT expression {
- $$ = $1 >> $3;
+ if ($3 < 0)
+ {
+ if (!context->isIgnoringErrors())
+ {
+ std::ostringstream stream;
+ stream << $1 << " >> " << $3;
+ std::string text = stream.str();
+ context->diagnostics->report(pp::Diagnostics::PP_UNDEFINED_SHIFT,
+ context->token->location,
+ text.c_str());
+ *(context->valid) = false;
+ }
+ $$ = static_cast<YYSTYPE>(0);
+ }
+ else
+ {
+ $$ = $1 >> $3;
+ }
}
| expression TOK_OP_LEFT expression {
- $$ = $1 << $3;
+ if ($3 < 0)
+ {
+ if (!context->isIgnoringErrors())
+ {
+ std::ostringstream stream;
+ stream << $1 << " << " << $3;
+ std::string text = stream.str();
+ context->diagnostics->report(pp::Diagnostics::PP_UNDEFINED_SHIFT,
+ context->token->location,
+ text.c_str());
+ *(context->valid) = false;
+ }
+ $$ = static_cast<YYSTYPE>(0);
+ }
+ else
+ {
+ $$ = $1 << $3;
+ }
}
| expression '-' expression {
$$ = $1 - $3;
diff --git a/src/tests/compiler_tests/MalformedShader_test.cpp b/src/tests/compiler_tests/MalformedShader_test.cpp
index 96d0778..64980d7 100644
--- a/src/tests/compiler_tests/MalformedShader_test.cpp
+++ b/src/tests/compiler_tests/MalformedShader_test.cpp
@@ -1635,3 +1635,23 @@
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
+
+// Covers a bug in our parsing of malformed shift preprocessor expressions.
+TEST_F(MalformedShaderTest, LineDirectiveUndefinedShift)
+{
+ const std::string &shaderString = "#line x << y";
+ if (compile(shaderString))
+ {
+ FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+ }
+}
+
+// Covers a bug in our parsing of malformed shift preprocessor expressions.
+TEST_F(MalformedShaderTest, LineDirectiveNegativeShift)
+{
+ const std::string &shaderString = "#line x << -1";
+ if (compile(shaderString))
+ {
+ FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+ }
+}
diff --git a/src/tests/preprocessor_tests/define_test.cpp b/src/tests/preprocessor_tests/define_test.cpp
index c4529a0..b95a6b4 100644
--- a/src/tests/preprocessor_tests/define_test.cpp
+++ b/src/tests/preprocessor_tests/define_test.cpp
@@ -7,6 +7,8 @@
#include "PreprocessorTest.h"
#include "compiler/preprocessor/Token.h"
+using testing::_;
+
class DefineTest : public PreprocessorTest
{
};
@@ -918,3 +920,22 @@
"defined(bar)\n";
preprocess(input, expected);
}
+
+// Test that line directive expressions give errors on negative or undefined shifts.
+TEST_F(DefineTest, NegativeShiftInLineDirective)
+{
+ const char *input =
+ "#line 1 << -1\n"
+ "#line 1 >> -1\n"
+ "#line 1 << x\n"
+ "#line 1 >> x\n";
+ const char *expected =
+ "\n"
+ "\n"
+ "\n"
+ "\n";
+
+ EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_UNDEFINED_SHIFT, _, _)).Times(4);
+ EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_INVALID_LINE_NUMBER, _, _)).Times(2);
+ preprocess(input, expected);
+}
\ No newline at end of file