Skip to content

Out-of-bounds read in GDfieldinfo via size_t underflow in DimList paren-stripping memmove #14379

@biniamf

Description

@biniamf

What is the bug?

A similar bug as #14378 but in a different file/path.

Root cause (GDapi.c):

  statmeta = EHgetmetavalue(metaptrs, "DimList", utlstr);
  if (statmeta == 0)
  {
      memmove(utlstr, utlstr + 1, strlen(utlstr) - 2);  // <- SIZE_MAX-1
      utlstr[strlen(utlstr) - 2] = 0;                   // <- same underflow
      ...

The code assumes DimList is always parenthesized: ("dim1","dim2").
It strips the leading "(" and trailing ")" via memmove with length
strlen()-2. If DimList is empty or single-char, strlen()-2 wraps to
SIZE_MAX due to unsigned arithmetic (size_t).

utlstr is a 512-byte heap buffer (calloc'd at line 1694). The memmove
reads SIZE_MAX-1 bytes starting at utlstr+1, far beyond the allocation.

Steps to reproduce the issue

PoC

The vulnerability is reachable from gdalmdiminfo via a crafted HDF-EOS grid file: poc_gdfinfo_dimlist_oob-read.he4.

ASAN_OPTIONS=detect_leaks=0 ./gdalmdiminfo poc_gdfinfo_dimlist_oob-read.he4

ASan output:

==58568==ERROR: AddressSanitizer: unknown-crash on address 0xf54909de5801
at pc 0xf7f9130752dc bp 0xffffda2e4290 sp 0xffffda2e4280
READ of size 18446744073709551614 at 0xf54909de5801 thread T0
    #0 0xf7f9130752d8 in memmove /usr/include/aarch64-linux-gnu/bits/string_fortified.h:36
    #1 0xf7f9130752d8 in GDfieldinfo /home/roo/Desktop/gdal/gdal/frmts/hdf4/hdf-eos/GDapi.c:1756
    #2 0xf7f9130f03f8 in HDF4EOSGridSubGroup::OpenMDArray(...) const /home/roo/Desktop/gdal/gdal/frmts/hdf4/hdf4multidim.cpp:2140
    #3 0xf7f914154cc0 in DumpArrays /home/roo/Desktop/gdal/gdal/apps/gdalmdiminfo_lib.cpp:1062
    #4 0xf7f914154cc0 in DumpGroup /home/roo/Desktop/gdal/gdal/apps/gdalmdiminfo_lib.cpp:1151
    #5 0xf7f9141537d4 in DumpGroup /home/roo/Desktop/gdal/gdal/apps/gdalmdiminfo_lib.cpp:1175
    #6 0xf7f9141537d4 in DumpGroup /home/roo/Desktop/gdal/gdal/apps/gdalmdiminfo_lib.cpp:1175
    #7 0xf7f9141537d4 in DumpGroup /home/roo/Desktop/gdal/gdal/apps/gdalmdiminfo_lib.cpp:1175
    #8 0xf7f914156cac in GDALMultiDimInfo /home/roo/Desktop/gdal/gdal/apps/gdalmdiminfo_lib.cpp:1360
    #9 in main /home/roo/Desktop/gdal/gdal/apps/gdalmdiminfo_bin.cpp:83

0xf54909de5801 is located 1 bytes inside of 512-byte region [0xf54909de5800,0xf54909de5a00)
allocated by thread T0 here:
    #0 in calloc
    #1 0xf7f913073e94 in GDfieldinfo /home/roo/Desktop/gdal/gdal/frmts/hdf4/hdf-eos/GDapi.c:1694

SUMMARY: AddressSanitizer: unknown-crash in memmove GDfieldinfo GDapi.c:1756

Impact:

  • Immediate: SIGSEGV leading to DoS

Versions and provenance

  • Version: GDAL 3.13.0dev-4c681ad376
  • Commit: 4c681ad

Additional context

Suggested fix (GDapi.c):

Validate string length before paren stripping:

  // before
  statmeta = EHgetmetavalue(metaptrs, "DimList", utlstr);
  if (statmeta == 0)
  {
      memmove(utlstr, utlstr + 1, strlen(utlstr) - 2);
      utlstr[strlen(utlstr) - 2] = 0;
      ...
  // after
  statmeta = EHgetmetavalue(metaptrs, "DimList", utlstr);
  if (statmeta == 0)
  {
      size_t len = strlen(utlstr);
      if (len >= 2)
      {
          memmove(utlstr, utlstr + 1, len - 2);
          utlstr[len - 2] = '\0';
      }
      else
      {
          utlstr[0] = '\0';
      }
      ...
  ```

Metadata

Metadata

Assignees

No one assigned

    Labels

    not for AI loversSee https://gdal.org/en/stable/community/ai_tool_policy.html

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions