From 19647a32b952b88ce6ee37073ba84e37cdad0c6f Mon Sep 17 00:00:00 2001 From: qining Date: Mon, 11 Apr 2016 19:12:17 -0400 Subject: [PATCH] Fix the infinite loop when an input file lacks EOF 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(). --- .../baseResults/preprocessor.eof_missing.vert.out | 2 ++ Test/preprocessor.eof_missing.vert | 1 + Test/test-preprocessor-list | 1 + glslang/MachineIndependent/Scan.h | 15 ++++++++++----- 4 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 Test/baseResults/preprocessor.eof_missing.vert.out create mode 100644 Test/preprocessor.eof_missing.vert diff --git a/Test/baseResults/preprocessor.eof_missing.vert.out b/Test/baseResults/preprocessor.eof_missing.vert.out new file mode 100644 index 00000000..bf09d53e --- /dev/null +++ b/Test/baseResults/preprocessor.eof_missing.vert.out @@ -0,0 +1,2 @@ +noEOF + diff --git a/Test/preprocessor.eof_missing.vert b/Test/preprocessor.eof_missing.vert new file mode 100644 index 00000000..91773148 --- /dev/null +++ b/Test/preprocessor.eof_missing.vert @@ -0,0 +1 @@ +noEOF \ No newline at end of file diff --git a/Test/test-preprocessor-list b/Test/test-preprocessor-list index 80d4b225..bd7e963b 100644 --- a/Test/test-preprocessor-list +++ b/Test/test-preprocessor-list @@ -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 diff --git a/glslang/MachineIndependent/Scan.h b/glslang/MachineIndependent/Scan.h index 219049be..5532fc31 100644 --- a/glslang/MachineIndependent/Scan.h +++ b/glslang/MachineIndependent/Scan.h @@ -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(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