Skip to content

[bimg] Heap-buffer-overflow (READ) in bimg::imageAlloc parsing malformed BMP #3532

@oneafter

Description

@oneafter

Description

We discovered a Heap Buffer Overflow (Read) vulnerability in bimg. The crash occurs in bimg::imageAlloc when bx::memCopy attempts to read data from a buffer returned by stb_image.

The application attempts to read 195,843 bytes from a buffer that is only 1 byte in size, leading to a massive out-of-bounds read and immediate crash.

Environment

  • OS: Linux x86_64
  • Complier: Clang
  • Build Configuration: Release mode with ASan enabled.

Vulnerability Details

  • Target: bimg (used by bgfx)
  • Vulnerability Type: Heap-buffer-overflow (READ)
  • Function: bimg::imageAlloc -> bx::memCopy
  • Location: bimg/src/image.cpp:3338
  • Root Cause Analysis: The ASAN report shows the source buffer was allocated in stbi__bmp_load (via stbi__malloc_mad3) with a size of only 1 byte. However, the bimg::imageAlloc function calculates the size of the image data to copy based on the image dimensions/format derived from the parsing step. It attempts to copy 195843 bytes from this 1-byte source buffer. This suggests a discrepancy between the buffer size actually decoded/allocated by stb_image (likely due to a malformed BMP header or RLE compression edge case) and the expected size calculated by bimg logic. bimg fails to verify if the source pointer contains enough data before copying.

Reproduce

  1. Build bgfx with Release optimization and ASAN enabled.
  2. Compile the bgfx harness with AddressSanitizer enabled (-fsanitize=address -g)
  3. Run with the crashing file repro:
./harness < repro

ASAN report

==63478==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x502000000011 at pc 0x55bbd116d34f bp 0x7fff76995830 sp 0x7fff76994ff0
READ of size 195843 at 0x502000000011 thread T0
    #0 0x55bbd116d34e in __asan_memcpy (/src/bgfx/harness+0xe334e) (BuildId: a2ed5e3f73ed170e14adb779fac52e140093e79d)
    #1 0x55bbd140b3f4 in bx::memCopy(void*, void const*, unsigned long) /src/bgfx/.build/projects/gmake-linux-clang/../../../../bx/src/bx.cpp:121:3
    #2 0x55bbd1358a7f in bimg::imageAlloc(bx::AllocatorI*, bimg::TextureFormat::Enum, unsigned short, unsigned short, unsigned short, unsigned short, bool, bool, void const*) /src/bgfx/.build/projects/gmake-linux-clang/../../../../bimg/src/image.cpp:3338:4
    #3 0x55bbd12245cc in bimg::imageParseStbImage(bx::AllocatorI*, void const*, unsigned int, bx::Error*) /src/bgfx/.build/projects/gmake-linux-clang/../../../../bimg/src/image_decode.cpp:688:28
    #4 0x55bbd121f099 in bimg::imageParse(bx::AllocatorI*, void const*, unsigned int, bimg::TextureFormat::Enum, bx::Error*) /src/bgfx/.build/projects/gmake-linux-clang/../../../../bimg/src/image_decode.cpp:901:27
    #5 0x55bbd11b34a5 in main /src/bgfx/harness.cpp:32:39
    #6 0x7f31068501c9 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #7 0x7f310685028a in __libc_start_main csu/../csu/libc-start.c:360:3
    #8 0x55bbd10cf7f4 in _start (/src/bgfx/harness+0x457f4) (BuildId: a2ed5e3f73ed170e14adb779fac52e140093e79d)

0x502000000011 is located 0 bytes after 1-byte region [0x502000000010,0x502000000011)
allocated by thread T0 here:
    #0 0x55bbd116f623 in malloc (/src/bgfx/harness+0xe5623) (BuildId: a2ed5e3f73ed170e14adb779fac52e140093e79d)
    #1 0x55bbd1275613 in lodepng_malloc(unsigned long) /src/bgfx/.build/projects/gmake-linux-clang/../../../../bimg/src/image_decode.cpp:43:9
    #2 0x55bbd1275613 in stbi__malloc(unsigned long) /src/bgfx/.build/projects/gmake-linux-clang/../../../../bimg/3rdparty/stb/stb_image.h:986:12
    #3 0x55bbd1275613 in stbi__malloc_mad3(int, int, int, int) /src/bgfx/.build/projects/gmake-linux-clang/../../../../bimg/3rdparty/stb/stb_image.h:1057:11
    #4 0x55bbd1275613 in stbi__bmp_load(stbi__context*, int*, int*, int*, int, stbi__result_info*) /src/bgfx/.build/projects/gmake-linux-clang/../../../../bimg/3rdparty/stb/stb_image.h:5594:22
    #5 0x55bbd1275613 in stbi__load_main(stbi__context*, int*, int*, int*, int, stbi__result_info*, int) /src/bgfx/.build/projects/gmake-linux-clang/../../../../bimg/3rdparty/stb/stb_image.h:1149:35
    #6 0x55bbd1263b94 in stbi__load_and_postprocess_8bit(stbi__context*, int*, int*, int*, int) /src/bgfx/.build/projects/gmake-linux-clang/../../../../bimg/3rdparty/stb/stb_image.h:1262:19

SUMMARY: AddressSanitizer: heap-buffer-overflow (/src/bgfx/harness+0xe334e) (BuildId: a2ed5e3f73ed170e14adb779fac52e140093e79d) in __asan_memcpy
Shadow bytes around the buggy address:
  0x501ffffffd80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x501ffffffe00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x501ffffffe80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x501fffffff00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x501fffffff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x502000000000: fa fa[01]fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x502000000080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x502000000100: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x502000000180: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x502000000200: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x502000000280: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==63478==ABORTING

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions