Skip to content

Heap-buffer-overflow in ckd_free_3d triggered by ps_mllr_read error cleanup on malformed file #433

@hgarrereyn

Description

@hgarrereyn

Invoking ps_mllr_read on a malformed file can lead to a heap-buffer-overflow (read) during the error cleanup path.

Tested on f6e44c6e

See the provided testcase:

testcase.cpp

#include <cstdio>
extern "C" {
#include "/fuzz/install/include/pocketsphinx/mllr.h"
}
int main(){
  // Malformed data
  const unsigned char data[] = {
    49,32,51,32,48,46,50,53,55,57,48,55,51,53,52,54,55,54,53,50,54,50,53,55,32,49,48,209,48,32,49,48,46,48,32,48,46,50,57,121,121,121,0,16,121,121,121,102,121,121,121,32,9,32,48,46,55,52,51,52,50,51,54,53,53,56,49,57,50,49,51,49,48,51,32,9,32,48,46,56,49,51,53,55,52,50,48,51,57,48,48,49,57,57,56,50,52,32,9,32,207,46,49,49,55,49,52,48,56,52,50,48,46,48,10,49,48,48,46,48,16,48,32,49,48,48,48,46,48,114,101,118,155,155,155,155,155,155,155,155,49,53,48,57,101,43,48,48,32,45,0,0,0,127,48,57,45,49,48,48,46,48,32,49,48,48,46,48,32,45,48,46,48,32,45,36,101,43,48,48,32,45,49,46,48,32,69,46,57,54,54,52,56,52,48,57,52,52,54,56,54,53,54,50,52,49,32,45,50,10,54,46,48,50,52,52,56,46,48,9,51,56,50,101,45,48,55,32,57,46,48,50,155,155,155,155,155,155,155,155,155,155,155,155,155,155,49,53,48,57,101,43,48,48,32,45,0,0,0,127,48,57,45,49,48,48,46,48,32,49,48,48,46,48,32,45,48,46,48,32,45,48,48,61,61,61,61,61,61,46,48,32,49,48,48,48,46,48,32,45,49,0,0,0,0,0,0,0,45,49,0,0,0,0,0,0,0,4
  };
  const char* path = "/tmp/min_mllr_small.txt";
  FILE* f = fopen(path, "wb");
  fwrite(data, 1, sizeof(data), f);
  fclose(f);
  // Triggers heap-buffer-overflow in ckd_free_3d during ps_mllr_read() error cleanup
  ps_mllr_t* m = ps_mllr_read(path);
  (void)m;
  return 0;
}

crash report

