Add base::numerics for safe math and conversions.
This replaces are "IsUnsignedXXXSafe" family of methods.
Also add overflow checks to unpack block sizes.
BUG=angleproject:1397
Change-Id: Ib47be149b0486c70f795b0d0f8899441faac9340
Reviewed-on: https://chromium-review.googlesource.com/348062
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
index 54a63ac..0f73448 100644
--- a/src/libANGLE/validationES.cpp
+++ b/src/libANGLE/validationES.cpp
@@ -7,6 +7,7 @@
// validationES.h: Validation functions for generic OpenGL ES entry point parameters
#include "libANGLE/validationES.h"
+
#include "libANGLE/validationES2.h"
#include "libANGLE/validationES3.h"
#include "libANGLE/Context.h"
@@ -25,6 +26,8 @@
#include "common/mathutil.h"
#include "common/utilities.h"
+using namespace angle;
+
namespace gl
{
const char *g_ExceedsMaxElementErrorMessage = "Element value exceeds maximum element index.";
@@ -1140,12 +1143,26 @@
GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
const InternalFormat &sizedFormatInfo = GetInternalFormatInfo(sizedInternalFormat);
- GLsizei outputPitch =
+ auto outputPitchOrErr =
sizedFormatInfo.computeRowPitch(type, width, context->getState().getPackAlignment(),
context->getState().getPackRowLength());
+
+ if (outputPitchOrErr.isError())
+ {
+ context->handleError(outputPitchOrErr.getError());
+ return false;
+ }
+
+ CheckedNumeric<GLuint> checkedOutputPitch(outputPitchOrErr.getResult());
+ auto checkedRequiredSize = checkedOutputPitch * height;
+ if (!checkedRequiredSize.IsValid())
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Unsigned multiplication overflow."));
+ return false;
+ }
+
// sized query sanity check
- int requiredSize = outputPitch * height;
- if (requiredSize > bufSize)
+ if (checkedRequiredSize.ValueOrDie() > static_cast<GLuint>(bufSize))
{
context->handleError(Error(GL_INVALID_OPERATION));
return false;
@@ -2815,11 +2832,10 @@
}
// Check for buffer overflow
- size_t offsetSize = static_cast<size_t>(offset);
- size_t lengthSize = static_cast<size_t>(length);
+ CheckedNumeric<size_t> checkedOffset(offset);
+ auto checkedSize = checkedOffset + length;
- if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) ||
- offsetSize + lengthSize > static_cast<size_t>(buffer->getSize()))
+ if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
{
context->handleError(
Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
@@ -2911,11 +2927,11 @@
}
// Check for buffer overflow
- size_t offsetSize = static_cast<size_t>(offset);
- size_t lengthSize = static_cast<size_t>(length);
+ CheckedNumeric<size_t> checkedOffset(offset);
+ auto checkedSize = checkedOffset + length;
- if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) ||
- offsetSize + lengthSize > static_cast<size_t>(buffer->getMapLength()))
+ if (!checkedSize.IsValid() ||
+ checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
{
context->handleError(
Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));