Skip to content

Commit e114f00

Browse files
Merge branch 'release/3.1.x' into af/backport-3075-to-3.1
2 parents d3b1cb2 + 152fa9e commit e114f00

3 files changed

Lines changed: 51 additions & 9 deletions

File tree

.github/workflows/build-and-test.yml

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
sdk-preview: true
2626
runtime: -x64
2727
codecov: false
28-
- os: macos-13 # macos-latest runs on arm64 runners where libgdiplus is unavailable
28+
- os: macos-26-intel
2929
framework: net7.0
3030
sdk: 7.0.x
3131
sdk-preview: true
@@ -48,7 +48,7 @@ jobs:
4848
sdk: 6.0.x
4949
runtime: -x64
5050
codecov: false
51-
- os: macos-13 # macos-latest runs on arm64 runners where libgdiplus is unavailable
51+
- os: macos-26-intel
5252
framework: net6.0
5353
sdk: 6.0.x
5454
runtime: -x64
@@ -69,8 +69,20 @@ jobs:
6969
- name: Install libgdi+, which is required for tests running on ubuntu
7070
if: ${{ contains(matrix.options.os, 'ubuntu') }}
7171
run: |
72-
sudo apt-get update
73-
sudo apt-get -y install libgdiplus libgif-dev libglib2.0-dev libcairo2-dev libtiff-dev libexif-dev
72+
sudo apt-get update
73+
sudo apt-get -y install libgdiplus libgif-dev libglib2.0-dev libcairo2-dev libtiff-dev libexif-dev
74+
75+
- name: Install libgdi+, which is required for tests running on macos
76+
if: ${{ contains(matrix.options.os, 'macos-26') }}
77+
run: |
78+
brew update
79+
brew install mono-libgdiplus
80+
# Create symlinks to make libgdiplus discoverable
81+
sudo mkdir -p /usr/local/lib
82+
sudo ln -sf $(brew --prefix)/lib/libgdiplus.dylib /usr/local/lib/libgdiplus.dylib
83+
# Verify installation
84+
ls -la $(brew --prefix)/lib/libgdiplus* || echo "libgdiplus not found in brew prefix"
85+
ls -la /usr/local/lib/libgdiplus* || echo "libgdiplus not found in /usr/local/lib"
7486
7587
- name: Git Config
7688
shell: bash

src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,10 @@ protected override Image<TPixel> Decode<TPixel>(BufferedReadStream stream, Cance
126126
switch (this.infoHeader.Compression)
127127
{
128128
case BmpCompression.RGB:
129-
if (this.infoHeader.BitsPerPixel == 32)
129+
130+
ushort bitsPerPixel = this.infoHeader.BitsPerPixel;
131+
132+
if (bitsPerPixel == 32)
130133
{
131134
if (this.bmpMetadata.InfoHeaderType == BmpInfoHeaderType.WinVersion3)
132135
{
@@ -137,26 +140,30 @@ protected override Image<TPixel> Decode<TPixel>(BufferedReadStream stream, Cance
137140
this.ReadRgb32Fast(stream, pixels, this.infoHeader.Width, this.infoHeader.Height, inverted);
138141
}
139142
}
140-
else if (this.infoHeader.BitsPerPixel == 24)
143+
else if (bitsPerPixel == 24)
141144
{
142145
this.ReadRgb24(stream, pixels, this.infoHeader.Width, this.infoHeader.Height, inverted);
143146
}
144-
else if (this.infoHeader.BitsPerPixel == 16)
147+
else if (bitsPerPixel == 16)
145148
{
146149
this.ReadRgb16(stream, pixels, this.infoHeader.Width, this.infoHeader.Height, inverted);
147150
}
148-
else if (this.infoHeader.BitsPerPixel <= 8)
151+
else if (bitsPerPixel is > 0 and <= 8)
149152
{
150153
this.ReadRgbPalette(
151154
stream,
152155
pixels,
153156
palette,
154157
this.infoHeader.Width,
155158
this.infoHeader.Height,
156-
this.infoHeader.BitsPerPixel,
159+
bitsPerPixel,
157160
bytesPerColorMapEntry,
158161
inverted);
159162
}
163+
else
164+
{
165+
BmpThrowHelper.ThrowInvalidImageContentException($"Invalid bits per pixel: {bitsPerPixel}");
166+
}
160167

161168
break;
162169

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,4 +598,27 @@ public void BmpDecoder_ThrowsException_Issue3074()
598598
using Image<Rgba32> image = Image.Load<Rgba32>(stream);
599599
});
600600
}
601+
602+
[Fact]
603+
public void BmpDecoder_ThrowsException_Issue3067()
604+
{
605+
// Construct minimal BMP with bitsPerPixel = 0
606+
byte[] bmp = new byte[54];
607+
bmp[0] = (byte)'B';
608+
bmp[1] = (byte)'M';
609+
BitConverter.GetBytes(54).CopyTo(bmp, 2);
610+
BitConverter.GetBytes(54).CopyTo(bmp, 10);
611+
BitConverter.GetBytes(40).CopyTo(bmp, 14);
612+
BitConverter.GetBytes(1).CopyTo(bmp, 18);
613+
BitConverter.GetBytes(1).CopyTo(bmp, 22);
614+
BitConverter.GetBytes((short)1).CopyTo(bmp, 26);
615+
BitConverter.GetBytes((short)0).CopyTo(bmp, 28); // bitsPerPixel = 0
616+
617+
using MemoryStream stream = new(bmp);
618+
619+
InvalidImageContentException ex = Assert.Throws<InvalidImageContentException>(() =>
620+
{
621+
using Image image = BmpDecoder.Instance.Decode(DecoderOptions.Default, stream);
622+
});
623+
}
601624
}

0 commit comments

Comments
 (0)