{
  "Date": "2025-09-27T23:25:17.249530+00:00",
  "Uname": "Linux 4b69dd4f002d 5.15.0-140-generic #150-Ubuntu SMP Sat Apr 12 06:00:09 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux",
  "OS": "Ubuntu",
  "OSRelease": "22.04",
  "Architecture": "amd64",
  "ExecutablePath": "/tmp/tmppgchfaw1/reproducer",
  "ProcEnviron": [
    "LIBAFL_EDGES_MAP_SIZE=800000",
    "PWD=/fuzz/workspace",
    "CXX=gf_libafl_cxx",
    "GRAPHFUZZ_USE_ASAN=1",
    "HOME=/root",
    "ASAN_OPTIONS=hard_rss_limit_mb=1024:detect_leaks=0",
    "TERM=xterm-256color",
    "SHLVL=1",
    "LD_LIBRARY_PATH=/fuzz/install/lib",
    "PATH=/root/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
    "CC=gf_libafl_cc",
    "DEBIAN_FRONTEND=noninteractive",
    "OLDPWD=/fuzz/src",
    "_=/usr/local/bin/agfi"
  ],
  "ProcCmdline": "/tmp/tmppgchfaw1/reproducer",
  "Stdin": "",
  "ProcStatus": [],
  "ProcMaps": [],
  "ProcFiles": [],
  "NetworkConnections": [],
  "CrashSeverity": {
    "Type": "NOT_EXPLOITABLE",
    "ShortDescription": "heap-buffer-overflow(read)",
    "Description": "Heap buffer overflow",
    "Explanation": "The target reads data past the end, or before the beginning, of the intended heap buffer."
  },
  "Stacktrace": [
    "    #0 0x55555565e8c4 in ckd_free_3d /fuzz/src/src/util/ckd_alloc.c:303:18",
    "    #1 0x55555565c9e9 in ps_mllr_free /fuzz/src/src/ps_mllr.c:152:13",
    "    #2 0x55555565c4ec in ps_mllr_read /fuzz/src/src/ps_mllr.c:129:5",
    "    #3 0x55555565b54e in main /tmp/tmppgchfaw1/reproducer.cpp:15:18",
    "    #4 0x7ffff7a6dd8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16",
    "    #5 0x7ffff7a6de3f in __libc_start_main csu/../csu/libc-start.c:392:3",
    "    #6 0x5555555802f4 in _start (/tmp/tmppgchfaw1/reproducer+0x2c2f4) (BuildId: 2d6febf4e02f25ac6994b79e9523702f9711bba0)"
  ],
  "Registers": {},
  "Disassembly": [],
  "Package": "",
  "PackageVersion": "",
  "PackageArchitecture": "",
  "PackageDescription": "",
  "AsanReport": [
    "==156==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x502000000070 at pc 0x55555565e8c5 bp 0x7fffffffe8c0 sp 0x7fffffffe8b8",
    "READ of size 8 at 0x502000000070 thread T0",
    "    #0 0x55555565e8c4 in ckd_free_3d /fuzz/src/src/util/ckd_alloc.c:303:18",
    "    #1 0x55555565c9e9 in ps_mllr_free /fuzz/src/src/ps_mllr.c:152:13",
    "    #2 0x55555565c4ec in ps_mllr_read /fuzz/src/src/ps_mllr.c:129:5",
    "    #3 0x55555565b54e in main /tmp/tmppgchfaw1/reproducer.cpp:15:18",
    "    #4 0x7ffff7a6dd8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16",
    "    #5 0x7ffff7a6de3f in __libc_start_main csu/../csu/libc-start.c:392:3",
    "    #6 0x5555555802f4 in _start (/tmp/tmppgchfaw1/reproducer+0x2c2f4) (BuildId: 2d6febf4e02f25ac6994b79e9523702f9711bba0)",
    "",
    "0x502000000071 is located 0 bytes after 1-byte region [0x502000000070,0x502000000071)",
    "allocated by thread T0 here:",
    "    #0 0x55555561c69e in malloc (/tmp/tmppgchfaw1/reproducer+0xc869e) (BuildId: 2d6febf4e02f25ac6994b79e9523702f9711bba0)",
    "    #1 0x55555565e20d in __ckd_malloc__ /fuzz/src/src/util/ckd_alloc.c:178:16",
    "    #2 0x55555565e20d in __ckd_calloc_3d__ /fuzz/src/src/util/ckd_alloc.c:279:19",
    "",
    "SUMMARY: AddressSanitizer: heap-buffer-overflow /fuzz/src/src/util/ckd_alloc.c:303:18 in ckd_free_3d",
    "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 00 04 fa fa 01 fa fa fa 00 fa fa fa[01]fa",
    "  0x502000000080: fa fa 01 fa fa fa 00 fa fa fa 01 fa fa fa 00 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",
    "==156==ABORTING"
  ],
  "MsanReport": [],
  "UbsanReport": [],
  "LuaReport": [],
  "PythonReport": [],
  "GoReport": [],
  "JavaReport": [],
  "RustReport": [],
  "JsReport": [],
  "CSharpReport": [],
  "CrashLine": "/fuzz/src/src/util/ckd_alloc.c:303:18",
  "Source": [
    "    299    {",
    "    300        void ***ptr = (void ***)inptr;",
    "    301    ",
    "    302        if (ptr && ptr[0])",
    "--->303            ckd_free(ptr[0][0]);",
    "    304        if (ptr)",
    "    305            ckd_free(ptr[0]);",
    "    306        ckd_free(ptr);",
    "    307    }",
    "    308    "
  ]
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions