]> git.ipfire.org Git - thirdparty/git.git/commitdiff
parse-options: add precision handling for OPTION_COUNTUP
authorRené Scharfe <l.s.r@web.de>
Wed, 9 Jul 2025 09:46:28 +0000 (11:46 +0200)
committerJunio C Hamano <gitster@pobox.com>
Wed, 9 Jul 2025 15:40:32 +0000 (08:40 -0700)
Similar to 09705696f7 (parse-options: introduce precision handling for
`OPTION_INTEGER`, 2025-04-17) support value variables of different sizes
for OPTION_COUNTUP.  Do that by requiring their "precision" to be set,
casting their "value" pointer accordingly and checking whether the value
fits.

Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
parse-options.c
parse-options.h
t/helper/test-parse-options.c

index a813511b1bcb68c348cc840b2f26ef98544dcecd..5224203ffe7bf8a70b4f58060bed20a5dad1afae 100644 (file)
@@ -177,10 +177,22 @@ static enum parse_opt_result do_get_value(struct parse_opt_ctx_t *p,
        }
 
        case OPTION_COUNTUP:
-               if (*(int *)opt->value < 0)
-                       *(int *)opt->value = 0;
-               *(int *)opt->value = unset ? 0 : *(int *)opt->value + 1;
-               return 0;
+       {
+               size_t bits = CHAR_BIT * opt->precision;
+               intmax_t upper_bound = INTMAX_MAX >> (bitsizeof(intmax_t) - bits);
+               intmax_t value = get_int_value(opt, flags);
+
+               if (value < 0)
+                       value = 0;
+               if (unset)
+                       value = 0;
+               else if (value < upper_bound)
+                       value++;
+               else
+                       return error(_("value for %s exceeds %"PRIdMAX),
+                                    optname(opt, flags), upper_bound);
+               return set_int_value(opt, flags, value);
+       }
 
        case OPTION_SET_INT:
                return set_int_value(opt, flags, unset ? 0 : opt->defval);
@@ -651,10 +663,10 @@ static void parse_options_check(const struct option *opts)
                case OPTION_BIT:
                case OPTION_NEGBIT:
                case OPTION_BITOP:
+               case OPTION_COUNTUP:
                        if (!signed_int_fits(opts->defval, opts->precision))
                                optbug(opts, "has invalid defval");
                        /* fallthru */
-               case OPTION_COUNTUP:
                case OPTION_NUMBER:
                        if ((opts->flags & PARSE_OPT_OPTARG) ||
                            !(opts->flags & PARSE_OPT_NOARG))
index 8bdf469ae9b29a5bd0b6f4b56e927735036ee308..312045604d98d1e806d67b60451b053fbfb4a37a 100644 (file)
@@ -183,6 +183,7 @@ struct option {
        .short_name = (s), \
        .long_name = (l), \
        .value = (v), \
+       .precision = sizeof(*v), \
        .help = (h), \
        .flags = PARSE_OPT_NOARG|(f), \
 }
index 2ba2546d70a0e91118fb785ff0061aaba1da7610..68579d83f3939e8f17ed0822e16d61c3c9d8253b 100644 (file)
@@ -178,6 +178,7 @@ int cmd__parse_options(int argc, const char **argv)
                        .type = OPTION_COUNTUP,
                        .short_name = '+',
                        .value = &boolean,
+                       .precision = sizeof(boolean),
                        .help = "same as -b",
                        .flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH,
                },
@@ -185,6 +186,7 @@ int cmd__parse_options(int argc, const char **argv)
                        .type = OPTION_COUNTUP,
                        .long_name = "ambiguous",
                        .value = &ambiguous,
+                       .precision = sizeof(ambiguous),
                        .help = "positive ambiguity",
                        .flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG,
                },
@@ -192,6 +194,7 @@ int cmd__parse_options(int argc, const char **argv)
                        .type = OPTION_COUNTUP,
                        .long_name = "no-ambiguous",
                        .value = &ambiguous,
+                       .precision = sizeof(ambiguous),
                        .help = "negative ambiguity",
                        .flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG,
                },