From 6d6b0f475e72eb5f4235cd0cc7c77f25545af80b Mon Sep 17 00:00:00 2001 From: colinator27 <17358554+colinator27@users.noreply.github.com> Date: Fri, 23 Aug 2024 14:43:36 -0400 Subject: [PATCH 1/2] Add negative length checks during deserialization --- UndertaleModLib/Models/UndertaleSprite.cs | 4 ++-- UndertaleModLib/UndertaleChunks.cs | 2 +- UndertaleModLib/Util/AdaptiveBinaryReader.cs | 2 +- UndertaleModLib/Util/BufferBinaryReader.cs | 21 ++++++++++++++++++++ UndertaleModLib/Util/FileBinaryReader.cs | 12 +++++++++++ 5 files changed, 37 insertions(+), 4 deletions(-) diff --git a/UndertaleModLib/Models/UndertaleSprite.cs b/UndertaleModLib/Models/UndertaleSprite.cs index 410b2bc16..3f89049fd 100644 --- a/UndertaleModLib/Models/UndertaleSprite.cs +++ b/UndertaleModLib/Models/UndertaleSprite.cs @@ -764,13 +764,13 @@ public static uint UnserializeChildObjectCount(UndertaleReader reader) switch (spineVersion) { case 1: - reader.Position += 8 + jsonLength + atlasLength + textures; + reader.Position += 8 + (uint)jsonLength + (uint)atlasLength + (uint)textures; break; case 2: case 3: { - reader.Position += jsonLength + atlasLength; + reader.Position += (uint)jsonLength + (uint)atlasLength; // TODO: make this return count instead if spine sprite // couldn't have sequence or nine slices data. diff --git a/UndertaleModLib/UndertaleChunks.cs b/UndertaleModLib/UndertaleChunks.cs index c6a0ec8d4..55466bc2d 100644 --- a/UndertaleModLib/UndertaleChunks.cs +++ b/UndertaleModLib/UndertaleChunks.cs @@ -1167,7 +1167,7 @@ private void CheckForTileCompression(UndertaleReader reader) reader.Position += 32; int effectCount = reader.ReadInt32(); - reader.Position += effectCount * 12 + 4; + reader.Position += (uint)effectCount * 12 + 4; int tileMapWidth = reader.ReadInt32(); int tileMapHeight = reader.ReadInt32(); diff --git a/UndertaleModLib/Util/AdaptiveBinaryReader.cs b/UndertaleModLib/Util/AdaptiveBinaryReader.cs index 5522678f0..efe5dadb4 100644 --- a/UndertaleModLib/Util/AdaptiveBinaryReader.cs +++ b/UndertaleModLib/Util/AdaptiveBinaryReader.cs @@ -87,7 +87,7 @@ public long AbsPosition if (isUsingBufferReader) { #if DEBUG - if (value > Length) + if (value < 0 || value > Length) throw new IOException("Reading out of bounds."); #endif bufferBinaryReader.Position = value - bufferBinaryReader.ChunkStartPosition + 8; diff --git a/UndertaleModLib/Util/BufferBinaryReader.cs b/UndertaleModLib/Util/BufferBinaryReader.cs index 4fded571d..17a12f3d9 100644 --- a/UndertaleModLib/Util/BufferBinaryReader.cs +++ b/UndertaleModLib/Util/BufferBinaryReader.cs @@ -27,6 +27,11 @@ public ChunkBuffer(int capacity) public int Read(byte[] buffer, int count) { + if (count < 0) + { + throw new ArgumentOutOfRangeException(nameof(count)); + } + int n = _length - _position; if (n > count) n = count; @@ -75,6 +80,9 @@ public byte ReadByte() public void Write(byte[] buffer, int count) { + if (count < 0) + throw new ArgumentOutOfRangeException(nameof(count)); + int i = _position + count; if (i < 0) throw new IOException("Writing out of the chunk buffer bounds."); @@ -174,6 +182,10 @@ public virtual bool ReadBoolean() public string ReadChars(int count) { + if (count < 0) + { + throw new ArgumentOutOfRangeException(nameof(count)); + } if (chunkBuffer.Position + count > _length) { throw new IOException("Reading out of chunk bounds"); @@ -198,6 +210,10 @@ public string ReadChars(int count) public byte[] ReadBytes(int count) { + if (count < 0) + { + throw new ArgumentOutOfRangeException(nameof(count)); + } if (chunkBuffer.Position + count > _length) { throw new IOException("Reading out of chunk bounds"); @@ -268,6 +284,8 @@ public string ReadGMString() int length = BinaryPrimitives.ReadInt32LittleEndian(ReadToBuffer(4)); + if (length < 0) + throw new IOException("Invalid string length"); if (chunkBuffer.Position + length + 1 >= _length) throw new IOException("Reading out of chunk bounds"); @@ -293,9 +311,12 @@ public string ReadGMString() return res; } + public void SkipGMString() { int length = BinaryPrimitives.ReadInt32LittleEndian(ReadToBuffer(4)); + if (length < 0) + throw new IOException("Invalid string length"); Position += (uint)length + 1; } diff --git a/UndertaleModLib/Util/FileBinaryReader.cs b/UndertaleModLib/Util/FileBinaryReader.cs index 87525d226..8275f86a2 100644 --- a/UndertaleModLib/Util/FileBinaryReader.cs +++ b/UndertaleModLib/Util/FileBinaryReader.cs @@ -63,6 +63,10 @@ public virtual bool ReadBoolean() public string ReadChars(int count) { + if (count < 0) + { + throw new ArgumentOutOfRangeException(nameof(count)); + } #if DEBUG if (Stream.Position + count > _length) throw new IOException("Reading out of bounds"); @@ -85,6 +89,10 @@ public string ReadChars(int count) public byte[] ReadBytes(int count) { + if (count < 0) + { + throw new ArgumentOutOfRangeException(nameof(count)); + } #if DEBUG if (Stream.Position + count > _length) throw new IOException("Reading out of bounds"); @@ -193,6 +201,8 @@ public string ReadGMString() throw new IOException("Reading out of bounds"); #endif int length = BinaryPrimitives.ReadInt32LittleEndian(ReadToBuffer(4)); + if (length < 0) + throw new IOException("Invalid string length"); #if DEBUG if (Stream.Position + length + 1 >= _length) throw new IOException("Reading out of bounds"); @@ -222,6 +232,8 @@ public string ReadGMString() public void SkipGMString() { int length = BinaryPrimitives.ReadInt32LittleEndian(ReadToBuffer(4)); + if (length < 0) + throw new IOException("Invalid string length"); Position += (uint)length + 1; } From 28d7c874e94c7e4198b83f66b6476777e0cbb3b7 Mon Sep 17 00:00:00 2001 From: colinator27 <17358554+colinator27@users.noreply.github.com> Date: Fri, 23 Aug 2024 14:57:05 -0400 Subject: [PATCH 2/2] Fix missing parenthesis --- UndertaleModLib/Util/AdaptiveBinaryReader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UndertaleModLib/Util/AdaptiveBinaryReader.cs b/UndertaleModLib/Util/AdaptiveBinaryReader.cs index fe5829990..42392484d 100644 --- a/UndertaleModLib/Util/AdaptiveBinaryReader.cs +++ b/UndertaleModLib/Util/AdaptiveBinaryReader.cs @@ -86,7 +86,7 @@ public long AbsPosition { if (isUsingBufferReader) { - if (value < 0 || value > Length + if (value < 0 || value > Length) throw new IOException("Reading out of bounds."); bufferBinaryReader.Position = value - bufferBinaryReader.ChunkStartPosition + 8; }