summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chromium/third_party/angle/src/libGLESv2/entry_points_gles_3_0.cpp44
1 files changed, 40 insertions, 4 deletions
diff --git a/chromium/third_party/angle/src/libGLESv2/entry_points_gles_3_0.cpp b/chromium/third_party/angle/src/libGLESv2/entry_points_gles_3_0.cpp
index 8ef131417a7..c1bbc98de8b 100644
--- a/chromium/third_party/angle/src/libGLESv2/entry_points_gles_3_0.cpp
+++ b/chromium/third_party/angle/src/libGLESv2/entry_points_gles_3_0.cpp
@@ -23,7 +23,10 @@
#include "libANGLE/validationES3.h"
#include "libANGLE/queryconversions.h"
+#include "base/numerics/safe_conversions.h"
#include "common/debug.h"
+#include "common/mathutil.h"
+#include "common/utilities.h"
namespace gl
{
@@ -1881,6 +1884,8 @@ const GLubyte *GL_APIENTRY GetStringi(GLenum name, GLuint index)
void GL_APIENTRY CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)
{
+ using base::IsValueInRangeForNumericType;
+ using base::internal::CheckedNumeric;
EVENT("(GLenum readTarget = 0x%X, GLenum writeTarget = 0x%X, GLintptr readOffset = %d, GLintptr writeOffset = %d, GLsizeiptr size = %d)",
readTarget, writeTarget, readOffset, writeOffset, size);
@@ -1915,20 +1920,51 @@ void GL_APIENTRY CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintp
return;
}
- if (readOffset < 0 || writeOffset < 0 || size < 0 ||
- static_cast<unsigned int>(readOffset + size) > readBuffer->getSize() ||
- static_cast<unsigned int>(writeOffset + size) > writeBuffer->getSize())
+ CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
+ CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
+ CheckedNumeric<GLintptr> checkedSize(size);
+ auto checkedReadSum = checkedReadOffset + checkedSize;
+ auto checkedWriteSum = checkedWriteOffset + checkedSize;
+
+ if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
+ !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
+ !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ if (readOffset < 0 || writeOffset < 0 || size < 0)
{
context->recordError(Error(GL_INVALID_VALUE));
return;
}
- if (readBuffer == writeBuffer && std::abs(readOffset - writeOffset) < size)
+ if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
+ checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
{
context->recordError(Error(GL_INVALID_VALUE));
return;
}
+ if (readBuffer == writeBuffer)
+ {
+ auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
+ if (!checkedOffsetDiff.IsValid())
+ {
+ // This shold not be possible.
+ UNREACHABLE();
+ context->handleError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ if (checkedOffsetDiff.ValueOrDie() < size)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ }
+
// if size is zero, the copy is a successful no-op
if (size > 0)
{