From: René Scharfe Date: Wed, 9 Jul 2025 09:46:28 +0000 (+0200) Subject: parse-options: add precision handling for OPTION_COUNTUP X-Git-Tag: v2.51.0-rc0~59^2 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=c1e616c39b31e78acc595790bf3a9553a022a19d;p=thirdparty%2Fgit.git parse-options: add precision handling for OPTION_COUNTUP 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 Signed-off-by: Junio C Hamano --- diff --git a/parse-options.c b/parse-options.c index a813511b1b..5224203ffe 100644 --- a/parse-options.c +++ b/parse-options.c @@ -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)) diff --git a/parse-options.h b/parse-options.h index 8bdf469ae9..312045604d 100644 --- a/parse-options.h +++ b/parse-options.h @@ -183,6 +183,7 @@ struct option { .short_name = (s), \ .long_name = (l), \ .value = (v), \ + .precision = sizeof(*v), \ .help = (h), \ .flags = PARSE_OPT_NOARG|(f), \ } diff --git a/t/helper/test-parse-options.c b/t/helper/test-parse-options.c index 2ba2546d70..68579d83f3 100644 --- a/t/helper/test-parse-options.c +++ b/t/helper/test-parse-options.c @@ -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, },