From fddd469ed1f00ec84bec6f13954e530e50771675 Mon Sep 17 00:00:00 2001 From: Jason Finch Date: Sun, 18 Oct 2026 09:26:26 +1000 Subject: [PATCH 1/2] Validate BMP bit depth and pixel data length before allocating the image An uncompressed bitmap with a bit depth other than 1, 2, 4, 8, 16, 24 or 32 was accepted by Identify, and Load failed with an ImageFormatException or a NotSupportedException depending on the depth. The header reader now rejects such depths with an InvalidImageContentException, so identification and decoding agree. An uncompressed or bit fields header could also declare far more pixel data than the stream holds. The decoder allocated the full pixel buffer before the first row read failed, and a single short row decoded without error. The declared pixel data is now checked against the remaining stream before the image is allocated; only the padding of the last row may be missing. --- src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs | 38 +++++++- .../Formats/Bmp/BmpDecoderTests.cs | 86 +++++++++++++++++++ 2 files changed, 120 insertions(+), 4 deletions(-) diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index 95f02503e9..bc80d5bbfa 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -133,6 +133,33 @@ protected override Image Decode(BufferedReadStream stream, Cance int bytesPerColorMapEntry = this.ReadImageHeaders(stream, out bool inverted, out byte[] palette); ushort bitsPerPixel = this.infoHeader.BitsPerPixel; + // Uncompressed pixel data has a size fixed by the header, so a header that declares more data than the + // stream holds is rejected before the pixel buffer is allocated. Otherwise a small file could make the + // decoder allocate a buffer for its declared dimensions before the first row read fails. + // The bit fields reader decodes every depth other than 16 as 32 bits per pixel. + int storedBitsPerPixel = this.infoHeader.Compression switch + { + BmpCompression.RGB => bitsPerPixel, + BmpCompression.BitFields or BmpCompression.BI_ALPHABITFIELDS => bitsPerPixel is 16 ? 16 : 32, + _ => 0 + }; + + if (storedBitsPerPixel > 0) + { + // Every row is padded to a multiple of four bytes. The padding of the last row is not required, + // because the row readers accept a short final read. Long arithmetic keeps the sizes of + // oversized declared dimensions from overflowing. + long rowBits = (long)this.infoHeader.Width * storedBitsPerPixel; + long stride = (rowBits + 31) / 32 * 4; + long requiredLength = (stride * (this.infoHeader.Height - 1)) + ((rowBits + 7) / 8); + long remainingLength = stream.Length - stream.Position; + if (requiredLength > remainingLength) + { + BmpThrowHelper.ThrowInvalidImageContentException( + $"The bitmap declares {requiredLength} bytes of pixel data, but only {remainingLength} bytes remain in the stream."); + } + } + image = new Image(this.configuration, this.infoHeader.Width, this.infoHeader.Height, this.metadata); Buffer2D pixels = image.GetRootFramePixelBuffer(); @@ -185,10 +212,6 @@ protected override Image Decode(BufferedReadStream stream, Cance break; - case BmpCompression.RGB when bitsPerPixel is <= 0 or > 32: - BmpThrowHelper.ThrowInvalidImageContentException($"Invalid bits per pixel: {bitsPerPixel}"); - break; - case BmpCompression.RLE24: this.ReadRle24(stream, pixels, this.infoHeader.Width, this.infoHeader.Height, inverted); @@ -1573,6 +1596,13 @@ private int ReadImageHeaders(BufferedReadStream stream, out bool inverted, out b BmpThrowHelper.ThrowInvalidImageContentException("Width and height must be greater than 0."); } + // Uncompressed pixel data is only defined for these depths. Rejecting any other depth here, rather than in + // the pixel readers, also keeps identification from reporting a header that cannot be decoded. + if (this.infoHeader.Compression is BmpCompression.RGB && this.infoHeader.BitsPerPixel is not (1 or 2 or 4 or 8 or 16 or 24 or 32)) + { + BmpThrowHelper.ThrowInvalidImageContentException($"Invalid bits per pixel: {this.infoHeader.BitsPerPixel}"); + } + int bytesPerColorMapEntry = 4; int colorMapSizeBytes = -1; if (this.infoHeader.ClrUsed == 0) diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs index 1702657892..344ffa35dc 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System.Buffers.Binary; using Microsoft.DotNet.RemoteExecutor; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats.Bmp; @@ -8,6 +9,7 @@ using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Tests.Memory; using SixLabors.ImageSharp.Tests.TestUtilities; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; using SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs; @@ -696,4 +698,88 @@ public void BmpDecoder_ThrowsException_Issue3074() using Image image = Image.Load(stream); }); } + + [Theory] + [InlineData(0)] + [InlineData(3)] + [InlineData(7)] + [InlineData(12)] + [InlineData(33)] + public void BmpDecoder_InvalidUncompressedBitsPerPixel_ThrowsInvalidImageContentException(short bitsPerPixel) + { + byte[] data = CreateUncompressedBitmap(2, 2, bitsPerPixel, 8); + + Assert.Throws(() => Image.Identify(data)); + Assert.Throws(() => + { + using Image image = Image.Load(data); + }); + } + + [Theory] + [InlineData(4000, 4000)] + [InlineData(100000, 1)] + public void BmpDecoder_PixelDataSmallerThanDeclared_ThrowsBeforeAllocatingPixelBuffer(int width, int height) + { + byte[] data = CreateUncompressedBitmap(width, height, 24, 72); + TestMemoryAllocator allocator = new(); + allocator.EnableNonThreadSafeLogging(); + Configuration configuration = Configuration.Default.Clone(); + configuration.MemoryAllocator = allocator; + DecoderOptions options = new() { Configuration = configuration }; + + Assert.Throws(() => + { + using Image image = Image.Load(options, data); + }); + + // The rejection must happen before the Rgba32 pixel buffer for the declared dimensions is requested. + Assert.DoesNotContain(allocator.AllocationLog, request => request.LengthInBytes >= width * height * 4); + } + + [Fact] + public void BmpDecoder_MissingLastRowPadding_Decodes() + { + using Image expected = new(1, 2); + expected[0, 0] = new Rgb24(255, 0, 0); + expected[0, 1] = new Rgb24(0, 0, 255); + + using MemoryStream stream = new(); + expected.SaveAsBmp(stream, new BmpEncoder { BitsPerPixel = BmpBitsPerPixel.Bit24 }); + + // Each 24-bit row of one pixel holds three bytes of pixel data and one byte of padding. + // The pixel data is at the end of the file, so dropping the last byte removes the padding of the last row. + byte[] data = stream.ToArray()[..^1]; + + using Image actual = Image.Load(data); + + Assert.Equal(expected[0, 0], actual[0, 0]); + Assert.Equal(expected[0, 1], actual[0, 1]); + } + + /// + /// Creates a bitmap with a file header, a 40-byte BITMAPINFOHEADER without compression, and zeroed pixel data. + /// + /// The declared width. + /// The declared height. + /// The declared bits per pixel. + /// The number of pixel data bytes that follow the headers. + /// The encoded bitmap. + private static byte[] CreateUncompressedBitmap(int width, int height, short bitsPerPixel, int pixelDataLength) + { + const int pixelDataOffset = 54; + byte[] bmp = new byte[pixelDataOffset + pixelDataLength]; + Span span = bmp; + span[0] = (byte)'B'; + span[1] = (byte)'M'; + BinaryPrimitives.WriteInt32LittleEndian(span[2..], bmp.Length); + BinaryPrimitives.WriteInt32LittleEndian(span[10..], pixelDataOffset); + BinaryPrimitives.WriteInt32LittleEndian(span[14..], 40); + BinaryPrimitives.WriteInt32LittleEndian(span[18..], width); + BinaryPrimitives.WriteInt32LittleEndian(span[22..], height); + BinaryPrimitives.WriteInt16LittleEndian(span[26..], 1); + BinaryPrimitives.WriteInt16LittleEndian(span[28..], bitsPerPixel); + + return bmp; + } } From ae46b5651d8db1009c85cefcf309f4c18ceb849f Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 27 Oct 2026 13:39:45 +1000 Subject: [PATCH 2/2] Fix BMP length-check overflow and use stored regression inputs Count available complete rows after reserving the final row's pixel bytes. This avoids long overflow for maximum 32-bit BMP dimensions and rejects impossible dimensions before any pixel buffer request in every integrity mode. Retain missing final padding and both stored row orders. Replace the PR's runtime BMP builder and encoder-generated input with 13 fixed files (1228 bytes total). Independently check their headers, lengths, masks, and intended truncations; Pillow also verifies both valid pixel arrays. Extend allocation assertions to detect any Rgba32 allocation, including split buffers, rather than only one allocation the size of the complete image. Current main fails 11 malformed-file cases; the original patch still fails the maximum-dimension regression. Release .NET 10: 392 BMP/ICO/CUR/ANI tests and 50 general format/dimension tests pass with the corrected patch. --- src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs | 20 ++- .../Formats/Bmp/BmpDecoderTests.cs | 127 ++++++++---------- tests/ImageSharp.Tests/TestImages.cs | 13 ++ .../Input/Bmp/headers/invalid-rgb-depth-0.bmp | 3 + .../Bmp/headers/invalid-rgb-depth-12.bmp | 3 + .../Input/Bmp/headers/invalid-rgb-depth-3.bmp | 3 + .../Bmp/headers/invalid-rgb-depth-33.bmp | 3 + .../Input/Bmp/headers/invalid-rgb-depth-7.bmp | 3 + .../missing-final-padding-top-down.bmp | 3 + .../Bmp/headers/missing-final-padding.bmp | 3 + .../headers/truncated-alphabitfields32.bmp | 3 + .../Bmp/headers/truncated-bitfields16.bmp | 3 + .../Bmp/headers/truncated-bitfields32.bmp | 3 + .../Bmp/headers/truncated-rgb24-100000x1.bmp | 3 + .../Bmp/headers/truncated-rgb24-4000x4000.bmp | 3 + .../truncated-rgb32-max-dimensions.bmp | 3 + 16 files changed, 120 insertions(+), 79 deletions(-) create mode 100644 tests/Images/Input/Bmp/headers/invalid-rgb-depth-0.bmp create mode 100644 tests/Images/Input/Bmp/headers/invalid-rgb-depth-12.bmp create mode 100644 tests/Images/Input/Bmp/headers/invalid-rgb-depth-3.bmp create mode 100644 tests/Images/Input/Bmp/headers/invalid-rgb-depth-33.bmp create mode 100644 tests/Images/Input/Bmp/headers/invalid-rgb-depth-7.bmp create mode 100644 tests/Images/Input/Bmp/headers/missing-final-padding-top-down.bmp create mode 100644 tests/Images/Input/Bmp/headers/missing-final-padding.bmp create mode 100644 tests/Images/Input/Bmp/headers/truncated-alphabitfields32.bmp create mode 100644 tests/Images/Input/Bmp/headers/truncated-bitfields16.bmp create mode 100644 tests/Images/Input/Bmp/headers/truncated-bitfields32.bmp create mode 100644 tests/Images/Input/Bmp/headers/truncated-rgb24-100000x1.bmp create mode 100644 tests/Images/Input/Bmp/headers/truncated-rgb24-4000x4000.bmp create mode 100644 tests/Images/Input/Bmp/headers/truncated-rgb32-max-dimensions.bmp diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index bc80d5bbfa..c853341b94 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -133,10 +133,9 @@ protected override Image Decode(BufferedReadStream stream, Cance int bytesPerColorMapEntry = this.ReadImageHeaders(stream, out bool inverted, out byte[] palette); ushort bitsPerPixel = this.infoHeader.BitsPerPixel; - // Uncompressed pixel data has a size fixed by the header, so a header that declares more data than the - // stream holds is rejected before the pixel buffer is allocated. Otherwise a small file could make the - // decoder allocate a buffer for its declared dimensions before the first row read fails. - // The bit fields reader decodes every depth other than 16 as 32 bits per pixel. + // Reject impossible RGB and bit-fields dimensions before allocating the image. Ignoring image data errors + // does not make these dimensions safe: a tiny file could otherwise request a large pixel buffer. + // Match ReadBitFields, which uses 32-bit storage for every depth other than 16. int storedBitsPerPixel = this.infoHeader.Compression switch { BmpCompression.RGB => bitsPerPixel, @@ -146,17 +145,16 @@ protected override Image Decode(BufferedReadStream stream, Cance if (storedBitsPerPixel > 0) { - // Every row is padded to a multiple of four bytes. The padding of the last row is not required, - // because the row readers accept a short final read. Long arithmetic keeps the sizes of - // oversized declared dimensions from overflowing. + // Stored rows start on four-byte boundaries. Retain support for missing padding after the final row. + // Reserve that row's pixel bytes, then count the complete strides available for the other rows. + // Division avoids multiplying width by height, which can overflow even long for 32-bit BMP dimensions. long rowBits = (long)this.infoHeader.Width * storedBitsPerPixel; long stride = (rowBits + 31) / 32 * 4; - long requiredLength = (stride * (this.infoHeader.Height - 1)) + ((rowBits + 7) / 8); + long finalRowBytes = (rowBits + 7) / 8; long remainingLength = stream.Length - stream.Position; - if (requiredLength > remainingLength) + if (remainingLength < finalRowBytes || this.infoHeader.Height - 1 > (remainingLength - finalRowBytes) / stride) { - BmpThrowHelper.ThrowInvalidImageContentException( - $"The bitmap declares {requiredLength} bytes of pixel data, but only {remainingLength} bytes remain in the stream."); + BmpThrowHelper.ThrowInvalidImageContentException("The bitmap does not contain enough pixel data for its declared dimensions."); } } diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs index 344ffa35dc..2c96f1c347 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -using System.Buffers.Binary; using Microsoft.DotNet.RemoteExecutor; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats.Bmp; @@ -699,87 +698,79 @@ public void BmpDecoder_ThrowsException_Issue3074() }); } + /// + /// Invalid RGB bit depths cannot define a pixel layout, even when image data errors are ignored. + /// + /// The stored bitmap with an unsupported RGB bit depth. [Theory] - [InlineData(0)] - [InlineData(3)] - [InlineData(7)] - [InlineData(12)] - [InlineData(33)] - public void BmpDecoder_InvalidUncompressedBitsPerPixel_ThrowsInvalidImageContentException(short bitsPerPixel) + [InlineData(InvalidRgbDepth0)] + [InlineData(InvalidRgbDepth3)] + [InlineData(InvalidRgbDepth7)] + [InlineData(InvalidRgbDepth12)] + [InlineData(InvalidRgbDepth33)] + public void BmpDecoder_InvalidUncompressedBitsPerPixel_ThrowsInvalidImageContentException(string path) { - byte[] data = CreateUncompressedBitmap(2, 2, bitsPerPixel, 8); + byte[] data = TestFile.Create(path).Bytes; - Assert.Throws(() => Image.Identify(data)); - Assert.Throws(() => + foreach (SegmentIntegrityHandling integrity in Enum.GetValues()) { - using Image image = Image.Load(data); - }); + DecoderOptions options = new() { SegmentIntegrityHandling = integrity }; + Assert.Throws(() => Image.Identify(options, data)); + Assert.Throws(() => + { + using Image image = Image.Load(options, data); + }); + } } + /// + /// Rejects dimensions that require more pixel data than the file contains before requesting pixel storage. + /// + /// The stored bitmap with incomplete RGB or bit-fields pixel data. [Theory] - [InlineData(4000, 4000)] - [InlineData(100000, 1)] - public void BmpDecoder_PixelDataSmallerThanDeclared_ThrowsBeforeAllocatingPixelBuffer(int width, int height) + [InlineData(TruncatedRgb24LargeImage)] + [InlineData(TruncatedRgb24WideRow)] + [InlineData(TruncatedBitFields16)] + [InlineData(TruncatedBitFields32)] + [InlineData(TruncatedAlphaBitFields32)] + [InlineData(TruncatedRgb32MaximumDimensions)] + public void BmpDecoder_PixelDataSmallerThanDeclared_ThrowsBeforeAllocatingPixelBuffer(string path) { - byte[] data = CreateUncompressedBitmap(width, height, 24, 72); - TestMemoryAllocator allocator = new(); - allocator.EnableNonThreadSafeLogging(); - Configuration configuration = Configuration.Default.Clone(); - configuration.MemoryAllocator = allocator; - DecoderOptions options = new() { Configuration = configuration }; + byte[] data = TestFile.Create(path).Bytes; - Assert.Throws(() => + foreach (SegmentIntegrityHandling integrity in Enum.GetValues()) { - using Image image = Image.Load(options, data); - }); - - // The rejection must happen before the Rgba32 pixel buffer for the declared dimensions is requested. - Assert.DoesNotContain(allocator.AllocationLog, request => request.LengthInBytes >= width * height * 4); - } - - [Fact] - public void BmpDecoder_MissingLastRowPadding_Decodes() - { - using Image expected = new(1, 2); - expected[0, 0] = new Rgb24(255, 0, 0); - expected[0, 1] = new Rgb24(0, 0, 255); - - using MemoryStream stream = new(); - expected.SaveAsBmp(stream, new BmpEncoder { BitsPerPixel = BmpBitsPerPixel.Bit24 }); - - // Each 24-bit row of one pixel holds three bytes of pixel data and one byte of padding. - // The pixel data is at the end of the file, so dropping the last byte removes the padding of the last row. - byte[] data = stream.ToArray()[..^1]; - - using Image actual = Image.Load(data); + // The allocator's group limit prevents a failed maximum-dimension regression from allocating that image. + TestMemoryAllocator allocator = new(); + allocator.EnableNonThreadSafeLogging(); + Configuration configuration = Configuration.Default.Clone(); + configuration.MemoryAllocator = allocator; + DecoderOptions options = new() { Configuration = configuration, SegmentIntegrityHandling = integrity }; + + InvalidImageContentException exception = Assert.Throws(() => + { + using Image image = Image.Load(options, data); + }); - Assert.Equal(expected[0, 0], actual[0, 0]); - Assert.Equal(expected[0, 1], actual[0, 1]); + // An allocation-limit exception is too late. No Rgba32 buffer, including a split buffer, may be requested. + Assert.Null(exception.InnerException); + Assert.DoesNotContain(allocator.AllocationLog, request => request.ElementType == typeof(Rgba32)); + } } /// - /// Creates a bitmap with a file header, a 40-byte BITMAPINFOHEADER without compression, and zeroed pixel data. + /// Accepts a missing padding byte after the final stored row in either row order. /// - /// The declared width. - /// The declared height. - /// The declared bits per pixel. - /// The number of pixel data bytes that follow the headers. - /// The encoded bitmap. - private static byte[] CreateUncompressedBitmap(int width, int height, short bitsPerPixel, int pixelDataLength) - { - const int pixelDataOffset = 54; - byte[] bmp = new byte[pixelDataOffset + pixelDataLength]; - Span span = bmp; - span[0] = (byte)'B'; - span[1] = (byte)'M'; - BinaryPrimitives.WriteInt32LittleEndian(span[2..], bmp.Length); - BinaryPrimitives.WriteInt32LittleEndian(span[10..], pixelDataOffset); - BinaryPrimitives.WriteInt32LittleEndian(span[14..], 40); - BinaryPrimitives.WriteInt32LittleEndian(span[18..], width); - BinaryPrimitives.WriteInt32LittleEndian(span[22..], height); - BinaryPrimitives.WriteInt16LittleEndian(span[26..], 1); - BinaryPrimitives.WriteInt16LittleEndian(span[28..], bitsPerPixel); - - return bmp; + /// The stored one-column bitmap with a red top pixel and a blue bottom pixel. + [Theory] + [InlineData(MissingFinalRowPadding)] + [InlineData(MissingFinalRowPaddingTopDown)] + public void BmpDecoder_MissingLastRowPadding_Decodes(string path) + { + using Image actual = Image.Load(TestFile.Create(path).Bytes); + + Assert.Equal(new Size(1, 2), actual.Size); + Assert.Equal(new Rgb24(255, 0, 0), actual[0, 0]); + Assert.Equal(new Rgb24(0, 0, 255), actual[0, 1]); } } diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 31dca8d5a6..49b52625c3 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -459,6 +459,19 @@ public static class Bmp // Note: The inverted images have been generated by altering the BitmapInfoHeader using a hex editor. // As such, the expected pixel output will be the reverse of the unaltered equivalent images. public const string Car = "Bmp/Car.bmp"; + public const string InvalidRgbDepth0 = "Bmp/headers/invalid-rgb-depth-0.bmp"; + public const string InvalidRgbDepth3 = "Bmp/headers/invalid-rgb-depth-3.bmp"; + public const string InvalidRgbDepth7 = "Bmp/headers/invalid-rgb-depth-7.bmp"; + public const string InvalidRgbDepth12 = "Bmp/headers/invalid-rgb-depth-12.bmp"; + public const string InvalidRgbDepth33 = "Bmp/headers/invalid-rgb-depth-33.bmp"; + public const string TruncatedRgb24LargeImage = "Bmp/headers/truncated-rgb24-4000x4000.bmp"; + public const string TruncatedRgb24WideRow = "Bmp/headers/truncated-rgb24-100000x1.bmp"; + public const string TruncatedBitFields16 = "Bmp/headers/truncated-bitfields16.bmp"; + public const string TruncatedBitFields32 = "Bmp/headers/truncated-bitfields32.bmp"; + public const string TruncatedAlphaBitFields32 = "Bmp/headers/truncated-alphabitfields32.bmp"; + public const string TruncatedRgb32MaximumDimensions = "Bmp/headers/truncated-rgb32-max-dimensions.bmp"; + public const string MissingFinalRowPadding = "Bmp/headers/missing-final-padding.bmp"; + public const string MissingFinalRowPaddingTopDown = "Bmp/headers/missing-final-padding-top-down.bmp"; public const string F = "Bmp/F.bmp"; public const string NegHeight = "Bmp/neg_height.bmp"; public const string CoreHeader = "Bmp/BitmapCoreHeaderQR.bmp"; diff --git a/tests/Images/Input/Bmp/headers/invalid-rgb-depth-0.bmp b/tests/Images/Input/Bmp/headers/invalid-rgb-depth-0.bmp new file mode 100644 index 0000000000..a748ec8821 --- /dev/null +++ b/tests/Images/Input/Bmp/headers/invalid-rgb-depth-0.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:23be9a3bc12c4818fc0e9aba881d00e4afed47f94e8f7419987dd197f417c05c +size 62 diff --git a/tests/Images/Input/Bmp/headers/invalid-rgb-depth-12.bmp b/tests/Images/Input/Bmp/headers/invalid-rgb-depth-12.bmp new file mode 100644 index 0000000000..ad7b6b9a32 --- /dev/null +++ b/tests/Images/Input/Bmp/headers/invalid-rgb-depth-12.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:70b9093ca2422a2509547cf158be6fdb425b729311e299a95d3ac3d1cd35ca2a +size 62 diff --git a/tests/Images/Input/Bmp/headers/invalid-rgb-depth-3.bmp b/tests/Images/Input/Bmp/headers/invalid-rgb-depth-3.bmp new file mode 100644 index 0000000000..48e01afd35 --- /dev/null +++ b/tests/Images/Input/Bmp/headers/invalid-rgb-depth-3.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:abe4d16944660433ee3c472711089b4091056bd206f446dd4a18eaf6aa278e9c +size 62 diff --git a/tests/Images/Input/Bmp/headers/invalid-rgb-depth-33.bmp b/tests/Images/Input/Bmp/headers/invalid-rgb-depth-33.bmp new file mode 100644 index 0000000000..b3c4b0c014 --- /dev/null +++ b/tests/Images/Input/Bmp/headers/invalid-rgb-depth-33.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b71c714a1808915b15ab8583fc464a1b41845629fc67fd54b24d20b1f3f04468 +size 62 diff --git a/tests/Images/Input/Bmp/headers/invalid-rgb-depth-7.bmp b/tests/Images/Input/Bmp/headers/invalid-rgb-depth-7.bmp new file mode 100644 index 0000000000..044382b047 --- /dev/null +++ b/tests/Images/Input/Bmp/headers/invalid-rgb-depth-7.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ac5e42f5c0feefc454446153bca6dfe9ba7cfdb579cf63865b7733997650598a +size 62 diff --git a/tests/Images/Input/Bmp/headers/missing-final-padding-top-down.bmp b/tests/Images/Input/Bmp/headers/missing-final-padding-top-down.bmp new file mode 100644 index 0000000000..1cf0309159 --- /dev/null +++ b/tests/Images/Input/Bmp/headers/missing-final-padding-top-down.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:edb0c2ce2ecee35d2e3f2dd03745183e9a5c609903b0516b9d096cd33719c0aa +size 61 diff --git a/tests/Images/Input/Bmp/headers/missing-final-padding.bmp b/tests/Images/Input/Bmp/headers/missing-final-padding.bmp new file mode 100644 index 0000000000..3de1ed3989 --- /dev/null +++ b/tests/Images/Input/Bmp/headers/missing-final-padding.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fb21ba3d4482e2d8d6b103c57ec57956df67e870a8a8b98bb6ae3687e3600a2a +size 61 diff --git a/tests/Images/Input/Bmp/headers/truncated-alphabitfields32.bmp b/tests/Images/Input/Bmp/headers/truncated-alphabitfields32.bmp new file mode 100644 index 0000000000..e0caf505db --- /dev/null +++ b/tests/Images/Input/Bmp/headers/truncated-alphabitfields32.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8332dd80fb79e689dc0c472e121f7ce117c0add354e8c61ee6c6b627d14a0476 +size 142 diff --git a/tests/Images/Input/Bmp/headers/truncated-bitfields16.bmp b/tests/Images/Input/Bmp/headers/truncated-bitfields16.bmp new file mode 100644 index 0000000000..76d8082241 --- /dev/null +++ b/tests/Images/Input/Bmp/headers/truncated-bitfields16.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:72190e5ea3331a466b9263bc404422500c8a52af33986e0f841fd61c447e1f3a +size 138 diff --git a/tests/Images/Input/Bmp/headers/truncated-bitfields32.bmp b/tests/Images/Input/Bmp/headers/truncated-bitfields32.bmp new file mode 100644 index 0000000000..a2b2d282f9 --- /dev/null +++ b/tests/Images/Input/Bmp/headers/truncated-bitfields32.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:568ea10e01df3087ec9cc5f7aa45a660bfa47dd13258ef3851d2a3303f07eb06 +size 138 diff --git a/tests/Images/Input/Bmp/headers/truncated-rgb24-100000x1.bmp b/tests/Images/Input/Bmp/headers/truncated-rgb24-100000x1.bmp new file mode 100644 index 0000000000..666e7d5e2f --- /dev/null +++ b/tests/Images/Input/Bmp/headers/truncated-rgb24-100000x1.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:173208862a7dcb0d1a8ac371792bf5ae58f50d8eb48c70c76cdeac8a5c32e3eb +size 126 diff --git a/tests/Images/Input/Bmp/headers/truncated-rgb24-4000x4000.bmp b/tests/Images/Input/Bmp/headers/truncated-rgb24-4000x4000.bmp new file mode 100644 index 0000000000..86304f25c2 --- /dev/null +++ b/tests/Images/Input/Bmp/headers/truncated-rgb24-4000x4000.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26d418b96e27e422fdeccc81a1c909f74a0b7e8ce09ab87bf4f957d460ba1371 +size 126 diff --git a/tests/Images/Input/Bmp/headers/truncated-rgb32-max-dimensions.bmp b/tests/Images/Input/Bmp/headers/truncated-rgb32-max-dimensions.bmp new file mode 100644 index 0000000000..6391e1d219 --- /dev/null +++ b/tests/Images/Input/Bmp/headers/truncated-rgb32-max-dimensions.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ff4d2387a8f9c30c77d61aaf988bc80c98956f89608d55afabbd99da7cd91143 +size 126