static void KillExistingWALSummaries(void);
static void WriteEmptyXLOG(void);
static void usage(void);
+static uint32 strtouint32_strict(const char *restrict s, char **restrict endptr, int base);
int
MultiXactId set_oldestmxid = 0;
char *endptr;
char *endptr2;
- int64 tmpi64;
char *DataDir = NULL;
char *log_fname = NULL;
int fd;
case 'e':
errno = 0;
- set_xid_epoch = strtoul(optarg, &endptr, 0);
+ set_xid_epoch = strtouint32_strict(optarg, &endptr, 0);
if (endptr == optarg || *endptr != '\0' || errno != 0)
{
/*------
case 'u':
errno = 0;
- set_oldest_xid = strtoul(optarg, &endptr, 0);
+ set_oldest_xid = strtouint32_strict(optarg, &endptr, 0);
if (endptr == optarg || *endptr != '\0' || errno != 0)
{
pg_log_error("invalid argument for option %s", "-u");
case 'x':
errno = 0;
- set_xid = strtoul(optarg, &endptr, 0);
+ set_xid = strtouint32_strict(optarg, &endptr, 0);
if (endptr == optarg || *endptr != '\0' || errno != 0)
{
pg_log_error("invalid argument for option %s", "-x");
case 'c':
errno = 0;
- set_oldest_commit_ts_xid = strtoul(optarg, &endptr, 0);
+ set_oldest_commit_ts_xid = strtouint32_strict(optarg, &endptr, 0);
if (endptr == optarg || *endptr != ',' || errno != 0)
{
pg_log_error("invalid argument for option %s", "-c");
case 'o':
errno = 0;
- set_oid = strtoul(optarg, &endptr, 0);
+ set_oid = strtouint32_strict(optarg, &endptr, 0);
if (endptr == optarg || *endptr != '\0' || errno != 0)
{
pg_log_error("invalid argument for option %s", "-o");
case 'm':
errno = 0;
- set_mxid = strtoul(optarg, &endptr, 0);
+ set_mxid = strtouint32_strict(optarg, &endptr, 0);
if (endptr == optarg || *endptr != ',' || errno != 0)
{
pg_log_error("invalid argument for option %s", "-m");
exit(1);
}
- set_oldestmxid = strtoul(endptr + 1, &endptr2, 0);
+ set_oldestmxid = strtouint32_strict(endptr + 1, &endptr2, 0);
if (endptr2 == endptr + 1 || *endptr2 != '\0' || errno != 0)
{
pg_log_error("invalid argument for option %s", "-m");
case 'O':
errno = 0;
- tmpi64 = strtoi64(optarg, &endptr, 0);
+ set_mxoff = strtouint32_strict(optarg, &endptr, 0);
if (endptr == optarg || *endptr != '\0' || errno != 0)
{
pg_log_error("invalid argument for option %s", "-O");
pg_log_error_hint("Try \"%s --help\" for more information.", progname);
exit(1);
}
- if (tmpi64 < 0 || tmpi64 > (int64) MaxMultiXactOffset)
- pg_fatal("multitransaction offset (-O) must be between 0 and %u", MaxMultiXactOffset);
-
- set_mxoff = (MultiXactOffset) tmpi64;
mxoff_given = true;
break;
printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
}
+
+/*
+ * strtouint32_strict -- like strtoul(), but returns uint32 and doesn't accept
+ * negative values
+ */
+static uint32
+strtouint32_strict(const char *restrict s, char **restrict endptr, int base)
+{
+ unsigned long val;
+ bool is_neg;
+
+ /* skip leading whitespace */
+ while (isspace(*s))
+ s++;
+
+ /*
+ * Is it negative? We still call strtoul() if it was, to set 'endptr'.
+ * (The current callers don't care though.)
+ */
+ is_neg = (*s == '-');
+
+ val = strtoul(s, endptr, base);
+
+ /* reject if it was negative */
+ if (errno == 0 && is_neg)
+ {
+ errno = ERANGE;
+ val = 0;
+ }
+
+ /*
+ * reject values larger than UINT32_MAX on platforms where long is 64 bits
+ * wide.
+ */
+ if (errno == 0 && val != (uint32) val)
+ {
+ errno = ERANGE;
+ val = UINT32_MAX;
+ }
+
+ return (uint32) val;
+}
'fails with incorrect -e option');
command_fails_like(
[ 'pg_resetwal', '-e' => '-1', $node->data_dir ],
- qr/must not be -1/,
+ qr/error: invalid argument for option -e/,
'fails with -e value -1');
# -l
command_fails_like(
# This used to be forbidden, but nextMulti can legitimately be 0 after
# wraparound, so we now accept it in pg_resetwal too.
-command_ok([ 'pg_resetwal', '-m' => '0,10', $node->data_dir ],
- 'succeeds with -m value 0 part 1');
+command_ok(
+ [ 'pg_resetwal', '-m' => '0,10', $node->data_dir ],
+ 'succeeds with -m value 0 in the first part');
+
+# -0 doesn't make sense however
+command_fails_like(
+ [ 'pg_resetwal', '-m' => '-0,10', $node->data_dir ],
+ qr/error: invalid argument for option -m/,
+ 'fails with -m value -0 in the first part');
command_fails_like(
[ 'pg_resetwal', '-m' => '10,0', $node->data_dir ],
qr/must not be 0/,
- 'fails with -m value 0 part 2');
+ 'fails with -m value 0 in the second part');
# -o
command_fails_like(
[ 'pg_resetwal', '-o' => 'foo', $node->data_dir ],
'fails with incorrect -O option');
command_fails_like(
[ 'pg_resetwal', '-O' => '-1', $node->data_dir ],
- qr/must be between 0 and 4294967295/,
+ qr/error: invalid argument for option -O/,
'fails with -O value -1');
# --wal-segsize
command_fails_like(
qr/must be greater than/,
'fails with -x value too small');
+# Check out of range values with -x. These are forbidden for all other
+# 32-bit values too, but we use just -x to exercise the parsing.
+command_fails_like(
+ [ 'pg_resetwal', '-x' => '-1', $node->data_dir ],
+ qr/error: invalid argument for option -x/,
+ 'fails with -x value -1');
+command_fails_like(
+ [ 'pg_resetwal', '-x' => '-100', $node->data_dir ],
+ qr/error: invalid argument for option -x/,
+ 'fails with negative -x value');
+command_fails_like(
+ [ 'pg_resetwal', '-x' => '10000000000', $node->data_dir ],
+ qr/error: invalid argument for option -x/,
+ 'fails with -x value too large');
+
# --char-signedness
command_fails_like(
[ 'pg_resetwal', '--char-signedness', 'foo', $node->data_dir ],