summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/txid/expected/txid.out21
-rw-r--r--contrib/txid/sql/txid.sql3
-rw-r--r--contrib/txid/txid.c48
3 files changed, 59 insertions, 13 deletions
diff --git a/contrib/txid/expected/txid.out b/contrib/txid/expected/txid.out
index c0220bb525c..1b0da20b5f6 100644
--- a/contrib/txid/expected/txid.out
+++ b/contrib/txid/expected/txid.out
@@ -8,18 +8,18 @@ select '12:13:'::txid_snapshot;
(1 row)
select '12:13:1,2'::txid_snapshot;
-ERROR: illegal txid_snapshot input format
+ERROR: invalid input for txid_snapshot: "12:13:1,2"
-- errors
select '31:12:'::txid_snapshot;
-ERROR: illegal txid_snapshot input format
+ERROR: invalid input for txid_snapshot: "31:12:"
select '0:1:'::txid_snapshot;
-ERROR: illegal txid_snapshot input format
+ERROR: invalid input for txid_snapshot: "0:1:"
select '12:13:0'::txid_snapshot;
-ERROR: illegal txid_snapshot input format
+ERROR: invalid input for txid_snapshot: "12:13:0"
select '12:16:14,13'::txid_snapshot;
-ERROR: illegal txid_snapshot input format
+ERROR: invalid input for txid_snapshot: "12:16:14,13"
select '12:16:14,14'::txid_snapshot;
-ERROR: illegal txid_snapshot input format
+ERROR: invalid input for txid_snapshot: "12:16:14,14"
create table snapshot_test (
nr integer,
snap txid_snapshot
@@ -210,3 +210,12 @@ select txid_visible_in_snapshot('1000100010001015', '1000100010001000:1000100010
t
(1 row)
+-- test 64bit overflow
+SELECT txid_snapshot '1:9223372036854775807:3';
+ txid_snapshot
+-------------------------
+ 1:9223372036854775807:3
+(1 row)
+
+SELECT txid_snapshot '1:9223372036854775808:3';
+ERROR: invalid input for txid_snapshot: "1:9223372036854775808:3"
diff --git a/contrib/txid/sql/txid.sql b/contrib/txid/sql/txid.sql
index b86bfffb050..efedb86bfac 100644
--- a/contrib/txid/sql/txid.sql
+++ b/contrib/txid/sql/txid.sql
@@ -56,3 +56,6 @@ select txid_snapshot '1000100010001000:1000100010001100:1000100010001012,1000100
select txid_visible_in_snapshot('1000100010001012', '1000100010001000:1000100010001100:1000100010001012,1000100010001013');
select txid_visible_in_snapshot('1000100010001015', '1000100010001000:1000100010001100:1000100010001012,1000100010001013');
+-- test 64bit overflow
+SELECT txid_snapshot '1:9223372036854775807:3';
+SELECT txid_snapshot '1:9223372036854775808:3';
diff --git a/contrib/txid/txid.c b/contrib/txid/txid.c
index 8a4b5e797ba..606fb40040b 100644
--- a/contrib/txid/txid.c
+++ b/contrib/txid/txid.c
@@ -226,6 +226,39 @@ buf_finalize(StringInfo buf)
}
/*
+ * simple number parser.
+ *
+ * We return 0 on error, which is invalid value for txid.
+ */
+static txid
+str2txid(const char *s, const char **endp)
+{
+ txid val = 0;
+
+ for (; *s; s++)
+ {
+ txid last = val;
+
+ if (*s < '0' || *s > '9')
+ break;
+
+ val = val * 10 + (*s - '0');
+
+ /*
+ * check for overflow
+ */
+ if (val > MAX_TXID || (val / 10) != last)
+ {
+ val = 0;
+ break;
+ }
+ }
+ if (endp)
+ *endp = s;
+ return val;
+}
+
+/*
* parse snapshot from cstring
*/
static TxidSnapshot *
@@ -234,21 +267,22 @@ parse_snapshot(const char *str)
txid xmin;
txid xmax;
txid last_val = 0, val;
- char *endp;
+ const char *str_start = str;
+ const char *endp;
StringInfo buf;
- xmin = (txid) strtoull(str, &endp, 0);
+ xmin = str2txid(str, &endp);
if (*endp != ':')
goto bad_format;
str = endp + 1;
- xmax = (txid) strtoull(str, &endp, 0);
+ xmax = str2txid(str, &endp);
if (*endp != ':')
goto bad_format;
str = endp + 1;
/* it should look sane */
- if (xmin > xmax || xmin == 0 || xmax > MAX_TXID)
+ if (xmin == 0 || xmax == 0 || xmin > xmax)
goto bad_format;
/* allocate buffer */
@@ -258,11 +292,11 @@ parse_snapshot(const char *str)
while (*str != '\0')
{
/* read next value */
- val = (txid) strtoull(str, &endp, 0);
+ val = str2txid(str, &endp);
str = endp;
/* require the input to be in order */
- if (val < xmin || val <= last_val || val >= xmax)
+ if (val < xmin || val >= xmax || val <= last_val)
goto bad_format;
buf_add_txid(buf, val);
@@ -277,7 +311,7 @@ parse_snapshot(const char *str)
return buf_finalize(buf);
bad_format:
- elog(ERROR, "illegal txid_snapshot input format");
+ elog(ERROR, "invalid input for txid_snapshot: \"%s\"", str_start);
return NULL;
}