pg_resetwal: Improve numeric command-line argument parsing
authorPeter Eisentraut
Fri, 20 Aug 2021 05:54:23 +0000 (07:54 +0200)
committerPeter Eisentraut
Fri, 20 Aug 2021 08:51:59 +0000 (10:51 +0200)
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

index 367496485734f24bcd9b92711893e290d29f4562..84b6f70ad6a7c91ce0fd8ed831628155adac922c 100644 (file)
@@ -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);