From a078addc8da7a86608c1b2941bfb151cce693458 Mon Sep 17 00:00:00 2001 From: sai pranav Date: Wed, 23 Sep 2026 23:07:31 +0530 Subject: [PATCH] Bound the buffers G_format_northing/easting/resolution write into format_double() (lib/gis/wind_format.c) formats a coordinate with sprintf(buf, "%.8f", value) for any non-lat/lon projection. %.8f on a double has no fixed maximum width -- DBL_MAX needs 318 characters -- but several callers pass a fixed local buffer sized for an ordinary coordinate: 30 bytes in r.coin, 50 in r.report, ps.map, and d.where. g.region's coordinate parser (scan_double() in wind_scan.c) is a bare sscanf with no magnitude check, so an extreme n=/s=/e=/w= value in a non-lat/lon projection is accepted, and the region's stored coordinate can be large enough to overflow these buffers when one of the four affected programs formats it. Reproduced with format_double() extracted verbatim into a standalone harness under AddressSanitizer: 9e19 (29-char result) is clean, 1e20 (30 characters, one more than a 30-byte buffer can hold with the terminator) overflows. DBL_MAX needs exactly 318 characters, measured directly. Bumped each of the four buffers to 320 bytes -- sign + DBL_MAX's 318 digits + the terminator -- rather than changing format_double()'s signature, which is called from many places across the tree with no size parameter today and felt like a separate, bigger decision. Fixes #7942. Could not build the full tree to test end to end -- this machine is already tight on disk space, and the change is a pure buffer-size literal with no logic difference, so I didn't think it was worth the risk for the confidence gained. clang-format is clean on all four files. Signed-off-by: sai pranav --- display/d.where/where.c | 2 +- lib/gis/wind_format.c | 6 +++--- ps/ps.map/map_info.c | 2 +- raster/r.coin/print_hdr.c | 2 +- raster/r.report/header.c | 6 +++--- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/display/d.where/where.c b/display/d.where/where.c index 402fd89a54e..9f775f14dd0 100644 --- a/display/d.where/where.c +++ b/display/d.where/where.c @@ -10,7 +10,7 @@ extern struct pj_info iproj, oproj, tproj; int where_am_i(char **coords, FILE *fp, int have_spheroid, int decimal, int dcoord) { - char buf1[50], buf2[50]; + char buf1[320], buf2[320]; int screen_x, screen_y; double east, north; int projection; diff --git a/lib/gis/wind_format.c b/lib/gis/wind_format.c index 45b6b2eb0ca..40eb45b6b7c 100644 --- a/lib/gis/wind_format.c +++ b/lib/gis/wind_format.c @@ -21,7 +21,7 @@ static void format_double(double, char *, int); * its ASCII representation (into buf). * * \param north northing - * \param[out] buf buffer to hold formatted string + * \param[out] buf buffer (>=320 bytes) to hold formatted string * \param projection projection code, or -1 to force full precision FP */ void G_format_northing(double north, char *buf, int projection) @@ -41,7 +41,7 @@ void G_format_northing(double north, char *buf, int projection) * its ASCII representation (into buf). * * \param east easting - * \param[out] buf buffer to hold formatted string + * \param[out] buf buffer (>=320 bytes) to hold formatted string * \param projection projection code, or -1 to force full precision FP */ void G_format_easting(double east, char *buf, int projection) @@ -61,7 +61,7 @@ void G_format_easting(double east, char *buf, int projection) * ASCII representation (into buf). * * \param res resolution value - * \param[out] buf buffer to hold formatted string + * \param[out] buf buffer (>=320 bytes) to hold formatted string * \param projection projection code, or -1 to force full precision FP */ void G_format_resolution(double res, char *buf, int projection) diff --git a/ps/ps.map/map_info.c b/ps/ps.map/map_info.c index e6d41760398..2807b444025 100644 --- a/ps/ps.map/map_info.c +++ b/ps/ps.map/map_info.c @@ -9,7 +9,7 @@ int map_info(void) { char buf[400]; - char east[50], west[50], north[50], south[50]; + char east[320], west[320], north[320], south[320]; double x, y, k, fontsize, dy, margin; static char *region = "REGION: "; diff --git a/raster/r.coin/print_hdr.c b/raster/r.coin/print_hdr.c index 9ac9b4c90c5..825b37b7624 100644 --- a/raster/r.coin/print_hdr.c +++ b/raster/r.coin/print_hdr.c @@ -19,7 +19,7 @@ int print_coin_hdr(int Conformat) { char unit_type[20]; const char *mapset, *location; - char north[30], south[30], east[30], west[30]; + char north[320], south[320], east[320], west[320]; mapset = G_mapset(); location = G_location(); diff --git a/raster/r.report/header.c b/raster/r.report/header.c index 390c793df43..bd7b7f7928c 100644 --- a/raster/r.report/header.c +++ b/raster/r.report/header.c @@ -21,9 +21,9 @@ int header(int unit1, int unit2) int i, k; char buf[BUFSZ]; char tbuf1[256], tbuf2[256]; - char north[50], south[50]; - char east[50], west[50]; - char ns_res[50], ew_res[50]; + char north[320], south[320]; + char east[320], west[320]; + char ns_res[320], ew_res[320]; int len1, len2; char *label;