Fix the infinite loop when an input file lacks EOF
authorqining <qining@google.com>
Mon, 11 Apr 2016 23:12:17 +0000 (19:12 -0400)
committerqining <qining@google.com>
Wed, 27 Apr 2016 14:05:57 +0000 (10:05 -0400)
The input scanner can be trapped in an infinite loop if the given input
file does not have EOF (and is not ended with a 'whitespace').

The problem is caused by unget(), which keeps rolling back the scanner
pointer without hitting an EOF at the end of the file. This makes getch()
function keep returning the last character of the file and never ends,
and the effect of advance() is always counteracted by unget().

Test/baseResults/preprocessor.eof_missing.vert.out [new file with mode: 0644]
Test/preprocessor.eof_missing.vert [new file with mode: 0644]
Test/test-preprocessor-list
glslang/MachineIndependent/Scan.h

diff --git a/Test/baseResults/preprocessor.eof_missing.vert.out b/Test/baseResults/preprocessor.eof_missing.vert.out
new file mode 100644 (file)
index 0000000..bf09d53
--- /dev/null
@@ -0,0 +1,2 @@
+noEOF
+
diff --git a/Test/preprocessor.eof_missing.vert b/Test/preprocessor.eof_missing.vert
new file mode 100644 (file)
index 0000000..9177314
--- /dev/null
@@ -0,0 +1 @@
+noEOF
\ No newline at end of file
index 80d4b22..bd7e963 100644 (file)
@@ -13,3 +13,4 @@ preprocessor.simple.vert
 preprocessor.success_if_parse_would_fail.vert
 preprocessor.defined.vert
 preprocessor.many.endif.vert
+preprocessor.eof_missing.vert
index 219049b..5532fc3 100644 (file)
@@ -54,7 +54,7 @@ public:
     TInputScanner(int n, const char* const s[], size_t L[], const char* const* names = nullptr, int b = 0, int f = 0, bool single = false) :
         numSources(n),
         sources(reinterpret_cast<const unsigned char* const *>(s)), // up to this point, common usage is "char*", but now we need positive 8-bit characters
-        lengths(L), currentSource(0), currentChar(0), stringBias(b), finale(f), singleLogical(single)
+        lengths(L), currentSource(0), currentChar(0), stringBias(b), finale(f), singleLogical(single), endOfFileReached(false)
     {
         loc = new TSourceLoc[numSources];
         for (int i = 0; i < numSources; ++i) {
@@ -81,10 +81,8 @@ public:
     // retrieve the next character and advance one character
     int get()
     {
-        if (currentSource >= numSources)
-            return EndOfInput;
-
         int ret = peek();
+        if (ret == EndOfInput)  return ret;
         ++loc[currentSource].column;
         ++logicalSourceLoc.column;
         if (ret == '\n') {
@@ -101,8 +99,10 @@ public:
     // retrieve the next character, no advance
     int peek()
     {
-        if (currentSource >= numSources)
+        if (currentSource >= numSources) {
+            endOfFileReached = true;
             return EndOfInput;
+        }
         // Make sure we do not read off the end of a string.
         // N.B. Sources can have a length of 0.
         int sourceToRead = currentSource;
@@ -122,6 +122,9 @@ public:
     // go back one character
     void unget()
     {
+        // Do not roll back if we reached the end of the file.
+        if (endOfFileReached) return;
+
         if (currentChar > 0) {
             --currentChar;
             --loc[currentSource].column;
@@ -251,6 +254,8 @@ protected:
     TSourceLoc logicalSourceLoc;
     bool singleLogical; // treats the strings as a single logical string.
                         // locations will be reported from the first string.
+
+    bool endOfFileReached; // set to true once peak() returns EndOfFile.
 };
 
 } // end namespace glslang