From 9869b9f19775de7d13f1bada5db5d8f14bf20859 Mon Sep 17 00:00:00 2001 From: Amul Sul Date: Mon, 20 Apr 2026 10:21:28 +0530 Subject: [PATCH] snapmgr: replace sscanf with strtol/strtoul in snapshot parse helpers parseIntFromText, parseXidFromText, and parseVxidFromText used sscanf to convert digit strings to integers. Replace with strtol/strtoul, which provide explicit overflow detection and advance the end-pointer directly, avoiding a redundant strchr scan over the already-parsed digits. --- src/backend/utils/time/snapmgr.c | 45 +++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 10fe18df2e7..20b8421b881 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -1308,24 +1308,27 @@ parseIntFromText(const char *prefix, char **s, const char *filename) { char *ptr = *s; int prefixlen = strlen(prefix); - int val; + long val; + char *endptr; if (strncmp(ptr, prefix, prefixlen) != 0) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid snapshot data in file \"%s\"", filename))); ptr += prefixlen; - if (sscanf(ptr, "%d", &val) != 1) + errno = 0; + val = strtol(ptr, &endptr, 10); + if (endptr == ptr || errno != 0 || val < INT_MIN || val > INT_MAX) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid snapshot data in file \"%s\"", filename))); - ptr = strchr(ptr, '\n'); + ptr = strchr(endptr, '\n'); if (!ptr) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid snapshot data in file \"%s\"", filename))); *s = ptr + 1; - return val; + return (int) val; } static TransactionId @@ -1333,24 +1336,27 @@ parseXidFromText(const char *prefix, char **s, const char *filename) { char *ptr = *s; int prefixlen = strlen(prefix); - TransactionId val; + unsigned long val; + char *endptr; if (strncmp(ptr, prefix, prefixlen) != 0) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid snapshot data in file \"%s\"", filename))); ptr += prefixlen; - if (sscanf(ptr, "%u", &val) != 1) + errno = 0; + val = strtoul(ptr, &endptr, 10); + if (endptr == ptr || errno != 0 || val > UINT_MAX) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid snapshot data in file \"%s\"", filename))); - ptr = strchr(ptr, '\n'); + ptr = strchr(endptr, '\n'); if (!ptr) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid snapshot data in file \"%s\"", filename))); *s = ptr + 1; - return val; + return (TransactionId) val; } static void @@ -1359,17 +1365,36 @@ parseVxidFromText(const char *prefix, char **s, const char *filename, { char *ptr = *s; int prefixlen = strlen(prefix); + long lval; + unsigned long ulval; + char *endptr; if (strncmp(ptr, prefix, prefixlen) != 0) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid snapshot data in file \"%s\"", filename))); ptr += prefixlen; - if (sscanf(ptr, "%d/%u", &vxid->procNumber, &vxid->localTransactionId) != 2) + + /* Parse procNumber (the signed integer before '/') */ + errno = 0; + lval = strtol(ptr, &endptr, 10); + if (endptr == ptr || errno != 0 || lval < INT_MIN || lval > INT_MAX || + *endptr != '/') ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid snapshot data in file \"%s\"", filename))); - ptr = strchr(ptr, '\n'); + vxid->procNumber = (ProcNumber) lval; + ptr = endptr + 1; /* skip the '/' separator */ + + /* Parse localTransactionId (the unsigned integer after '/') */ + errno = 0; + ulval = strtoul(ptr, &endptr, 10); + if (endptr == ptr || errno != 0 || ulval > UINT_MAX) + ereport(ERROR, + (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid snapshot data in file \"%s\"", filename))); + vxid->localTransactionId = (LocalTransactionId) ulval; + ptr = strchr(endptr, '\n'); if (!ptr) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), -- 2.47.1