Browse Source

Fix #3067

pull/3069/head
James Jackson-South 2 months ago
parent
commit
34e7f9700d
  1. 19
      src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
  2. 23
      tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs

19
src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs

@ -130,6 +130,13 @@ internal sealed class BmpDecoderCore : ImageDecoderCore
Image<TPixel>? image = null;
try
{
ushort bitsPerPixel = this.infoHeader.BitsPerPixel;
if (bitsPerPixel is not (1 or 2 or 4 or 8 or 16 or 24 or 32))
{
BmpThrowHelper.ThrowInvalidImageContentException($"Invalid bits per pixel: {bitsPerPixel}");
}
int bytesPerColorMapEntry = this.ReadImageHeaders(stream, out bool inverted, out byte[] palette);
image = new Image<TPixel>(this.configuration, this.infoHeader.Width, this.infoHeader.Height, this.metadata);
@ -138,23 +145,23 @@ internal sealed class BmpDecoderCore : ImageDecoderCore
switch (this.infoHeader.Compression)
{
case BmpCompression.RGB when this.infoHeader.BitsPerPixel is 32 && this.bmpMetadata.InfoHeaderType is BmpInfoHeaderType.WinVersion3:
case BmpCompression.RGB when bitsPerPixel is 32 && this.bmpMetadata.InfoHeaderType is BmpInfoHeaderType.WinVersion3:
this.ReadRgb32Slow(stream, pixels, this.infoHeader.Width, this.infoHeader.Height, inverted);
break;
case BmpCompression.RGB when this.infoHeader.BitsPerPixel is 32:
case BmpCompression.RGB when bitsPerPixel is 32:
this.ReadRgb32Fast(stream, pixels, this.infoHeader.Width, this.infoHeader.Height, inverted);
break;
case BmpCompression.RGB when this.infoHeader.BitsPerPixel is 24:
case BmpCompression.RGB when bitsPerPixel is 24:
this.ReadRgb24(stream, pixels, this.infoHeader.Width, this.infoHeader.Height, inverted);
break;
case BmpCompression.RGB when this.infoHeader.BitsPerPixel is 16:
case BmpCompression.RGB when bitsPerPixel is 16:
this.ReadRgb16(stream, pixels, this.infoHeader.Width, this.infoHeader.Height, inverted);
break;
case BmpCompression.RGB when this.infoHeader.BitsPerPixel is <= 8 && this.processedAlphaMask:
case BmpCompression.RGB when bitsPerPixel is <= 8 && this.processedAlphaMask:
this.ReadRgbPaletteWithAlphaMask(
stream,
pixels,
@ -166,7 +173,7 @@ internal sealed class BmpDecoderCore : ImageDecoderCore
inverted);
break;
case BmpCompression.RGB when this.infoHeader.BitsPerPixel is <= 8:
case BmpCompression.RGB when bitsPerPixel is <= 8:
this.ReadRgbPalette(
stream,
pixels,

23
tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs

@ -571,4 +571,27 @@ public class BmpDecoderTests
});
Assert.IsType<InvalidMemoryOperationException>(ex.InnerException);
}
[Fact]
public void BmpDecoder_ThrowsException_Issue3067()
{
// Construct minimal BMP with bitsPerPixel = 0
byte[] bmp = new byte[54];
bmp[0] = (byte)'B';
bmp[1] = (byte)'M';
BitConverter.GetBytes(54).CopyTo(bmp, 2);
BitConverter.GetBytes(54).CopyTo(bmp, 10);
BitConverter.GetBytes(40).CopyTo(bmp, 14);
BitConverter.GetBytes(1).CopyTo(bmp, 18);
BitConverter.GetBytes(1).CopyTo(bmp, 22);
BitConverter.GetBytes((short)1).CopyTo(bmp, 26);
BitConverter.GetBytes((short)0).CopyTo(bmp, 28); // bitsPerPixel = 0
using MemoryStream stream = new(bmp);
InvalidImageContentException ex = Assert.Throws<InvalidImageContentException>(() =>
{
using Image image = BmpDecoder.Instance.Decode(DecoderOptions.Default, stream);
});
}
}

Loading…
Cancel
Save