From 9a6345ed741783e8770ef160e822d2257873adef Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Fri, 20 Aug 2021 07:54:23 +0200 Subject: [PATCH] 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 Discussion: https://www.postgresql.org/message-id/flat/6a10a211-872b-3c4c-106b-909ae5fefa61%40enterprisedb.com --- src/bin/pg_resetwal/pg_resetwal.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c index 36749648573..84b6f70ad6a 100644 --- a/src/bin/pg_resetwal/pg_resetwal.c +++ b/src/bin/pg_resetwal/pg_resetwal.c @@ -154,8 +154,9 @@ main(int argc, char *argv[]) break; case 'e': + errno = 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) */ @@ -171,8 +172,9 @@ main(int argc, char *argv[]) break; case 'u': + errno = 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"); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); @@ -186,8 +188,9 @@ main(int argc, char *argv[]) break; case 'x': + errno = 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"); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); @@ -201,15 +204,16 @@ main(int argc, char *argv[]) break; case 'c': + errno = 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"); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); exit(1); } 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"); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); @@ -232,8 +236,9 @@ main(int argc, char *argv[]) break; case 'o': + errno = 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"); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); @@ -247,8 +252,9 @@ main(int argc, char *argv[]) break; case 'm': + errno = 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"); 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); - if (endptr2 == endptr + 1 || *endptr2 != '\0') + if (endptr2 == endptr + 1 || *endptr2 != '\0' || errno != 0) { pg_log_error("invalid argument for option %s", "-m"); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); @@ -280,8 +286,9 @@ main(int argc, char *argv[]) break; case 'O': + errno = 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"); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); @@ -310,8 +317,9 @@ main(int argc, char *argv[]) break; case 1: + errno = 0; 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"); exit(1);