Fix off-by-one in info log query.
authorJarkko Pöyry <jpoyry@google.com>
Tue, 10 Feb 2015 21:54:51 +0000 (13:54 -0800)
committerJarkko Pöyry <jpoyry@google.com>
Tue, 10 Feb 2015 22:04:41 +0000 (14:04 -0800)
- Fix off-by-one in info log query causing infolog string to contain
  0-byte.
- Tolerate and work around GL implementation off-by-ones in infolog
  query.

Change-Id: I94f2ac55ed9f7a341055f28c69d36a4e0f213481

framework/opengl/gluShaderProgram.cpp

index 1b47046..3070bc8 100644 (file)
@@ -123,17 +123,29 @@ static bool getProgramLinkStatus (const glw::Functions& gl, deUint32 program)
 
 static std::string getProgramInfoLog (const glw::Functions& gl, deUint32 program)
 {
-       int     infoLogLen      = 0;
-       int     unusedLen;
+       int infoLogLen = 0;
+       int unusedLen;
 
-       gl.getProgramiv(program, GL_INFO_LOG_LENGTH,    &infoLogLen);
+       gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLen);
        GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv()");
 
        if (infoLogLen > 0)
        {
-               std::vector<char> infoLog(infoLogLen);
-               gl.getProgramInfoLog(program, (int)infoLog.size(), &unusedLen, &infoLog[0]);
-               return std::string(&infoLog[0], infoLogLen);
+               // The INFO_LOG_LENGTH query and the buffer query implementations have
+               // very commonly off-by-one errors. Try to work around these issues.
+
+               // add tolerance for off-by-one in log length, buffer write, and for terminator
+               std::vector<char> infoLog(infoLogLen + 3, '\0');
+
+               // claim buf size is one smaller to protect from off-by-one writing over buffer bounds
+               gl.getProgramInfoLog(program, (int)infoLog.size() - 1, &unusedLen, &infoLog[0]);
+
+               // return whole buffer if null terminator was overwritten
+               if (infoLog[(int)(infoLog.size()) - 1] != '\0')
+                       return std::string(&infoLog[0], infoLog.size());
+
+               // read as C string. infoLog is guaranteed to be 0-terminated
+               return std::string(&infoLog[0]);
        }
        return std::string();
 }