pg_resetwal: Improve numeric command-line argument parsing

Check errno after strtoul()/strtol() to handle out of range errors
better.  For out of range, strtoul() returns ULONG_MAX, and the
previous code would proceed with that result.

Reported-by: Mark Dilger <mark.dilger@enterprisedb.com>
Discussion: https://www.postgresql.org/message-id/flat/6a10a211-872b-3c4c-106b-909ae5fefa61%40enterprisedb.com
This commit is contained in:
Peter Eisentraut 2021-08-20 07:54:23 +02:00
parent f1899f251d
commit 9a6345ed74
1 changed files with 18 additions and 10 deletions

View File

@ -154,8 +154,9 @@ main(int argc, char *argv[])
break; break;
case 'e': case 'e':
errno = 0;
set_xid_epoch = strtoul(optarg, &endptr, 0); set_xid_epoch = strtoul(optarg, &endptr, 0);
if (endptr == optarg || *endptr != '\0') if (endptr == optarg || *endptr != '\0' || errno != 0)
{ {
/*------ /*------
translator: the second %s is a command line argument (-e, etc) */ translator: the second %s is a command line argument (-e, etc) */
@ -171,8 +172,9 @@ main(int argc, char *argv[])
break; break;
case 'u': case 'u':
errno = 0;
set_oldest_xid = strtoul(optarg, &endptr, 0); set_oldest_xid = strtoul(optarg, &endptr, 0);
if (endptr == optarg || *endptr != '\0') if (endptr == optarg || *endptr != '\0' || errno != 0)
{ {
pg_log_error("invalid argument for option %s", "-u"); pg_log_error("invalid argument for option %s", "-u");
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
@ -186,8 +188,9 @@ main(int argc, char *argv[])
break; break;
case 'x': case 'x':
errno = 0;
set_xid = strtoul(optarg, &endptr, 0); set_xid = strtoul(optarg, &endptr, 0);
if (endptr == optarg || *endptr != '\0') if (endptr == optarg || *endptr != '\0' || errno != 0)
{ {
pg_log_error("invalid argument for option %s", "-x"); pg_log_error("invalid argument for option %s", "-x");
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
@ -201,15 +204,16 @@ main(int argc, char *argv[])
break; break;
case 'c': case 'c':
errno = 0;
set_oldest_commit_ts_xid = strtoul(optarg, &endptr, 0); set_oldest_commit_ts_xid = strtoul(optarg, &endptr, 0);
if (endptr == optarg || *endptr != ',') if (endptr == optarg || *endptr != ',' || errno != 0)
{ {
pg_log_error("invalid argument for option %s", "-c"); pg_log_error("invalid argument for option %s", "-c");
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
exit(1); exit(1);
} }
set_newest_commit_ts_xid = strtoul(endptr + 1, &endptr2, 0); set_newest_commit_ts_xid = strtoul(endptr + 1, &endptr2, 0);
if (endptr2 == endptr + 1 || *endptr2 != '\0') if (endptr2 == endptr + 1 || *endptr2 != '\0' || errno != 0)
{ {
pg_log_error("invalid argument for option %s", "-c"); pg_log_error("invalid argument for option %s", "-c");
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
@ -232,8 +236,9 @@ main(int argc, char *argv[])
break; break;
case 'o': case 'o':
errno = 0;
set_oid = strtoul(optarg, &endptr, 0); set_oid = strtoul(optarg, &endptr, 0);
if (endptr == optarg || *endptr != '\0') if (endptr == optarg || *endptr != '\0' || errno != 0)
{ {
pg_log_error("invalid argument for option %s", "-o"); pg_log_error("invalid argument for option %s", "-o");
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
@ -247,8 +252,9 @@ main(int argc, char *argv[])
break; break;
case 'm': case 'm':
errno = 0;
set_mxid = strtoul(optarg, &endptr, 0); set_mxid = strtoul(optarg, &endptr, 0);
if (endptr == optarg || *endptr != ',') if (endptr == optarg || *endptr != ',' || errno != 0)
{ {
pg_log_error("invalid argument for option %s", "-m"); pg_log_error("invalid argument for option %s", "-m");
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
@ -256,7 +262,7 @@ main(int argc, char *argv[])
} }
set_oldestmxid = strtoul(endptr + 1, &endptr2, 0); set_oldestmxid = strtoul(endptr + 1, &endptr2, 0);
if (endptr2 == endptr + 1 || *endptr2 != '\0') if (endptr2 == endptr + 1 || *endptr2 != '\0' || errno != 0)
{ {
pg_log_error("invalid argument for option %s", "-m"); pg_log_error("invalid argument for option %s", "-m");
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
@ -280,8 +286,9 @@ main(int argc, char *argv[])
break; break;
case 'O': case 'O':
errno = 0;
set_mxoff = strtoul(optarg, &endptr, 0); set_mxoff = strtoul(optarg, &endptr, 0);
if (endptr == optarg || *endptr != '\0') if (endptr == optarg || *endptr != '\0' || errno != 0)
{ {
pg_log_error("invalid argument for option %s", "-O"); pg_log_error("invalid argument for option %s", "-O");
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
@ -310,8 +317,9 @@ main(int argc, char *argv[])
break; break;
case 1: case 1:
errno = 0;
set_wal_segsize = strtol(optarg, &endptr, 10) * 1024 * 1024; set_wal_segsize = strtol(optarg, &endptr, 10) * 1024 * 1024;
if (endptr == optarg || *endptr != '\0') if (endptr == optarg || *endptr != '\0' || errno != 0)
{ {
pg_log_error("argument of --wal-segsize must be a number"); pg_log_error("argument of --wal-segsize must be a number");
exit(1); exit(1);