summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2016-12-02 16:57:19 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-03-20 16:01:41 +0000
commit5bb09b5f95e014c8e2c684bb6a4b00115b66ebc1 (patch)
tree0d03d99bcf55e2adbf284648eefe5fb8f08c4452
parent929be7c02f99726d2c887d291ad914a91e005402 (diff)
[Backport] Use safe math in ValidateCopyBufferSubData.
This should fix any potential out of bounds reads/writes. BUG=chromium:660854 Change-Id: Iffa00e4551d7362115cbf023a09b1d0e15f724c8 Reviewed-on: https://chromium-review.googlesource.com/405816 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: Corentin Wallez <cwallez@chromium.org> (CVE-2016-5221) Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
-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)
{