Skip to content

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

@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 during GIF parsing.

The application attempts to read 248,852 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__gif_load (via stbi__malloc) 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 derived from the GIF metadata. It attempts to copy 248,852 bytes from this 1-byte source buffer. This indicates that bimg does not validate if the buffer returned by stb_image (specifically for GIF files) actually contains the amount of data expected by the image dimensions before performing the memory copy.

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

==63587==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x502000000011 at pc 0x55f85c9ff34f bp 0x7ffc6942af10 sp 0x7ffc6942a6d0
READ of size 248852 at 0x502000000011 thread T0
    #0 0x55f85c9ff34e in __asan_memcpy (/src/bgfx/harness+0xe334e) (BuildId: a2ed5e3f73ed170e14adb779fac52e140093e79d)
    #1 0x55f85cc9d3f4 in bx::memCopy(void*, void const*, unsigned long) /src/bgfx/.build/projects/gmake-linux-clang/../../../../bx/src/bx.cpp:121:3
    #2 0x55f85cbeaa7f 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 0x55f85cab65cc 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 0x55f85cab1099 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 0x55f85ca454a5 in main /src/bgfx/harness.cpp:32:39
    #6 0x7f06c148d1c9 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #7 0x7f06c148d28a in __libc_start_main csu/../csu/libc-start.c:360:3
    #8 0x55f85c9617f4 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 0x55f85ca01623 in malloc (/src/bgfx/harness+0xe5623) (BuildId: a2ed5e3f73ed170e14adb779fac52e140093e79d)
    #1 0x55f85cb0e45c in lodepng_malloc(unsigned long) /src/bgfx/.build/projects/gmake-linux-clang/../../../../bimg/src/image_decode.cpp:43:9
    #2 0x55f85cb0e45c in stbi__malloc(unsigned long) /src/bgfx/.build/projects/gmake-linux-clang/../../../../bimg/3rdparty/stb/stb_image.h:986:12
    #3 0x55f85cb0e45c in stbi__gif_load_next(stbi__context*, stbi__gif*, int*, int, unsigned char*) /src/bgfx/.build/projects/gmake-linux-clang/../../../../bimg/3rdparty/stb/stb_image.h:6790:28
    #4 0x55f85cb0e45c in stbi__gif_load(stbi__context*, int*, int*, int*, int, stbi__result_info*) /src/bgfx/.build/projects/gmake-linux-clang/../../../../bimg/3rdparty/stb/stb_image.h:7052:8
    #5 0x55f85cb0e45c 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:1152:35
    #6 0x55f85caf5b94 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 fd fa fa fa fd 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
==63587==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