v2-0001-snapmgr-replace-sscanf-with-strtol-strtoul-in-sna.patch
application/octet-stream
Filename: v2-0001-snapmgr-replace-sscanf-with-strtol-strtoul-in-sna.patch
Type: application/octet-stream
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v2-0001
Subject: snapmgr: replace sscanf with strtol/strtoul in snapshot parse helpers
| File | + | − |
|---|---|---|
| src/backend/utils/time/snapmgr.c | 37 | 10 |
From 583dc36426508b73364a681be6ed29e1a4d87808 Mon Sep 17 00:00:00 2001
From: Amul Sul <sulamul@gmail.com>
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