From 23ae060ebb92080fcb180c9306e3caa4edb144b4 Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Sat, 30 Jul 2022 19:28:50 +0200 Subject: [PATCH] Throw exception, if not enough data is available in the stream --- src/ImageSharp/Formats/Tga/TgaDecoderCore.cs | 83 +++++++++++++++++--- 1 file changed, 73 insertions(+), 10 deletions(-) diff --git a/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs b/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs index 18a5d02a64..af586e2544 100644 --- a/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs +++ b/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs @@ -117,7 +117,11 @@ namespace SixLabors.ImageSharp.Formats.Tga using (IMemoryOwner palette = this.memoryAllocator.Allocate(colorMapSizeInBytes, AllocationOptions.Clean)) { Span paletteSpan = palette.GetSpan(); - this.currentStream.Read(paletteSpan, this.fileHeader.CMapStart, colorMapSizeInBytes); + int bytesRead = this.currentStream.Read(paletteSpan, this.fileHeader.CMapStart, colorMapSizeInBytes); + if (bytesRead != colorMapSizeInBytes) + { + TgaThrowHelper.ThrowInvalidImageContentException("Not enough data to read the color map"); + } if (this.fileHeader.ImageType == TgaImageType.RleColorMapped) { @@ -417,7 +421,12 @@ namespace SixLabors.ImageSharp.Formats.Tga { for (int x = width - 1; x >= 0; x--) { - this.currentStream.Read(this.scratchBuffer, 0, 2); + int bytesRead = this.currentStream.Read(this.scratchBuffer, 0, 2); + if (bytesRead != 2) + { + TgaThrowHelper.ThrowInvalidImageContentException("Not enough data to read a pixel row"); + } + if (!this.hasAlpha) { this.scratchBuffer[1] |= 1 << 7; @@ -437,7 +446,11 @@ namespace SixLabors.ImageSharp.Formats.Tga } else { - this.currentStream.Read(rowSpan); + int bytesRead = this.currentStream.Read(rowSpan); + if (bytesRead != rowSpan.Length) + { + TgaThrowHelper.ThrowInvalidImageContentException("Not enough data to read a pixel row"); + } if (!this.hasAlpha) { @@ -652,7 +665,12 @@ namespace SixLabors.ImageSharp.Formats.Tga private void ReadL8Row(int width, Buffer2D pixels, Span row, int y) where TPixel : unmanaged, IPixel { - this.currentStream.Read(row); + int bytesRead = this.currentStream.Read(row); + if (bytesRead != row.Length) + { + TgaThrowHelper.ThrowInvalidImageContentException("Not enough data to read a pixel row"); + } + Span pixelSpan = pixels.DangerousGetRowSpan(y); PixelOperations.Instance.FromL8Bytes(this.Configuration, row, pixelSpan, width); } @@ -670,7 +688,12 @@ namespace SixLabors.ImageSharp.Formats.Tga private void ReadBgr24Pixel(TPixel color, int x, Span pixelSpan) where TPixel : unmanaged, IPixel { - this.currentStream.Read(this.scratchBuffer, 0, 3); + int bytesRead = this.currentStream.Read(this.scratchBuffer, 0, 3); + if (bytesRead != 3) + { + TgaThrowHelper.ThrowInvalidImageContentException("Not enough data to read a bgr pixel"); + } + color.FromBgr24(Unsafe.As(ref this.scratchBuffer[0])); pixelSpan[x] = color; } @@ -679,7 +702,12 @@ namespace SixLabors.ImageSharp.Formats.Tga private void ReadBgr24Row(int width, Buffer2D pixels, Span row, int y) where TPixel : unmanaged, IPixel { - this.currentStream.Read(row); + int bytesRead = this.currentStream.Read(row); + if (bytesRead != row.Length) + { + TgaThrowHelper.ThrowInvalidImageContentException("Not enough data to read a pixel row"); + } + Span pixelSpan = pixels.DangerousGetRowSpan(y); PixelOperations.Instance.FromBgr24Bytes(this.Configuration, row, pixelSpan, width); } @@ -688,7 +716,12 @@ namespace SixLabors.ImageSharp.Formats.Tga private void ReadBgra32Pixel(int x, TPixel color, Span pixelRow) where TPixel : unmanaged, IPixel { - this.currentStream.Read(this.scratchBuffer, 0, 4); + int bytesRead = this.currentStream.Read(this.scratchBuffer, 0, 4); + if (bytesRead != 4) + { + TgaThrowHelper.ThrowInvalidImageContentException("Not enough data to read a bgra pixel"); + } + byte alpha = this.tgaMetadata.AlphaChannelBits == 0 ? byte.MaxValue : this.scratchBuffer[3]; color.FromBgra32(new Bgra32(this.scratchBuffer[2], this.scratchBuffer[1], this.scratchBuffer[0], alpha)); pixelRow[x] = color; @@ -698,7 +731,12 @@ namespace SixLabors.ImageSharp.Formats.Tga private void ReadBgra32Row(int width, Buffer2D pixels, Span row, int y) where TPixel : unmanaged, IPixel { - this.currentStream.Read(row); + int bytesRead = this.currentStream.Read(row); + if (bytesRead != row.Length) + { + TgaThrowHelper.ThrowInvalidImageContentException("Not enough data to read a pixel row"); + } + Span pixelSpan = pixels.DangerousGetRowSpan(y); PixelOperations.Instance.FromBgra32Bytes(this.Configuration, row, pixelSpan, width); } @@ -708,6 +746,11 @@ namespace SixLabors.ImageSharp.Formats.Tga where TPixel : unmanaged, IPixel { int colorIndex = this.currentStream.ReadByte(); + if (colorIndex == -1) + { + TgaThrowHelper.ThrowInvalidImageContentException("Not enough data to read color index"); + } + this.ReadPalettedBgra16Pixel(palette, colorIndex, colorMapPixelSizeInBytes, ref color); pixelRow[x] = color; } @@ -733,6 +776,11 @@ namespace SixLabors.ImageSharp.Formats.Tga where TPixel : unmanaged, IPixel { int colorIndex = this.currentStream.ReadByte(); + if (colorIndex == -1) + { + TgaThrowHelper.ThrowInvalidImageContentException("Not enough data to read color index"); + } + color.FromBgr24(Unsafe.As(ref palette[colorIndex * colorMapPixelSizeInBytes])); pixelRow[x] = color; } @@ -742,6 +790,11 @@ namespace SixLabors.ImageSharp.Formats.Tga where TPixel : unmanaged, IPixel { int colorIndex = this.currentStream.ReadByte(); + if (colorIndex == -1) + { + TgaThrowHelper.ThrowInvalidImageContentException("Not enough data to read color index"); + } + color.FromBgra32(Unsafe.As(ref palette[colorIndex * colorMapPixelSizeInBytes])); pixelRow[x] = color; } @@ -767,7 +820,12 @@ namespace SixLabors.ImageSharp.Formats.Tga if (highBit == 1) { int runLength = runLengthByte & 127; - this.currentStream.Read(pixel, 0, bytesPerPixel); + int bytesRead = this.currentStream.Read(pixel, 0, bytesPerPixel); + if (bytesRead != bytesPerPixel) + { + TgaThrowHelper.ThrowInvalidImageContentException("Not enough data to read a pixel from the stream"); + } + int bufferIdx = uncompressedPixels * bytesPerPixel; for (int i = 0; i < runLength + 1; i++, uncompressedPixels++) { @@ -782,7 +840,12 @@ namespace SixLabors.ImageSharp.Formats.Tga int bufferIdx = uncompressedPixels * bytesPerPixel; for (int i = 0; i < runLength + 1; i++, uncompressedPixels++) { - this.currentStream.Read(pixel, 0, bytesPerPixel); + int bytesRead = this.currentStream.Read(pixel, 0, bytesPerPixel); + if (bytesRead != bytesPerPixel) + { + TgaThrowHelper.ThrowInvalidImageContentException("Not enough data to read a pixel from the stream"); + } + pixel.CopyTo(buffer.Slice(bufferIdx)); bufferIdx += bytesPerPixel; }