]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix cidin() to handle values above 2^31 platform-independently.
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 18 Oct 2016 16:24:46 +0000 (12:24 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 18 Oct 2016 16:25:21 +0000 (12:25 -0400)
CommandId is declared as uint32, and values up to 4G are indeed legal.
cidout() handles them properly by treating the value as unsigned int.
But cidin() was just using atoi(), which has platform-dependent behavior
for values outside the range of signed int, as reported by Bart Lengkeek
in bug #14379.  Use strtoul() instead, as xidin() does.

In passing, make some purely cosmetic changes to make xidin/xidout
look more like cidin/cidout; the former didn't have a monopoly on
best practice IMO.

Neither xidin nor cidin make any attempt to throw error for invalid input.
I didn't change that here, and am not sure it's worth worrying about
since neither is really a user-facing type.  The point is just to ensure
that indubitably-valid inputs work as expected.

It's been like this for a long time, so back-patch to all supported
branches.

Report: <20161018152550.1413.6439@wrigleys.postgresql.org>

src/backend/utils/adt/xid.c

index 76d29ff2a379de01d0e895ccd3fc2601cfcadd13..da8d1f30d5291ee30817de0da0e8794450f0cdad 100644 (file)
@@ -40,13 +40,10 @@ Datum
 xidout(PG_FUNCTION_ARGS)
 {
        TransactionId transactionId = PG_GETARG_TRANSACTIONID(0);
+       char       *result = (char *) palloc(16);
 
-       /* maximum 32 bit unsigned integer representation takes 10 chars */
-       char       *str = palloc(11);
-
-       snprintf(str, 11, "%lu", (unsigned long) transactionId);
-
-       PG_RETURN_CSTRING(str);
+       snprintf(result, 16, "%lu", (unsigned long) transactionId);
+       PG_RETURN_CSTRING(result);
 }
 
 /*
@@ -132,12 +129,9 @@ xidComparator(const void *arg1, const void *arg2)
 Datum
 cidin(PG_FUNCTION_ARGS)
 {
-       char       *s = PG_GETARG_CSTRING(0);
-       CommandId       c;
-
-       c = atoi(s);
+       char       *str = PG_GETARG_CSTRING(0);
 
-       PG_RETURN_COMMANDID(c);
+       PG_RETURN_COMMANDID((CommandId) strtoul(str, NULL, 0));
 }
 
 /*
@@ -149,7 +143,7 @@ cidout(PG_FUNCTION_ARGS)
        CommandId       c = PG_GETARG_COMMANDID(0);
        char       *result = (char *) palloc(16);
 
-       snprintf(result, 16, "%u", (unsigned int) c);
+       snprintf(result, 16, "%lu", (unsigned long) c);
        PG_RETURN_CSTRING(result);
 }