summaryrefslogtreecommitdiff
path: root/src/video_core/textures/astc.cpp
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2021-01-15 02:15:04 -0300
committerGravatar ReinUsesLisp2021-01-15 02:24:36 -0300
commit0ec71b78fb248eae6b6fbbb3f5735b2f9646fd62 (patch)
treecc9e78548bd7c2bae9cce294e17280936f8e581b /src/video_core/textures/astc.cpp
parentMerge pull request #5302 from lat9nq/appimage-update (diff)
downloadyuzu-0ec71b78fb248eae6b6fbbb3f5735b2f9646fd62.tar.gz
yuzu-0ec71b78fb248eae6b6fbbb3f5735b2f9646fd62.tar.xz
yuzu-0ec71b78fb248eae6b6fbbb3f5735b2f9646fd62.zip
astc: Return zero on out of bound bits
Avoid out of bound reads on invalid ASTC textures. Games can bind invalid textures that make us read or write out of bounds.
Diffstat (limited to 'src/video_core/textures/astc.cpp')
-rw-r--r--src/video_core/textures/astc.cpp39
1 files changed, 22 insertions, 17 deletions
diff --git a/src/video_core/textures/astc.cpp b/src/video_core/textures/astc.cpp
index acd5bdd78..1f1c3bd3a 100644
--- a/src/video_core/textures/astc.cpp
+++ b/src/video_core/textures/astc.cpp
@@ -42,21 +42,24 @@ constexpr u32 Popcnt(u32 n) {
42 42
43class InputBitStream { 43class InputBitStream {
44public: 44public:
45 constexpr explicit InputBitStream(const u8* ptr, std::size_t start_offset = 0) 45 constexpr explicit InputBitStream(std::span<const u8> data, size_t start_offset = 0)
46 : cur_byte{ptr}, next_bit{start_offset % 8} {} 46 : cur_byte{data.data()}, total_bits{data.size()}, next_bit{start_offset % 8} {}
47 47
48 constexpr std::size_t GetBitsRead() const { 48 constexpr size_t GetBitsRead() const {
49 return bits_read; 49 return bits_read;
50 } 50 }
51 51
52 constexpr bool ReadBit() { 52 constexpr bool ReadBit() {
53 const bool bit = (*cur_byte >> next_bit++) & 1; 53 if (bits_read >= total_bits * 8) {
54 return 0;
55 }
56 const bool bit = ((*cur_byte >> next_bit) & 1) != 0;
57 ++next_bit;
54 while (next_bit >= 8) { 58 while (next_bit >= 8) {
55 next_bit -= 8; 59 next_bit -= 8;
56 cur_byte++; 60 ++cur_byte;
57 } 61 }
58 62 ++bits_read;
59 bits_read++;
60 return bit; 63 return bit;
61 } 64 }
62 65
@@ -79,8 +82,9 @@ public:
79 82
80private: 83private:
81 const u8* cur_byte; 84 const u8* cur_byte;
82 std::size_t next_bit = 0; 85 size_t total_bits = 0;
83 std::size_t bits_read = 0; 86 size_t next_bit = 0;
87 size_t bits_read = 0;
84}; 88};
85 89
86class OutputBitStream { 90class OutputBitStream {
@@ -200,8 +204,8 @@ using IntegerEncodedVector = boost::container::static_vector<
200 204
201static void DecodeTritBlock(InputBitStream& bits, IntegerEncodedVector& result, u32 nBitsPerValue) { 205static void DecodeTritBlock(InputBitStream& bits, IntegerEncodedVector& result, u32 nBitsPerValue) {
202 // Implement the algorithm in section C.2.12 206 // Implement the algorithm in section C.2.12
203 u32 m[5]; 207 std::array<u32, 5> m;
204 u32 t[5]; 208 std::array<u32, 5> t;
205 u32 T; 209 u32 T;
206 210
207 // Read the trit encoded block according to 211 // Read the trit encoded block according to
@@ -866,7 +870,7 @@ public:
866 } 870 }
867}; 871};
868 872
869static void DecodeColorValues(u32* out, u8* data, const u32* modes, const u32 nPartitions, 873static void DecodeColorValues(u32* out, std::span<u8> data, const u32* modes, const u32 nPartitions,
870 const u32 nBitsForColorData) { 874 const u32 nBitsForColorData) {
871 // First figure out how many color values we have 875 // First figure out how many color values we have
872 u32 nValues = 0; 876 u32 nValues = 0;
@@ -898,7 +902,7 @@ static void DecodeColorValues(u32* out, u8* data, const u32* modes, const u32 nP
898 // We now have enough to decode our integer sequence. 902 // We now have enough to decode our integer sequence.
899 IntegerEncodedVector decodedColorValues; 903 IntegerEncodedVector decodedColorValues;
900 904
901 InputBitStream colorStream(data); 905 InputBitStream colorStream(data, 0);
902 DecodeIntegerSequence(decodedColorValues, colorStream, range, nValues); 906 DecodeIntegerSequence(decodedColorValues, colorStream, range, nValues);
903 907
904 // Once we have the decoded values, we need to dequantize them to the 0-255 range 908 // Once we have the decoded values, we need to dequantize them to the 0-255 range
@@ -1441,7 +1445,7 @@ static void ComputeEndpos32s(Pixel& ep1, Pixel& ep2, const u32*& colorValues,
1441 1445
1442static void DecompressBlock(std::span<const u8, 16> inBuf, const u32 blockWidth, 1446static void DecompressBlock(std::span<const u8, 16> inBuf, const u32 blockWidth,
1443 const u32 blockHeight, std::span<u32, 12 * 12> outBuf) { 1447 const u32 blockHeight, std::span<u32, 12 * 12> outBuf) {
1444 InputBitStream strm(inBuf.data()); 1448 InputBitStream strm(inBuf);
1445 TexelWeightParams weightParams = DecodeBlockInfo(strm); 1449 TexelWeightParams weightParams = DecodeBlockInfo(strm);
1446 1450
1447 // Was there an error? 1451 // Was there an error?
@@ -1619,15 +1623,16 @@ static void DecompressBlock(std::span<const u8, 16> inBuf, const u32 blockWidth,
1619 1623
1620 // Make sure that higher non-texel bits are set to zero 1624 // Make sure that higher non-texel bits are set to zero
1621 const u32 clearByteStart = (weightParams.GetPackedBitSize() >> 3) + 1; 1625 const u32 clearByteStart = (weightParams.GetPackedBitSize() >> 3) + 1;
1622 if (clearByteStart > 0) { 1626 if (clearByteStart > 0 && clearByteStart <= texelWeightData.size()) {
1623 texelWeightData[clearByteStart - 1] &= 1627 texelWeightData[clearByteStart - 1] &=
1624 static_cast<u8>((1 << (weightParams.GetPackedBitSize() % 8)) - 1); 1628 static_cast<u8>((1 << (weightParams.GetPackedBitSize() % 8)) - 1);
1629 std::memset(texelWeightData.data() + clearByteStart, 0,
1630 std::min(16U - clearByteStart, 16U));
1625 } 1631 }
1626 std::memset(texelWeightData.data() + clearByteStart, 0, std::min(16U - clearByteStart, 16U));
1627 1632
1628 IntegerEncodedVector texelWeightValues; 1633 IntegerEncodedVector texelWeightValues;
1629 1634
1630 InputBitStream weightStream(texelWeightData.data()); 1635 InputBitStream weightStream(texelWeightData);
1631 1636
1632 DecodeIntegerSequence(texelWeightValues, weightStream, weightParams.m_MaxWeight, 1637 DecodeIntegerSequence(texelWeightValues, weightStream, weightParams.m_MaxWeight,
1633 weightParams.GetNumWeightValues()); 1638 weightParams.GetNumWeightValues());