|
@@ -0,0 +1,125 @@
|
|
|
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
+From: Alexis Hetu <[email protected]>
|
|
|
+Date: Wed, 15 Sep 2021 13:40:28 -0400
|
|
|
+Subject: Fix integer overflow in BlockLayoutEncoder
|
|
|
+MIME-Version: 1.0
|
|
|
+Content-Type: text/plain; charset=UTF-8
|
|
|
+Content-Transfer-Encoding: 8bit
|
|
|
+
|
|
|
+BlockLayoutEncoder::mCurrentOffset's computation had the
|
|
|
+possibility of causing integer overflows in multiple places,
|
|
|
+so this CL adds CheckedNumeric variables in a number of
|
|
|
+these occurrences in order to prevent integer overflows and
|
|
|
+causing issues.
|
|
|
+
|
|
|
+The issue in this case was an integer overflow causing the
|
|
|
+code in ValidateTypeSizeLimitations.cpp to use an invalid
|
|
|
+result from "layoutEncoder.getCurrentOffset()", which ended
|
|
|
+up compiling a shader which would later cause an OOM error.
|
|
|
+
|
|
|
+Bug: chromium:1248665
|
|
|
+Change-Id: I688d669f21c6dc2957e43bdf91f8f8f08180a6f7
|
|
|
+Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3163356
|
|
|
+Reviewed-by: Jamie Madill <[email protected]>
|
|
|
+Reviewed-by: Kenneth Russell <[email protected]>
|
|
|
+Reviewed-by: Geoff Lang <[email protected]>
|
|
|
+Commit-Queue: Alexis Hétu <[email protected]>
|
|
|
+(cherry picked from commit 158ef351fc8b827c201e056a8ddba50fd4235671)
|
|
|
+Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3194392
|
|
|
+
|
|
|
+diff --git a/src/compiler/translator/blocklayout.cpp b/src/compiler/translator/blocklayout.cpp
|
|
|
+index 0539923bc75f5b88228dcb387c8aba4c701edc1b..1e6b143a1e1ee9a127b71685febd36416a8840f6 100644
|
|
|
+--- a/src/compiler/translator/blocklayout.cpp
|
|
|
++++ b/src/compiler/translator/blocklayout.cpp
|
|
|
+@@ -199,6 +199,13 @@ BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type,
|
|
|
+ return memberInfo;
|
|
|
+ }
|
|
|
+
|
|
|
++size_t BlockLayoutEncoder::getCurrentOffset() const
|
|
|
++{
|
|
|
++ angle::base::CheckedNumeric<size_t> checkedOffset(mCurrentOffset);
|
|
|
++ checkedOffset *= kBytesPerComponent;
|
|
|
++ return checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
|
|
|
++}
|
|
|
++
|
|
|
+ size_t BlockLayoutEncoder::getShaderVariableSize(const ShaderVariable &structVar, bool isRowMajor)
|
|
|
+ {
|
|
|
+ size_t currentOffset = mCurrentOffset;
|
|
|
+@@ -226,7 +233,13 @@ size_t BlockLayoutEncoder::GetBlockRegisterElement(const BlockMemberInfo &info)
|
|
|
+
|
|
|
+ void BlockLayoutEncoder::align(size_t baseAlignment)
|
|
|
+ {
|
|
|
+- mCurrentOffset = rx::roundUp<size_t>(mCurrentOffset, baseAlignment);
|
|
|
++ angle::base::CheckedNumeric<size_t> checkedOffset(mCurrentOffset);
|
|
|
++ checkedOffset += baseAlignment;
|
|
|
++ checkedOffset -= 1;
|
|
|
++ angle::base::CheckedNumeric<size_t> checkedAlignmentOffset = checkedOffset;
|
|
|
++ checkedAlignmentOffset %= baseAlignment;
|
|
|
++ checkedOffset -= checkedAlignmentOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
|
|
|
++ mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
|
|
|
+ }
|
|
|
+
|
|
|
+ // StubBlockEncoder implementation.
|
|
|
+@@ -289,7 +302,7 @@ void Std140BlockEncoder::getBlockLayoutInfo(GLenum type,
|
|
|
+ baseAlignment = ComponentAlignment(numComponents);
|
|
|
+ }
|
|
|
+
|
|
|
+- mCurrentOffset = rx::roundUp(mCurrentOffset, baseAlignment);
|
|
|
++ align(baseAlignment);
|
|
|
+
|
|
|
+ *matrixStrideOut = matrixStride;
|
|
|
+ *arrayStrideOut = arrayStride;
|
|
|
+@@ -303,16 +316,23 @@ void Std140BlockEncoder::advanceOffset(GLenum type,
|
|
|
+ {
|
|
|
+ if (!arraySizes.empty())
|
|
|
+ {
|
|
|
+- mCurrentOffset += arrayStride * gl::ArraySizeProduct(arraySizes);
|
|
|
++ angle::base::CheckedNumeric<size_t> checkedOffset(arrayStride);
|
|
|
++ checkedOffset *= gl::ArraySizeProduct(arraySizes);
|
|
|
++ checkedOffset += mCurrentOffset;
|
|
|
++ mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
|
|
|
+ }
|
|
|
+ else if (gl::IsMatrixType(type))
|
|
|
+ {
|
|
|
+- const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
|
|
|
+- mCurrentOffset += matrixStride * numRegisters;
|
|
|
++ angle::base::CheckedNumeric<size_t> checkedOffset(matrixStride);
|
|
|
++ checkedOffset *= gl::MatrixRegisterCount(type, isRowMajorMatrix);
|
|
|
++ checkedOffset += mCurrentOffset;
|
|
|
++ mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+- mCurrentOffset += gl::VariableComponentCount(type);
|
|
|
++ angle::base::CheckedNumeric<size_t> checkedOffset(mCurrentOffset);
|
|
|
++ checkedOffset += gl::VariableComponentCount(type);
|
|
|
++ mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+diff --git a/src/compiler/translator/blocklayout.h b/src/compiler/translator/blocklayout.h
|
|
|
+index 726d76fa178f77a978ff2c82ec20fb8f1ad03f0b..ff90a2487830b365697ce41d660a689857b75319 100644
|
|
|
+--- a/src/compiler/translator/blocklayout.h
|
|
|
++++ b/src/compiler/translator/blocklayout.h
|
|
|
+@@ -80,7 +80,7 @@ class BlockLayoutEncoder
|
|
|
+ const std::vector<unsigned int> &arraySizes,
|
|
|
+ bool isRowMajorMatrix);
|
|
|
+
|
|
|
+- size_t getCurrentOffset() const { return mCurrentOffset * kBytesPerComponent; }
|
|
|
++ size_t getCurrentOffset() const;
|
|
|
+ size_t getShaderVariableSize(const ShaderVariable &structVar, bool isRowMajor);
|
|
|
+
|
|
|
+ // Called when entering/exiting a structure variable.
|
|
|
+diff --git a/src/tests/gl_tests/WebGLCompatibilityTest.cpp b/src/tests/gl_tests/WebGLCompatibilityTest.cpp
|
|
|
+index f57e3c6e012788666186b532fad6fc2d07d9d4b7..35cadfd7312ab1cd77c7d153c6a25b5cd47d9fe8 100644
|
|
|
+--- a/src/tests/gl_tests/WebGLCompatibilityTest.cpp
|
|
|
++++ b/src/tests/gl_tests/WebGLCompatibilityTest.cpp
|
|
|
+@@ -5047,7 +5047,7 @@ void main()
|
|
|
+
|
|
|
+ constexpr char kVSArrayMuchTooLarge[] =
|
|
|
+ R"(varying vec4 color;
|
|
|
+-const int array_size = 795418649;
|
|
|
++const int array_size = 556007917;
|
|
|
+ void main()
|
|
|
+ {
|
|
|
+ mat2 array[array_size];
|