Commit f97f6e0e by Alexis Hetu Committed by Alexis Hétu

Pixel unpack buffer validation

Added proper validation to make sure the pixel unpack buffer is both unmapped and large enough, when imageSize is specified. Change-Id: If6ec764d741bb9d63d38d0656188846c5a9be66d Reviewed-on: https://swiftshader-review.googlesource.com/13868Tested-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com>
parent d469de2d
...@@ -1579,11 +1579,33 @@ Buffer *Context::getGenericUniformBuffer() const ...@@ -1579,11 +1579,33 @@ Buffer *Context::getGenericUniformBuffer() const
return mState.genericUniformBuffer; return mState.genericUniformBuffer;
} }
const GLvoid* Context::getPixels(const GLvoid* data) const GLsizei Context::getRequiredBufferSize(GLsizei width, GLsizei height, GLsizei depth, GLint internalformat, GLenum type) const
{ {
es2::Buffer* unpackBuffer = getPixelUnpackBuffer(); GLenum format = GetSizedInternalFormat(internalformat, type);
const unsigned char* unpackBufferData = unpackBuffer ? static_cast<const unsigned char*>(unpackBuffer->data()) : nullptr; GLsizei inputWidth = (mState.unpackInfo.rowLength == 0) ? width : mState.unpackInfo.rowLength;
return unpackBufferData ? unpackBufferData + (ptrdiff_t)(data) : data; GLsizei inputPitch = egl::ComputePitch(inputWidth, format, type, mState.unpackInfo.alignment);
GLsizei inputHeight = (mState.unpackInfo.imageHeight == 0) ? height : mState.unpackInfo.imageHeight;
size_t offset = egl::ComputePackingOffset(format, type, inputWidth, inputHeight, mState.unpackInfo.alignment, mState.unpackInfo.skipImages, mState.unpackInfo.skipRows, mState.unpackInfo.skipPixels);
return inputPitch * inputHeight * depth + static_cast<GLsizei>(offset);
}
GLenum Context::getPixels(const GLvoid **data, GLsizei imageSize) const
{
if(mState.pixelUnpackBuffer)
{
if(mState.pixelUnpackBuffer->name)
{
if(mState.pixelUnpackBuffer->isMapped() ||
(mState.pixelUnpackBuffer->size() < imageSize) ||
((*data) && (imageSize % static_cast<GLsizei>((ptrdiff_t)(*data)))))
{
return GL_INVALID_OPERATION;
}
}
*data = static_cast<const unsigned char*>(mState.pixelUnpackBuffer->data()) + (ptrdiff_t)(*data);
}
return GL_NONE;
} }
bool Context::getBuffer(GLenum target, es2::Buffer **buffer) const bool Context::getBuffer(GLenum target, es2::Buffer **buffer) const
......
...@@ -646,7 +646,8 @@ public: ...@@ -646,7 +646,8 @@ public:
Buffer *getPixelPackBuffer() const; Buffer *getPixelPackBuffer() const;
Buffer *getPixelUnpackBuffer() const; Buffer *getPixelUnpackBuffer() const;
Buffer *getGenericUniformBuffer() const; Buffer *getGenericUniformBuffer() const;
const GLvoid* getPixels(const GLvoid* data) const; GLsizei getRequiredBufferSize(GLsizei width, GLsizei height, GLsizei depth, GLint internalformat, GLenum type) const;
GLenum getPixels(const GLvoid **data, GLsizei imageSize) const;
bool getBuffer(GLenum target, es2::Buffer **buffer) const; bool getBuffer(GLenum target, es2::Buffer **buffer) const;
Program *getCurrentProgram() const; Program *getCurrentProgram() const;
Texture2D *getTexture2D() const; Texture2D *getTexture2D() const;
......
...@@ -876,6 +876,12 @@ void CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLs ...@@ -876,6 +876,12 @@ void CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLs
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
} }
GLenum validationError = context->getPixels(&data, imageSize);
if(validationError != GL_NONE)
{
return error(validationError);
}
texture->setCompressedImage(level, internalformat, width, height, imageSize, data); texture->setCompressedImage(level, internalformat, width, height, imageSize, data);
} }
else else
...@@ -895,7 +901,16 @@ void CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLs ...@@ -895,7 +901,16 @@ void CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLs
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
{
GLenum validationError = context->getPixels(&data, imageSize);
if(validationError != GL_NONE)
{
return error(validationError);
}
texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data); texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data);
}
break; break;
default: UNREACHABLE(target); default: UNREACHABLE(target);
} }
...@@ -932,7 +947,7 @@ void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yo ...@@ -932,7 +947,7 @@ void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yo
return error(validationError); return error(validationError);
} }
if(width == 0 || height == 0 || !data) if(width == 0 || height == 0)
{ {
return; return;
} }
...@@ -962,7 +977,12 @@ void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yo ...@@ -962,7 +977,12 @@ void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yo
if(validationError == GL_NONE) if(validationError == GL_NONE)
{ {
texture->subImageCompressed(level, xoffset, yoffset, width, height, sizedInternalFormat, imageSize, context->getPixels(data)); validationError = context->getPixels(&data, imageSize);
}
if(validationError == GL_NONE)
{
texture->subImageCompressed(level, xoffset, yoffset, width, height, sizedInternalFormat, imageSize, data);
} }
else else
{ {
...@@ -977,7 +997,12 @@ void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yo ...@@ -977,7 +997,12 @@ void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yo
if(validationError == GL_NONE) if(validationError == GL_NONE)
{ {
texture->subImageCompressed(target, level, xoffset, yoffset, width, height, sizedInternalFormat, imageSize, context->getPixels(data)); validationError = context->getPixels(&data, imageSize);
}
if(validationError == GL_NONE)
{
texture->subImageCompressed(target, level, xoffset, yoffset, width, height, sizedInternalFormat, imageSize, data);
} }
else else
{ {
...@@ -5104,6 +5129,12 @@ void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, ...@@ -5104,6 +5129,12 @@ void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width,
GLenum sizedInternalFormat = GetSizedInternalFormat(format, type); GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
validationError = context->getPixels(&data, context->getRequiredBufferSize(width, height, 1, sizedInternalFormat, type));
if(validationError != GL_NONE)
{
return error(validationError);
}
if(target == GL_TEXTURE_2D) if(target == GL_TEXTURE_2D)
{ {
es2::Texture2D *texture = context->getTexture2D(); es2::Texture2D *texture = context->getTexture2D();
...@@ -5113,7 +5144,7 @@ void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, ...@@ -5113,7 +5144,7 @@ void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width,
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
} }
texture->setImage(context, level, width, height, sizedInternalFormat, type, context->getUnpackInfo(), context->getPixels(data)); texture->setImage(context, level, width, height, sizedInternalFormat, type, context->getUnpackInfo(), data);
} }
else else
{ {
...@@ -5124,7 +5155,7 @@ void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, ...@@ -5124,7 +5155,7 @@ void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width,
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
} }
texture->setImage(context, target, level, width, height, sizedInternalFormat, type, context->getUnpackInfo(), context->getPixels(data)); texture->setImage(context, target, level, width, height, sizedInternalFormat, type, context->getUnpackInfo(), data);
} }
} }
} }
...@@ -5471,15 +5502,21 @@ void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLs ...@@ -5471,15 +5502,21 @@ void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLs
{ {
GLenum sizedInternalFormat = GetSizedInternalFormat(format, type); GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
GLenum validationError = context->getPixels(&data, context->getRequiredBufferSize(width, height, 1, sizedInternalFormat, type));
if(validationError != GL_NONE)
{
return error(validationError);
}
if(target == GL_TEXTURE_2D) if(target == GL_TEXTURE_2D)
{ {
es2::Texture2D *texture = context->getTexture2D(); es2::Texture2D *texture = context->getTexture2D();
GLenum validationError = ValidateSubImageParams(false, width, height, xoffset, yoffset, target, level, sizedInternalFormat, texture); validationError = ValidateSubImageParams(false, width, height, xoffset, yoffset, target, level, sizedInternalFormat, texture);
if(validationError == GL_NONE) if(validationError == GL_NONE)
{ {
texture->subImage(context, level, xoffset, yoffset, width, height, sizedInternalFormat, type, context->getUnpackInfo(), context->getPixels(data)); texture->subImage(context, level, xoffset, yoffset, width, height, sizedInternalFormat, type, context->getUnpackInfo(), data);
} }
else else
{ {
...@@ -5490,11 +5527,11 @@ void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLs ...@@ -5490,11 +5527,11 @@ void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLs
{ {
es2::TextureCubeMap *texture = context->getTextureCubeMap(); es2::TextureCubeMap *texture = context->getTextureCubeMap();
GLenum validationError = ValidateSubImageParams(false, width, height, xoffset, yoffset, target, level, sizedInternalFormat, texture); validationError = ValidateSubImageParams(false, width, height, xoffset, yoffset, target, level, sizedInternalFormat, texture);
if(validationError == GL_NONE) if(validationError == GL_NONE)
{ {
texture->subImage(context, target, level, xoffset, yoffset, width, height, sizedInternalFormat, type, context->getUnpackInfo(), context->getPixels(data)); texture->subImage(context, target, level, xoffset, yoffset, width, height, sizedInternalFormat, type, context->getUnpackInfo(), data);
} }
else else
{ {
...@@ -6323,7 +6360,14 @@ void TexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei wi ...@@ -6323,7 +6360,14 @@ void TexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei wi
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
} }
texture->setImage(context, level, width, height, depth, GetSizedInternalFormat(internalformat, type), type, context->getUnpackInfo(), context->getPixels(data)); GLenum sizedInternalFormat = GetSizedInternalFormat(internalformat, type);
GLenum validationError = context->getPixels(&data, context->getRequiredBufferSize(width, height, depth, sizedInternalFormat, type));
if(validationError != GL_NONE)
{
return error(validationError);
}
texture->setImage(context, level, width, height, depth, sizedInternalFormat, type, context->getUnpackInfo(), data);
} }
} }
...@@ -6366,9 +6410,15 @@ void TexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, ...@@ -6366,9 +6410,15 @@ void TexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset,
GLenum sizedInternalFormat = GetSizedInternalFormat(format, type); GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
GLenum validationError = ValidateSubImageParams(false, width, height, depth, xoffset, yoffset, zoffset, target, level, sizedInternalFormat, texture); GLenum validationError = ValidateSubImageParams(false, width, height, depth, xoffset, yoffset, zoffset, target, level, sizedInternalFormat, texture);
if(validationError == GL_NONE) if(validationError == GL_NONE)
{ {
texture->subImage(context, level, xoffset, yoffset, zoffset, width, height, depth, sizedInternalFormat, type, context->getUnpackInfo(), context->getPixels(data)); validationError = context->getPixels(&data, context->getRequiredBufferSize(width, height, depth, sizedInternalFormat, type));
}
if(validationError == GL_NONE)
{
texture->subImage(context, level, xoffset, yoffset, zoffset, width, height, depth, sizedInternalFormat, type, context->getUnpackInfo(), data);
} }
else else
{ {
...@@ -6486,6 +6536,13 @@ void CompressedTexImage3DOES(GLenum target, GLint level, GLenum internalformat, ...@@ -6486,6 +6536,13 @@ void CompressedTexImage3DOES(GLenum target, GLint level, GLenum internalformat,
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
} }
GLenum validationError = context->getPixels(&data, imageSize);
if(validationError != GL_NONE)
{
return error(validationError);
}
texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data); texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data);
} }
} }
...@@ -6521,7 +6578,7 @@ void CompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint ...@@ -6521,7 +6578,7 @@ void CompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint
return error(validationError); return error(validationError);
} }
if(width == 0 || height == 0 || depth == 0 || !data) if(width == 0 || height == 0 || depth == 0)
{ {
return; return;
} }
...@@ -6537,7 +6594,14 @@ void CompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint ...@@ -6537,7 +6594,14 @@ void CompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
} }
texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, context->getPixels(data)); GLenum validationError = context->getPixels(&data, imageSize);
if(validationError != GL_NONE)
{
return error(validationError);
}
texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
} }
} }
......
...@@ -678,7 +678,15 @@ GL_APICALL void GL_APIENTRY glTexImage3D(GLenum target, GLint level, GLint inter ...@@ -678,7 +678,15 @@ GL_APICALL void GL_APIENTRY glTexImage3D(GLenum target, GLint level, GLint inter
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
} }
texture->setImage(context, level, width, height, depth, GetSizedInternalFormat(internalformat, type), type, context->getUnpackInfo(), context->getPixels(data)); GLenum sizedInternalFormat = GetSizedInternalFormat(internalformat, type);
GLenum validationError = context->getPixels(&data, context->getRequiredBufferSize(width, height, depth, sizedInternalFormat, type));
if(validationError != GL_NONE)
{
return error(validationError);
}
texture->setImage(context, level, width, height, depth, sizedInternalFormat, type, context->getUnpackInfo(), data);
} }
} }
...@@ -724,7 +732,13 @@ GL_APICALL void GL_APIENTRY glTexSubImage3D(GLenum target, GLint level, GLint xo ...@@ -724,7 +732,13 @@ GL_APICALL void GL_APIENTRY glTexSubImage3D(GLenum target, GLint level, GLint xo
GLenum validationError = ValidateSubImageParams(false, width, height, depth, xoffset, yoffset, zoffset, target, level, sizedInternalFormat, texture); GLenum validationError = ValidateSubImageParams(false, width, height, depth, xoffset, yoffset, zoffset, target, level, sizedInternalFormat, texture);
if(validationError == GL_NONE) if(validationError == GL_NONE)
{ {
texture->subImage(context, level, xoffset, yoffset, zoffset, width, height, depth, sizedInternalFormat, type, context->getUnpackInfo(), context->getPixels(data)); GLenum validationError = context->getPixels(&data, context->getRequiredBufferSize(width, height, depth, sizedInternalFormat, type));
if(validationError != GL_NONE)
{
return error(validationError);
}
texture->subImage(context, level, xoffset, yoffset, zoffset, width, height, depth, sizedInternalFormat, type, context->getUnpackInfo(), data);
} }
else else
{ {
...@@ -856,6 +870,12 @@ GL_APICALL void GL_APIENTRY glCompressedTexImage3D(GLenum target, GLint level, G ...@@ -856,6 +870,12 @@ GL_APICALL void GL_APIENTRY glCompressedTexImage3D(GLenum target, GLint level, G
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
} }
GLenum validationError = context->getPixels(&data, imageSize);
if(validationError != GL_NONE)
{
return error(validationError);
}
texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data); texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data);
} }
} }
...@@ -892,7 +912,7 @@ GL_APICALL void GL_APIENTRY glCompressedTexSubImage3D(GLenum target, GLint level ...@@ -892,7 +912,7 @@ GL_APICALL void GL_APIENTRY glCompressedTexSubImage3D(GLenum target, GLint level
return error(validationError); return error(validationError);
} }
if(width == 0 || height == 0 || depth == 0 || !data) if(width == 0 || height == 0 || depth == 0)
{ {
return; return;
} }
...@@ -908,7 +928,13 @@ GL_APICALL void GL_APIENTRY glCompressedTexSubImage3D(GLenum target, GLint level ...@@ -908,7 +928,13 @@ GL_APICALL void GL_APIENTRY glCompressedTexSubImage3D(GLenum target, GLint level
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
} }
texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, context->getPixels(data)); GLenum validationError = context->getPixels(&data, imageSize);
if(validationError != GL_NONE)
{
return error(validationError);
}
texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment