Skip to content

lib/raster3d: fix int overflow in Rast3d_copy_values byte offset - #7970

Merged
nilason merged 1 commit into
OSGeo:mainfrom
YannChemin:patch-7
Sep 29, 2026
Merged

nilason merged 1 commit into
OSGeo:mainfrom
YannChemin:patch-7

Conversation

@YannChemin

Copy link
Copy Markdown
Contributor

… offset.

eltLength, offsSrc and offsDst are all int, so the byte offset is multiplied in 32-bit arithmetic. G_incr_void_ptr() (lib/gis/alloc.c:182) already takes a size_t, but the product has overflowed before it gets there. In our crash, the element offset was 681 M, which fits in an int. Multiplied by 4 bytes for FCELL it becomes 2.7 G, which overflows, goes negative, and memcpy writes before the buffer.

The minimal fix: widen the multiplication to size_t:

67 src = G_incr_void_ptr(src, (size_t)eltLength * offsSrc);
68 dst = G_incr_void_ptr(dst, (size_t)eltLength * offsDst);

That fixes our case: blocks of up to 2³¹ − 1 cells, which is 8 GiB of FCELL. Line 70 already casts the memcpy length the same way ((size_t)nElts * eltLength), so the fix makes lines 67–68 consistent with the line just below them. A complete fix for blocks over 2³¹ cells would also need two more changes. Both alter the public API, so they suit a separate PR:

  • lib/raster3d/getblock.c:66–67 computes the destination offset (z + dz) * nx * ny + (y + dy) * nx + (x + dx) in int.
  • Rast3d_copy_values() takes its offsets as int (the prototype is at include/grass/defs/raster3d.h:173). Both would have to become size_t.

… offset.

eltLength, offsSrc and offsDst are all int, so the byte offset is multiplied in 32-bit arithmetic. G_incr_void_ptr() (lib/gis/alloc.c:182) already takes a size_t, but the product has overflowed before it gets there. In our crash, the element offset was 681 M, which fits in an int. Multiplied by 4 bytes for FCELL it becomes 2.7 G, which overflows, goes negative, and memcpy writes before the buffer.

The minimal fix: widen the multiplication to size_t:

67    src = G_incr_void_ptr(src, (size_t)eltLength * offsSrc);
68    dst = G_incr_void_ptr(dst, (size_t)eltLength * offsDst);

That fixes our case: blocks of up to 2³¹ − 1 cells, which is 8 GiB of FCELL. Line 70 already casts the memcpy length the same way ((size_t)nElts * eltLength), so the fix makes lines 67–68 consistent with the line just below them.
A complete fix for blocks over 2³¹ cells would also need two more changes. Both alter the public API, so they suit a separate PR:
- lib/raster3d/getblock.c:66–67 computes the destination offset (z + dz) * nx * ny + (y + dy) * nx + (x + dx) in int.
- Rast3d_copy_values() takes its offsets as int (the prototype is at include/grass/defs/raster3d.h:173). Both would have to become size_t.
@github-actions github-actions Bot added C Related code is in C libraries raster3d labels Sep 29, 2026
@nilason nilason changed the title Update misc.c : raster3d: fix int overflow in Rast3d_copy_values byte… lib/raster3d: fix int overflow in Rast3d_copy_values byte offset Sep 29, 2026
@nilason
nilason merged commit 4047b0f into OSGeo:main Sep 29, 2026
26 of 27 checks passed
@github-actions github-actions Bot added this to the 8.6.0 milestone Sep 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C Related code is in C libraries raster3d

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants