From 5f77421d75707d11dc4610766d3eea2c8daa43e6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jarkko=20P=C3=B6yry?= Date: Wed, 25 Mar 2015 11:21:16 -0700 Subject: [PATCH] Fix shader info log including 0-terminator. Change-Id: I6722327906f76a06634606daa740981ebdf8540a --- framework/opengl/gluShaderProgram.cpp | 40 +++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/framework/opengl/gluShaderProgram.cpp b/framework/opengl/gluShaderProgram.cpp index 3070bc8..7c273d8 100644 --- a/framework/opengl/gluShaderProgram.cpp +++ b/framework/opengl/gluShaderProgram.cpp @@ -89,23 +89,45 @@ void Shader::compile (void) GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCompileShader()"); - // Query status & log. + // Query status { - int compileStatus = 0; - int infoLogLen = 0; - int unusedLen; + int compileStatus = 0; - m_gl.getShaderiv(m_shader, GL_COMPILE_STATUS, &compileStatus); - m_gl.getShaderiv(m_shader, GL_INFO_LOG_LENGTH, &infoLogLen); + m_gl.getShaderiv(m_shader, GL_COMPILE_STATUS, &compileStatus); GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGetShaderiv()"); m_info.compileOk = compileStatus != GL_FALSE; + } + + // Query log + { + int infoLogLen = 0; + int unusedLen; + + m_gl.getShaderiv(m_shader, GL_INFO_LOG_LENGTH, &infoLogLen); + GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGetShaderiv()"); if (infoLogLen > 0) { - std::vector infoLog(infoLogLen); - m_gl.getShaderInfoLog(m_shader, (int)infoLog.size(), &unusedLen, &infoLog[0]); - m_info.infoLog = 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 infoLog(infoLogLen + 3, '\0'); + + // claim buf size is one smaller to protect from off-by-one writing over buffer bounds + m_gl.getShaderInfoLog(m_shader, (int)infoLog.size() - 1, &unusedLen, &infoLog[0]); + + if (infoLog[(int)(infoLog.size()) - 1] != '\0') + { + // return whole buffer if null terminator was overwritten + m_info.infoLog = std::string(&infoLog[0], infoLog.size()); + } + else + { + // read as C string. infoLog is guaranteed to be 0-terminated + m_info.infoLog = std::string(&infoLog[0]); + } } } } -- 2.7.4