From 57095f24ce4c3335cb6e8be09477dad6bab17c0d Mon Sep 17 00:00:00 2001 From: sai pranav Date: Thu, 1 Oct 2026 08:29:02 +0530 Subject: [PATCH] Bound the buffers G_get_datumparams_from_projinfo writes into G_get_datumparams_from_projinfo() wrote the datum, datumparams, nadgrids, and towgs84/dx/dy/dz values straight from a PROJ_INFO-format Key_Value set into caller-supplied buffers with plain sprintf, and the function signature had no size parameter at all, so it had no way to bound the write regardless of how big the caller's buffer was. general/g.setproj/main.c calls it with two 100-byte stack buffers. Any datum value over 99 characters overflows the first; any towgs84/nadgrids value, or the three dx/dy/dz values combined (joined as "towgs84=%s,%s,%s"), over roughly 90 characters overflows the second. These values come from a location's PROJ_INFO file, which is plain text and not length-validated anywhere -- hand-edited, imported from an external CRS/WKT definition via g.proj, or shipped in a downloaded sample or shared location. lib/gis/proj3.c's own caller uses 256-byte buffers -- so the function already has two different "safe" sizes depending on which caller you look at, which is the real problem: there is no size the function itself can assume. Added explicit size_t parameters for each buffer and switched both sprintf calls to snprintf, updating both call sites (g.setproj and proj3.c) to pass sizeof() their own buffers. Verified with a small program linked against a local build of libgrass_gis: a 499-character towgs84 value, which previously overflowed the 100-byte g.setproj buffer via plain sprintf, now truncates safely to 99 characters plus the terminator instead. Built the gis library (grass_gis target) clean with the change. Fixes #7982. Signed-off-by: sai pranav --- general/g.setproj/main.c | 5 +++-- include/grass/defs/gis.h | 3 ++- lib/gis/datum.c | 27 ++++++++++++++++++--------- lib/gis/proj3.c | 3 ++- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/general/g.setproj/main.c b/general/g.setproj/main.c index 2f6c10b0a01..716b5c5d31a 100644 --- a/general/g.setproj/main.c +++ b/general/g.setproj/main.c @@ -209,8 +209,9 @@ int main(int argc, char *argv[]) 1)) { char lbuf[100], lbufa[100]; - if (exist && (G_get_datumparams_from_projinfo(old_proj_keys, lbuf, - lbufa) == 2)) { + if (exist && + (G_get_datumparams_from_projinfo(old_proj_keys, lbuf, sizeof(lbuf), + lbufa, sizeof(lbufa)) == 2)) { G_strip(lbuf); if ((i = G_get_datum_by_name(lbuf)) > 0) { G_message(_("The current datum is %s (%s)"), G_datum_name(i), diff --git a/include/grass/defs/gis.h b/include/grass/defs/gis.h index 498418fb01e..9fb1bb25c73 100644 --- a/include/grass/defs/gis.h +++ b/include/grass/defs/gis.h @@ -299,7 +299,8 @@ int G_get_datum_by_name(const char *); const char *G_datum_name(int); const char *G_datum_description(int); const char *G_datum_ellipsoid(int); -int G_get_datumparams_from_projinfo(const struct Key_Value *, char *, char *); +int G_get_datumparams_from_projinfo(const struct Key_Value *, char *, size_t, + char *, size_t); void G_read_datum_table(void); /* debug.c */ diff --git a/lib/gis/datum.c b/lib/gis/datum.c index 3c2d74ca981..cb0627be983 100644 --- a/lib/gis/datum.c +++ b/lib/gis/datum.c @@ -81,16 +81,19 @@ const char *G_datum_ellipsoid(int n) } /*********************************************************** - * G_get_datumparams_from_projinfo(projinfo, datumname, params) + * G_get_datumparams_from_projinfo(projinfo, datumname, datumname_size, + * params, params_size) * struct Key_Value *projinfo Set of key_value pairs containing * projection information in PROJ_INFO file * format * char *datumname Pointer into which a string containing * the datum name (if present) will be * placed. + * size_t datumname_size Size in bytes of the datumname buffer. * char *params Pointer into which a string containing * the datum parameters (if present) will * be placed. + * size_t params_size Size in bytes of the params buffer. * * Extract the datum transformation-related parameters from a * set of general PROJ_INFO parameters. @@ -102,33 +105,39 @@ const char *G_datum_ellipsoid(int n) ************************************************************/ int G_get_datumparams_from_projinfo(const struct Key_Value *projinfo, - char *datumname, char *params) + char *datumname, size_t datumname_size, + char *params, size_t params_size) { int returnval = -1; if (NULL != G_find_key_value("datum", projinfo)) { - sprintf(datumname, "%s", G_find_key_value("datum", projinfo)); + snprintf(datumname, datumname_size, "%s", + G_find_key_value("datum", projinfo)); returnval = 1; } if (G_find_key_value("datumparams", projinfo) != NULL) { - sprintf(params, "%s", G_find_key_value("datumparams", projinfo)); + snprintf(params, params_size, "%s", + G_find_key_value("datumparams", projinfo)); returnval = 2; } else if (G_find_key_value("nadgrids", projinfo) != NULL) { - sprintf(params, "nadgrids=%s", G_find_key_value("nadgrids", projinfo)); + snprintf(params, params_size, "nadgrids=%s", + G_find_key_value("nadgrids", projinfo)); returnval = 2; } else if (G_find_key_value("towgs84", projinfo) != NULL) { - sprintf(params, "towgs84=%s", G_find_key_value("towgs84", projinfo)); + snprintf(params, params_size, "towgs84=%s", + G_find_key_value("towgs84", projinfo)); returnval = 2; } else if (G_find_key_value("dx", projinfo) != NULL && G_find_key_value("dy", projinfo) != NULL && G_find_key_value("dz", projinfo) != NULL) { - sprintf(params, "towgs84=%s,%s,%s", G_find_key_value("dx", projinfo), - G_find_key_value("dy", projinfo), - G_find_key_value("dz", projinfo)); + snprintf(params, params_size, "towgs84=%s,%s,%s", + G_find_key_value("dx", projinfo), + G_find_key_value("dy", projinfo), + G_find_key_value("dz", projinfo)); returnval = 2; } diff --git a/lib/gis/proj3.c b/lib/gis/proj3.c index 4c1491452c4..640d8f3f4b3 100644 --- a/lib/gis/proj3.c +++ b/lib/gis/proj3.c @@ -193,7 +193,8 @@ const char *G_database_datum_name(void) else if (!proj_info) return NULL; else - datumstatus = G_get_datumparams_from_projinfo(proj_info, buf, params); + datumstatus = G_get_datumparams_from_projinfo( + proj_info, buf, sizeof(buf), params, sizeof(params)); if (datumstatus == 2) return G_store(params);