Skip to content

Commit 34e7f97

Browse files
Fix #3067
1 parent fea3df9 commit 34e7f97

2 files changed

Lines changed: 36 additions & 6 deletions

File tree

src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,13 @@ protected override Image<TPixel> Decode<TPixel>(BufferedReadStream stream, Cance
130130
Image<TPixel>? image = null;
131131
try
132132
{
133+
ushort bitsPerPixel = this.infoHeader.BitsPerPixel;
134+
135+
if (bitsPerPixel is not (1 or 2 or 4 or 8 or 16 or 24 or 32))
136+
{
137+
BmpThrowHelper.ThrowInvalidImageContentException($"Invalid bits per pixel: {bitsPerPixel}");
138+
}
139+
133140
int bytesPerColorMapEntry = this.ReadImageHeaders(stream, out bool inverted, out byte[] palette);
134141

135142
image = new Image<TPixel>(this.configuration, this.infoHeader.Width, this.infoHeader.Height, this.metadata);
@@ -138,23 +145,23 @@ protected override Image<TPixel> Decode<TPixel>(BufferedReadStream stream, Cance
138145

139146
switch (this.infoHeader.Compression)
140147
{
141-
case BmpCompression.RGB when this.infoHeader.BitsPerPixel is 32 && this.bmpMetadata.InfoHeaderType is BmpInfoHeaderType.WinVersion3:
148+
case BmpCompression.RGB when bitsPerPixel is 32 && this.bmpMetadata.InfoHeaderType is BmpInfoHeaderType.WinVersion3:
142149
this.ReadRgb32Slow(stream, pixels, this.infoHeader.Width, this.infoHeader.Height, inverted);
143150

144151
break;
145-
case BmpCompression.RGB when this.infoHeader.BitsPerPixel is 32:
152+
case BmpCompression.RGB when bitsPerPixel is 32:
146153
this.ReadRgb32Fast(stream, pixels, this.infoHeader.Width, this.infoHeader.Height, inverted);
147154

148155
break;
149-
case BmpCompression.RGB when this.infoHeader.BitsPerPixel is 24:
156+
case BmpCompression.RGB when bitsPerPixel is 24:
150157
this.ReadRgb24(stream, pixels, this.infoHeader.Width, this.infoHeader.Height, inverted);
151158

152159
break;
153-
case BmpCompression.RGB when this.infoHeader.BitsPerPixel is 16:
160+
case BmpCompression.RGB when bitsPerPixel is 16:
154161
this.ReadRgb16(stream, pixels, this.infoHeader.Width, this.infoHeader.Height, inverted);
155162

156163
break;
157-
case BmpCompression.RGB when this.infoHeader.BitsPerPixel is <= 8 && this.processedAlphaMask:
164+
case BmpCompression.RGB when bitsPerPixel is <= 8 && this.processedAlphaMask:
158165
this.ReadRgbPaletteWithAlphaMask(
159166
stream,
160167
pixels,
@@ -166,7 +173,7 @@ protected override Image<TPixel> Decode<TPixel>(BufferedReadStream stream, Cance
166173
inverted);
167174

168175
break;
169-
case BmpCompression.RGB when this.infoHeader.BitsPerPixel is <= 8:
176+
case BmpCompression.RGB when bitsPerPixel is <= 8:
170177
this.ReadRgbPalette(
171178
stream,
172179
pixels,

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,4 +571,27 @@ public void BmpDecoder_ThrowsException_Issue2696<TPixel>(TestImageProvider<TPixe
571571
});
572572
Assert.IsType<InvalidMemoryOperationException>(ex.InnerException);
573573
}
574+
575+
[Fact]
576+
public void BmpDecoder_ThrowsException_Issue3067()
577+
{
578+
// Construct minimal BMP with bitsPerPixel = 0
579+
byte[] bmp = new byte[54];
580+
bmp[0] = (byte)'B';
581+
bmp[1] = (byte)'M';
582+
BitConverter.GetBytes(54).CopyTo(bmp, 2);
583+
BitConverter.GetBytes(54).CopyTo(bmp, 10);
584+
BitConverter.GetBytes(40).CopyTo(bmp, 14);
585+
BitConverter.GetBytes(1).CopyTo(bmp, 18);
586+
BitConverter.GetBytes(1).CopyTo(bmp, 22);
587+
BitConverter.GetBytes((short)1).CopyTo(bmp, 26);
588+
BitConverter.GetBytes((short)0).CopyTo(bmp, 28); // bitsPerPixel = 0
589+
590+
using MemoryStream stream = new(bmp);
591+
592+
InvalidImageContentException ex = Assert.Throws<InvalidImageContentException>(() =>
593+
{
594+
using Image image = BmpDecoder.Instance.Decode(DecoderOptions.Default, stream);
595+
});
596+
}
574597
}

0 commit comments

Comments
 (0)