Commit 4b4cdff8 by Jamie Madill Committed by Commit Bot

Fix unpack parameter validation.

BUG=angleproject:1397 Change-Id: Icdfc99eefcfad730ec887b82ec0758a6d6c0b9a7 Reviewed-on: https://chromium-review.googlesource.com/348064Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 8b8d0432
...@@ -684,23 +684,34 @@ gl::ErrorOrResult<GLuint> InternalFormat::computeRowPitch(GLenum formatType, ...@@ -684,23 +684,34 @@ gl::ErrorOrResult<GLuint> InternalFormat::computeRowPitch(GLenum formatType,
GLint alignment, GLint alignment,
GLint rowLength) const GLint rowLength) const
{ {
ASSERT(alignment > 0 && isPow2(alignment)); // Compressed images do not use pack/unpack parameters.
GLuint rowBytes; if (compressed)
{
ASSERT(rowLength == 0);
return computeCompressedImageSize(formatType, gl::Extents(width, 1, 1));
}
CheckedNumeric<GLuint> checkedRowBytes(0);
if (rowLength > 0) if (rowLength > 0)
{ {
ASSERT(!compressed); CheckedNumeric<GLuint> checkePixelBytes(pixelBytes);
CheckedNumeric<GLuint> checkedBytes(pixelBytes); checkedRowBytes = checkePixelBytes * rowLength;
checkedBytes *= rowLength;
ANGLE_TRY_CHECKED_MATH(checkedBytes);
rowBytes = checkedBytes.ValueOrDie();
} }
else else
{ {
ANGLE_TRY_RESULT(computeBlockSize(formatType, gl::Extents(width, 1, 1)), rowBytes); CheckedNumeric<GLuint> checkedWidth(width);
const auto &typeInfo = GetTypeInfo(formatType);
CheckedNumeric<GLuint> checkedComponents(typeInfo.specialInterpretation ? 1u
: componentCount);
CheckedNumeric<GLuint> checkedTypeBytes(typeInfo.bytes);
checkedRowBytes = checkedWidth * checkedComponents * checkedTypeBytes;
} }
auto checkedResult = rx::CheckedRoundUp(rowBytes, static_cast<GLuint>(alignment));
ANGLE_TRY_CHECKED_MATH(checkedResult); ASSERT(alignment > 0 && isPow2(alignment));
return checkedResult.ValueOrDie(); CheckedNumeric<GLuint> checkedAlignment(alignment);
auto aligned = rx::roundUp(checkedRowBytes, checkedAlignment);
ANGLE_TRY_CHECKED_MATH(aligned);
return aligned.ValueOrDie();
} }
gl::ErrorOrResult<GLuint> InternalFormat::computeDepthPitch(GLenum formatType, gl::ErrorOrResult<GLuint> InternalFormat::computeDepthPitch(GLenum formatType,
...@@ -710,15 +721,8 @@ gl::ErrorOrResult<GLuint> InternalFormat::computeDepthPitch(GLenum formatType, ...@@ -710,15 +721,8 @@ gl::ErrorOrResult<GLuint> InternalFormat::computeDepthPitch(GLenum formatType,
GLint rowLength, GLint rowLength,
GLint imageHeight) const GLint imageHeight) const
{ {
GLuint rows; GLuint rows =
if (imageHeight > 0) (imageHeight > 0 ? static_cast<GLuint>(imageHeight) : static_cast<GLuint>(height));
{
rows = imageHeight;
}
else
{
rows = height;
}
GLuint rowPitch = 0; GLuint rowPitch = 0;
ANGLE_TRY_RESULT(computeRowPitch(formatType, width, alignment, rowLength), rowPitch); ANGLE_TRY_RESULT(computeRowPitch(formatType, width, alignment, rowLength), rowPitch);
...@@ -728,28 +732,21 @@ gl::ErrorOrResult<GLuint> InternalFormat::computeDepthPitch(GLenum formatType, ...@@ -728,28 +732,21 @@ gl::ErrorOrResult<GLuint> InternalFormat::computeDepthPitch(GLenum formatType,
return depthPitch.ValueOrDie(); return depthPitch.ValueOrDie();
} }
gl::ErrorOrResult<GLuint> InternalFormat::computeBlockSize(GLenum formatType, gl::ErrorOrResult<GLuint> InternalFormat::computeCompressedImageSize(GLenum formatType,
const gl::Extents &size) const const gl::Extents &size) const
{ {
CheckedNumeric<GLuint> checkedWidth(size.width); CheckedNumeric<GLuint> checkedWidth(size.width);
CheckedNumeric<GLuint> checkedHeight(size.height); CheckedNumeric<GLuint> checkedHeight(size.height);
CheckedNumeric<GLuint> checkedDepth(size.depth); CheckedNumeric<GLuint> checkedDepth(size.depth);
CheckedNumeric<GLuint> checkedBlockWidth(compressedBlockWidth);
if (compressed) CheckedNumeric<GLuint> checkedBlockHeight(compressedBlockHeight);
{
auto numBlocksWide = (checkedWidth + compressedBlockWidth - 1u) / compressedBlockWidth; ASSERT(compressed);
auto numBlocksHigh = (checkedHeight + compressedBlockHeight - 1u) / compressedBlockHeight; auto numBlocksWide = (checkedWidth + checkedBlockWidth - 1u) / checkedBlockWidth;
auto bytes = numBlocksWide * numBlocksHigh * pixelBytes * checkedDepth; auto numBlocksHigh = (checkedHeight + checkedBlockHeight - 1u) / checkedBlockHeight;
ANGLE_TRY_CHECKED_MATH(bytes); auto bytes = numBlocksWide * numBlocksHigh * pixelBytes * checkedDepth;
return bytes.ValueOrDie(); ANGLE_TRY_CHECKED_MATH(bytes);
} return bytes.ValueOrDie();
const Type &typeInfo = GetTypeInfo(formatType);
GLuint components = typeInfo.specialInterpretation ? 1u : componentCount;
auto result = checkedWidth * checkedHeight * checkedDepth * components * typeInfo.bytes;
ANGLE_TRY_CHECKED_MATH(result);
return result.ValueOrDie();
} }
GLuint InternalFormat::computeSkipPixels(GLint rowPitch, GLuint InternalFormat::computeSkipPixels(GLint rowPitch,
...@@ -761,26 +758,52 @@ GLuint InternalFormat::computeSkipPixels(GLint rowPitch, ...@@ -761,26 +758,52 @@ GLuint InternalFormat::computeSkipPixels(GLint rowPitch,
return skipImages * depthPitch + skipRows * rowPitch + skipPixels * pixelBytes; return skipImages * depthPitch + skipRows * rowPitch + skipPixels * pixelBytes;
} }
gl::ErrorOrResult<GLuint> InternalFormat::computeUnpackSize(
GLenum formatType,
const gl::Extents &size,
const gl::PixelUnpackState &unpack) const
{
// Compressed images do not use unpack parameters.
if (compressed)
{
return computeCompressedImageSize(formatType, size);
}
base::CheckedNumeric<GLuint> checkedGroups(unpack.rowLength > 0 ? unpack.rowLength
: size.width);
base::CheckedNumeric<GLuint> checkedRows(unpack.imageHeight > 0 ? unpack.imageHeight
: size.height);
// Compute the groups of all the layers in (0,depth-1)
auto layerGroups = checkedGroups * checkedRows * (size.depth - 1);
// Compute the groups in the last layer (for non-3D textures, the only one)
auto lastLayerGroups = checkedGroups * (size.height - 1) + size.width;
// The total size is the sum times the bytes per pixel.
auto totalSize = (layerGroups + lastLayerGroups) * pixelBytes;
ANGLE_TRY_CHECKED_MATH(totalSize);
return totalSize.ValueOrDie();
}
GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type) GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type)
{ {
const InternalFormat& formatInfo = GetInternalFormatInfo(internalFormat); const InternalFormat &formatInfo = GetInternalFormatInfo(internalFormat);
if (formatInfo.pixelBytes > 0) if (formatInfo.pixelBytes > 0)
{ {
return internalFormat; return internalFormat;
} }
else
static const FormatMap formatMap = BuildFormatMap();
auto iter = formatMap.find(FormatTypePair(internalFormat, type));
if (iter != formatMap.end())
{ {
static const FormatMap formatMap = BuildFormatMap(); return iter->second;
FormatMap::const_iterator iter = formatMap.find(FormatTypePair(internalFormat, type));
if (iter != formatMap.end())
{
return iter->second;
}
else
{
return GL_NONE;
}
} }
return GL_NONE;
} }
const FormatSet &GetAllSizedInternalFormats() const FormatSet &GetAllSizedInternalFormats()
......
...@@ -44,12 +44,16 @@ struct InternalFormat ...@@ -44,12 +44,16 @@ struct InternalFormat
GLint alignment, GLint alignment,
GLint rowLength, GLint rowLength,
GLint imageHeight) const; GLint imageHeight) const;
gl::ErrorOrResult<GLuint> computeBlockSize(GLenum formatType, const gl::Extents &size) const; gl::ErrorOrResult<GLuint> computeCompressedImageSize(GLenum formatType,
const gl::Extents &size) const;
GLuint computeSkipPixels(GLint rowPitch, GLuint computeSkipPixels(GLint rowPitch,
GLint depthPitch, GLint depthPitch,
GLint skipImages, GLint skipImages,
GLint skipRows, GLint skipRows,
GLint skipPixels) const; GLint skipPixels) const;
gl::ErrorOrResult<GLuint> computeUnpackSize(GLenum formatType,
const gl::Extents &size,
const gl::PixelUnpackState &unpack) const;
GLuint redBits; GLuint redBits;
GLuint greenBits; GLuint greenBits;
......
...@@ -625,11 +625,7 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index, ...@@ -625,11 +625,7 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index,
ASSERT(!image->isDirty()); ASSERT(!image->isDirty());
ID3D11Resource *resource = nullptr; ID3D11Resource *resource = nullptr;
gl::Error error = getResource(&resource); ANGLE_TRY(getResource(&resource));
if (error.isError())
{
return error;
}
ASSERT(resource); ASSERT(resource);
UINT destSubresource = getSubresourceIndex(index); UINT destSubresource = getSubresourceIndex(index);
...@@ -679,12 +675,7 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index, ...@@ -679,12 +675,7 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index,
d3d11::LoadImageFunctionInfo loadFunctionInfo = d3d11Format.loadFunctions.at(type); d3d11::LoadImageFunctionInfo loadFunctionInfo = d3d11Format.loadFunctions.at(type);
if (loadFunctionInfo.requiresConversion) if (loadFunctionInfo.requiresConversion)
{ {
error = mRenderer->getScratchMemoryBuffer(neededSize, &conversionBuffer); ANGLE_TRY(mRenderer->getScratchMemoryBuffer(neededSize, &conversionBuffer));
if (error.isError())
{
return error;
}
loadFunctionInfo.loadFunction(width, height, depth, pixelData + srcSkipBytes, srcRowPitch, loadFunctionInfo.loadFunction(width, height, depth, pixelData + srcSkipBytes, srcRowPitch,
srcDepthPitch, conversionBuffer->data(), bufferRowPitch, srcDepthPitch, conversionBuffer->data(), bufferRowPitch,
bufferDepthPitch); bufferDepthPitch);
...@@ -720,7 +711,7 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index, ...@@ -720,7 +711,7 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index,
bufferRowPitch, bufferDepthPitch); bufferRowPitch, bufferDepthPitch);
} }
return gl::Error(GL_NO_ERROR); return gl::NoError();
} }
TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain) TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain)
......
...@@ -390,9 +390,9 @@ gl::Error TextureGL::setStorage(GLenum target, size_t levels, GLenum internalFor ...@@ -390,9 +390,9 @@ gl::Error TextureGL::setStorage(GLenum target, size_t levels, GLenum internalFor
if (internalFormatInfo.compressed) if (internalFormatInfo.compressed)
{ {
GLuint dataSize = 0; GLuint dataSize = 0;
ANGLE_TRY_RESULT( ANGLE_TRY_RESULT(internalFormatInfo.computeCompressedImageSize(
internalFormatInfo.computeBlockSize(GL_UNSIGNED_BYTE, levelSize), GL_UNSIGNED_BYTE, levelSize),
dataSize); dataSize);
mFunctions->compressedTexImage2D(target, static_cast<GLint>(level), mFunctions->compressedTexImage2D(target, static_cast<GLint>(level),
texStorageFormat.internalFormat, texStorageFormat.internalFormat,
levelSize.width, levelSize.height, 0, levelSize.width, levelSize.height, 0,
...@@ -413,9 +413,9 @@ gl::Error TextureGL::setStorage(GLenum target, size_t levels, GLenum internalFor ...@@ -413,9 +413,9 @@ gl::Error TextureGL::setStorage(GLenum target, size_t levels, GLenum internalFor
if (internalFormatInfo.compressed) if (internalFormatInfo.compressed)
{ {
GLuint dataSize = 0; GLuint dataSize = 0;
ANGLE_TRY_RESULT( ANGLE_TRY_RESULT(internalFormatInfo.computeCompressedImageSize(
internalFormatInfo.computeBlockSize(GL_UNSIGNED_BYTE, levelSize), GL_UNSIGNED_BYTE, levelSize),
dataSize); dataSize);
mFunctions->compressedTexImage2D( mFunctions->compressedTexImage2D(
face, static_cast<GLint>(level), texStorageFormat.internalFormat, face, static_cast<GLint>(level), texStorageFormat.internalFormat,
levelSize.width, levelSize.height, 0, levelSize.width, levelSize.height, 0,
...@@ -465,7 +465,8 @@ gl::Error TextureGL::setStorage(GLenum target, size_t levels, GLenum internalFor ...@@ -465,7 +465,8 @@ gl::Error TextureGL::setStorage(GLenum target, size_t levels, GLenum internalFor
{ {
GLuint dataSize = 0; GLuint dataSize = 0;
ANGLE_TRY_RESULT( ANGLE_TRY_RESULT(
internalFormatInfo.computeBlockSize(GL_UNSIGNED_BYTE, levelSize), dataSize); internalFormatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, levelSize),
dataSize);
mFunctions->compressedTexImage3D(target, i, texStorageFormat.internalFormat, mFunctions->compressedTexImage3D(target, i, texStorageFormat.internalFormat,
levelSize.width, levelSize.height, levelSize.width, levelSize.height,
levelSize.depth, 0, levelSize.depth, 0,
......
...@@ -1831,7 +1831,7 @@ bool ValidateCompressedTexImage2D(Context *context, ...@@ -1831,7 +1831,7 @@ bool ValidateCompressedTexImage2D(Context *context,
const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
auto blockSizeOrErr = auto blockSizeOrErr =
formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1)); formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
if (blockSizeOrErr.isError()) if (blockSizeOrErr.isError())
{ {
context->handleError(blockSizeOrErr.getError()); context->handleError(blockSizeOrErr.getError());
...@@ -1879,7 +1879,7 @@ bool ValidateCompressedTexSubImage2D(Context *context, ...@@ -1879,7 +1879,7 @@ bool ValidateCompressedTexSubImage2D(Context *context,
const InternalFormat &formatInfo = GetInternalFormatInfo(format); const InternalFormat &formatInfo = GetInternalFormatInfo(format);
auto blockSizeOrErr = auto blockSizeOrErr =
formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1)); formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
if (blockSizeOrErr.isError()) if (blockSizeOrErr.isError())
{ {
context->handleError(blockSizeOrErr.getError()); context->handleError(blockSizeOrErr.getError());
......
...@@ -472,25 +472,12 @@ bool ValidateES3TexImageParametersBase(Context *context, ...@@ -472,25 +472,12 @@ bool ValidateES3TexImageParametersBase(Context *context,
{ {
// ...the data would be unpacked from the buffer object such that the memory reads required // ...the data would be unpacked from the buffer object such that the memory reads required
// would exceed the data store size. // would exceed the data store size.
size_t widthSize = static_cast<size_t>(width);
size_t heightSize = static_cast<size_t>(height);
size_t depthSize = static_cast<size_t>(depth);
GLenum sizedFormat = GetSizedInternalFormat(actualInternalFormat, type); GLenum sizedFormat = GetSizedInternalFormat(actualInternalFormat, type);
CheckedNumeric<size_t> checkedBytes(gl::GetInternalFormatInfo(sizedFormat).pixelBytes);
checkedBytes *= widthSize;
checkedBytes *= heightSize;
checkedBytes *= depthSize;
if (!checkedBytes.IsValid())
{
// Overflow past the end of the buffer
context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow"));
return false;
}
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat); const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
auto copyBytesOrErr = formatInfo.computeBlockSize(type, gl::Extents(width, height, depth)); const gl::Extents size(width, height, depth);
const auto &unpack = context->getState().getUnpackState();
auto copyBytesOrErr = formatInfo.computeUnpackSize(type, size, unpack);
if (copyBytesOrErr.isError()) if (copyBytesOrErr.isError())
{ {
context->handleError(copyBytesOrErr.getError()); context->handleError(copyBytesOrErr.getError());
...@@ -1549,6 +1536,12 @@ bool ValidateCompressedTexImage3D(Context *context, ...@@ -1549,6 +1536,12 @@ bool ValidateCompressedTexImage3D(Context *context,
return false; return false;
} }
if (!ValidTextureTarget(context, target))
{
context->handleError(Error(GL_INVALID_ENUM));
return false;
}
// Validate image size // Validate image size
if (!ValidImageSizeParameters(context, target, level, width, height, depth, false)) if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
{ {
...@@ -1557,8 +1550,14 @@ bool ValidateCompressedTexImage3D(Context *context, ...@@ -1557,8 +1550,14 @@ bool ValidateCompressedTexImage3D(Context *context,
} }
const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
if (!formatInfo.compressed)
{
context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
return false;
}
auto blockSizeOrErr = auto blockSizeOrErr =
formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth)); formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
if (blockSizeOrErr.isError()) if (blockSizeOrErr.isError())
{ {
context->handleError(Error(GL_INVALID_VALUE)); context->handleError(Error(GL_INVALID_VALUE));
...@@ -1907,7 +1906,7 @@ bool ValidateCompressedTexSubImage3D(Context *context, ...@@ -1907,7 +1906,7 @@ bool ValidateCompressedTexSubImage3D(Context *context,
const InternalFormat &formatInfo = GetInternalFormatInfo(format); const InternalFormat &formatInfo = GetInternalFormatInfo(format);
auto blockSizeOrErr = auto blockSizeOrErr =
formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth)); formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
if (blockSizeOrErr.isError()) if (blockSizeOrErr.isError())
{ {
context->handleError(blockSizeOrErr.getError()); context->handleError(blockSizeOrErr.getError());
......
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