]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Validate -l and -L arguments in named-checkzone
authorOndřej Surý <ondrej@isc.org>
Wed, 29 Apr 2026 12:52:21 +0000 (14:52 +0200)
committerOndřej Surý <ondrej@isc.org>
Wed, 29 Apr 2026 15:25:49 +0000 (17:25 +0200)
The -l (max TTL) and -L (source serial) flags parsed their arguments
with strtol() and assigned the result directly to uint32_t with no
range check. A negative value such as -1 became UINT32_MAX, which made
-l silently disable the TTL cap it claimed to enforce, and out-of-range
values truncated to 32 bits without warning.

Switch both flags to isc_parse_uint32(), which rejects leading non-
alphanumeric input (catching '-'), checks ERANGE, and validates the
32-bit range, so an invalid argument now exits with an error instead
of being silently coerced.

Assisted-by: Claude:claude-opus-4-7
bin/check/named-checkzone.c

index 9a15eec34e9913d20e4b259a5267f3ea0828ca47..40b4eabd1f9cd9f6b1c794f9e67898ea7750b9c4 100644 (file)
@@ -24,6 +24,7 @@
 #include <isc/lib.h>
 #include <isc/log.h>
 #include <isc/mem.h>
+#include <isc/parseint.h>
 #include <isc/result.h>
 #include <isc/string.h>
 #include <isc/timer.h>
@@ -107,7 +108,6 @@ main(int argc, char **argv) {
        bool snset = false;
        bool logdump = false;
        FILE *errout = stdout;
-       char *endp;
 
        outputstyle = &dns_master_style_full;
 
@@ -222,22 +222,23 @@ main(int argc, char **argv) {
 
                case 'L':
                        snset = true;
-                       endp = NULL;
-                       serialnum = strtol(isc_commandline_argument, &endp, 0);
-                       if (*endp != '\0') {
-                               fprintf(stderr, "source serial number "
-                                               "must be numeric");
+                       if (isc_parse_uint32(&serialnum,
+                                            isc_commandline_argument,
+                                            0) != ISC_R_SUCCESS)
+                       {
+                               fprintf(stderr, "source serial number must be "
+                                               "a 32-bit unsigned integer\n");
                                exit(EXIT_FAILURE);
                        }
                        break;
 
                case 'l':
                        zone_options |= DNS_ZONEOPT_CHECKTTL;
-                       endp = NULL;
-                       maxttl = strtol(isc_commandline_argument, &endp, 0);
-                       if (*endp != '\0') {
-                               fprintf(stderr, "maximum TTL "
-                                               "must be numeric");
+                       if (isc_parse_uint32(&maxttl, isc_commandline_argument,
+                                            0) != ISC_R_SUCCESS)
+                       {
+                               fprintf(stderr, "maximum TTL must be a 32-bit "
+                                               "unsigned integer\n");
                                exit(EXIT_FAILURE);
                        }
                        break;