preprocessor: Fix lineno overflow on line continuations

BUG=chromium:774807

Change-Id: I4b3fbee31683f411810080572cfff0f8307b93bf
Reviewed-on: https://chromium-review.googlesource.com/744183
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/compiler/preprocessor/DiagnosticsBase.cpp b/src/compiler/preprocessor/DiagnosticsBase.cpp
index 1b9575b..c89bc9f 100644
--- a/src/compiler/preprocessor/DiagnosticsBase.cpp
+++ b/src/compiler/preprocessor/DiagnosticsBase.cpp
@@ -118,6 +118,8 @@
             return "extension directive must occur before any non-preprocessor tokens in ESSL3";
         case PP_UNDEFINED_SHIFT:
             return "shift exponent is negative or undefined";
+        case PP_TOKENIZER_ERROR:
+            return "internal tokenizer error";
         // Errors end.
         // Warnings begin.
         case PP_EOF_IN_DIRECTIVE:
diff --git a/src/compiler/preprocessor/Input.cpp b/src/compiler/preprocessor/Input.cpp
index e5bcd8e..3a473f7 100644
--- a/src/compiler/preprocessor/Input.cpp
+++ b/src/compiler/preprocessor/Input.cpp
@@ -61,6 +61,11 @@
             {
                 // Line continuation of backslash + newline.
                 skipChar();
+                // Fake an EOF if the line number would overflow.
+                if (*lineNo == INT_MAX)
+                {
+                    return 0;
+                }
                 ++(*lineNo);
             }
             else if (c != nullptr && (*c) == '\r')
@@ -71,6 +76,11 @@
                 {
                     skipChar();
                 }
+                // Fake an EOF if the line number would overflow.
+                if (*lineNo == INT_MAX)
+                {
+                    return 0;
+                }
                 ++(*lineNo);
             }
             else
diff --git a/src/compiler/preprocessor/Tokenizer.cpp b/src/compiler/preprocessor/Tokenizer.cpp
index 76b376b..d8a9b9a 100644
--- a/src/compiler/preprocessor/Tokenizer.cpp
+++ b/src/compiler/preprocessor/Tokenizer.cpp
@@ -1680,11 +1680,18 @@
     yylloc->line = yylineno;
     yylval->clear();
 
-    if (YY_START == COMMENT)
+    // Line number overflows fake EOFs to exit early, check for this case.
+    if (yylineno == INT_MAX)
+    {
+        yyextra->diagnostics->report(pp::Diagnostics::PP_TOKENIZER_ERROR,
+                                     pp::SourceLocation(yyfileno, yylineno),
+                                     "Integer overflow on line number");
+    }
+    else if (YY_START == COMMENT)
     {
         yyextra->diagnostics->report(pp::Diagnostics::PP_EOF_IN_COMMENT,
                                      pp::SourceLocation(yyfileno, yylineno),
-                                     "");
+                                     "EOF while in a comment");
     }
     yyterminate();
 }
diff --git a/src/compiler/preprocessor/Tokenizer.l b/src/compiler/preprocessor/Tokenizer.l
index 564f580..096812d 100644
--- a/src/compiler/preprocessor/Tokenizer.l
+++ b/src/compiler/preprocessor/Tokenizer.l
@@ -277,11 +277,17 @@
     yylloc->line = yylineno;
     yylval->clear();
 
-    if (YY_START == COMMENT)
+    // Line number overflows fake EOFs to exit early, check for this case.
+    if (yylineno == INT_MAX) {
+        yyextra->diagnostics->report(pp::Diagnostics::PP_TOKENIZER_ERROR,
+                pp::SourceLocation(yyfileno, yylineno),
+                "Integer overflow on line number");
+    }
+    else if (YY_START == COMMENT)
     {
         yyextra->diagnostics->report(pp::Diagnostics::PP_EOF_IN_COMMENT,
                                      pp::SourceLocation(yyfileno, yylineno),
-                                     "");
+                                     "EOF while in a comment");
     }
     yyterminate();
 }
diff --git a/src/tests/preprocessor_tests/location_test.cpp b/src/tests/preprocessor_tests/location_test.cpp
index 995db0d..0b36e4e 100644
--- a/src/tests/preprocessor_tests/location_test.cpp
+++ b/src/tests/preprocessor_tests/location_test.cpp
@@ -270,7 +270,7 @@
 // Test for an error being generated when the line number overflows - regular version
 TEST_F(LocationTest, LineOverflowRegular)
 {
-    const char *str = "#line 2147483647\n\n";
+    const char *str = "#line 0x7FFFFFFF\n\n";
 
     ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
 
@@ -285,7 +285,39 @@
 // Test for an error being generated when the line number overflows - inside /* */ comment version
 TEST_F(LocationTest, LineOverflowInComment)
 {
-    const char *str = "#line 2147483647\n/*\n*/";
+    const char *str = "#line 0x7FFFFFFF\n/*\n*/";
+
+    ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
+
+    using testing::_;
+    // Error reported about EOF.
+    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_TOKENIZER_ERROR, _, _));
+
+    pp::Token token;
+    mPreprocessor.lex(&token);
+}
+
+// Test for an error being generated when the line number overflows - inside \n continuation
+// version
+TEST_F(LocationTest, LineOverflowInContinuationN)
+{
+    const char *str = "#line 0x7FFFFFFF\n \\\n\n";
+
+    ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
+
+    using testing::_;
+    // Error reported about EOF.
+    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_TOKENIZER_ERROR, _, _));
+
+    pp::Token token;
+    mPreprocessor.lex(&token);
+}
+
+// Test for an error being generated when the line number overflows - inside \r\n continuation
+// version
+TEST_F(LocationTest, LineOverflowInContinuationRN)
+{
+    const char *str = "#line 0x7FFFFFFF\n \\\r\n\n";
 
     ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));