From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Alexis Hetu 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 Reviewed-by: Kenneth Russell Reviewed-by: Geoff Lang Commit-Queue: Alexis Hétu (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 65a729e05d9f9abca5ca1ca72466f68751ed602b..f523da7de61a156212ac578481b679fd626b5046 100644 --- a/src/compiler/translator/blocklayout.cpp +++ b/src/compiler/translator/blocklayout.cpp @@ -198,6 +198,13 @@ BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type, return memberInfo; } +size_t BlockLayoutEncoder::getCurrentOffset() const +{ + angle::base::CheckedNumeric checkedOffset(mCurrentOffset); + checkedOffset *= kBytesPerComponent; + return checkedOffset.ValueOrDefault(std::numeric_limits::max()); +} + size_t BlockLayoutEncoder::getShaderVariableSize(const ShaderVariable &structVar, bool isRowMajor) { size_t currentOffset = mCurrentOffset; @@ -225,7 +232,13 @@ size_t BlockLayoutEncoder::GetBlockRegisterElement(const BlockMemberInfo &info) void BlockLayoutEncoder::align(size_t baseAlignment) { - mCurrentOffset = rx::roundUp(mCurrentOffset, baseAlignment); + angle::base::CheckedNumeric checkedOffset(mCurrentOffset); + checkedOffset += baseAlignment; + checkedOffset -= 1; + angle::base::CheckedNumeric checkedAlignmentOffset = checkedOffset; + checkedAlignmentOffset %= baseAlignment; + checkedOffset -= checkedAlignmentOffset.ValueOrDefault(std::numeric_limits::max()); + mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits::max()); } // StubBlockEncoder implementation. @@ -288,7 +301,7 @@ void Std140BlockEncoder::getBlockLayoutInfo(GLenum type, baseAlignment = ComponentAlignment(numComponents); } - mCurrentOffset = rx::roundUp(mCurrentOffset, baseAlignment); + align(baseAlignment); *matrixStrideOut = matrixStride; *arrayStrideOut = arrayStride; @@ -302,16 +315,23 @@ void Std140BlockEncoder::advanceOffset(GLenum type, { if (!arraySizes.empty()) { - mCurrentOffset += arrayStride * gl::ArraySizeProduct(arraySizes); + angle::base::CheckedNumeric checkedOffset(arrayStride); + checkedOffset *= gl::ArraySizeProduct(arraySizes); + checkedOffset += mCurrentOffset; + mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits::max()); } else if (gl::IsMatrixType(type)) { - const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); - mCurrentOffset += matrixStride * numRegisters; + angle::base::CheckedNumeric checkedOffset(matrixStride); + checkedOffset *= gl::MatrixRegisterCount(type, isRowMajorMatrix); + checkedOffset += mCurrentOffset; + mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits::max()); } else { - mCurrentOffset += gl::VariableComponentCount(type); + angle::base::CheckedNumeric checkedOffset(mCurrentOffset); + checkedOffset += gl::VariableComponentCount(type); + mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits::max()); } } diff --git a/src/compiler/translator/blocklayout.h b/src/compiler/translator/blocklayout.h index 27b2247cb5f14c77577d46c9deec7308bcf1e73c..5004a5c206a6148faba29983044207046de1dcd4 100644 --- a/src/compiler/translator/blocklayout.h +++ b/src/compiler/translator/blocklayout.h @@ -80,7 +80,7 @@ class BlockLayoutEncoder const std::vector &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.