From 75b10ece39c6cb8352fa89c4d55ea7a2427b3186 Mon Sep 17 00:00:00 2001 From: Yann Chemin Date: Tue, 29 Sep 2026 05:05:18 +0200 Subject: [PATCH] Update misc.c : raster3d: fix int overflow in Rast3d_copy_values byte offset. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- lib/raster3d/misc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/raster3d/misc.c b/lib/raster3d/misc.c index de69881c9bc..13dd6768481 100644 --- a/lib/raster3d/misc.c +++ b/lib/raster3d/misc.c @@ -64,8 +64,8 @@ void Rast3d_copy_values(const void *src, int offsSrc, int typeSrc, void *dst, eltLength = Rast3d_length(typeSrc); - src = G_incr_void_ptr(src, eltLength * offsSrc); - dst = G_incr_void_ptr(dst, eltLength * offsDst); + src = G_incr_void_ptr(src, (size_t)eltLength * offsSrc); + dst = G_incr_void_ptr(dst, (size_t)eltLength * offsDst); memcpy(dst, src, (size_t)nElts * eltLength); }