From 583dc36426508b73364a681be6ed29e1a4d87808 Mon Sep 17 00:00:00 2001 From: Amul Sul Date: Mon, 20 Apr 2026 10:21:28 +0530 Subject: [PATCH v2] 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 | 47 +++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 10fe18df2e7..27a0ec835e8 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -1308,24 +1308,28 @@ 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 +1337,27 @@ parseXidFromText(const char *prefix, char **s, const char *filename) { char *ptr = *s; int prefixlen = strlen(prefix); - TransactionId val; + unsigned long xid; + 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; + xid = strtoul(ptr, &endptr, 10); + if (endptr == ptr || errno != 0 || xid > 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) xid; } static void @@ -1359,17 +1366,37 @@ parseVxidFromText(const char *prefix, char **s, const char *filename, { char *ptr = *s; int prefixlen = strlen(prefix); + long procno; + unsigned long xid; + 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; + procno = strtol(ptr, &endptr, 10); + if (endptr == ptr || errno != 0 || + procno < INT_MIN || procno > 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) procno; + ptr = endptr + 1; /* skip the '/' separator */ + + /* Parse localTransactionId (the unsigned integer after '/') */ + errno = 0; + xid = strtoul(ptr, &endptr, 10); + if (endptr == ptr || errno != 0 || xid > UINT_MAX) + ereport(ERROR, + (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid snapshot data in file \"%s\"", filename))); + vxid->localTransactionId = (LocalTransactionId) xid; + ptr = strchr(endptr, '\n'); if (!ptr) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), -- 2.47.1