parse-options: add precision handling for OPTION_BITOP

Similar to 09705696f7 (parse-options: introduce precision handling for `OPTION_INTEGER`, 2025-04-17) support value variables of different sizes for OPTION_BITOP. Do that by requiring their "precision" to be set, casting their "value" pointer accordingly and checking whether the value fits. Check if "devfal" fits into an integer variable with the given "precision", but don't check "extra", as its value is only used to clear bits, so cannot lead to an overflow. Not checking continues to allow e.g., using -1 to clear all bits even if the value variable has a narrower type than intptr_t. Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

René Scharfe committed Jul 9, 2025 at 11:46 UTC 1d918bf2a5eb9d860df1dd115ef2641d7b5870e9
2 files changed +8 -4
parse-options.c
+7 -4
@@ -167,11 +167,14 @@ static enum parse_opt_result do_get_value(struct parse_opt_ctx_t *p,
167 }
168
169 case OPTION_BITOP:
170 + {
171 + intmax_t value = get_int_value(opt, flags);
172 if (unset)
173 BUG("BITOP can't have unset form");
172 - *(int *)opt->value &= ~opt->extra;
173 - *(int *)opt->value |= opt->defval;
174 - return 0;
174 + value &= ~opt->extra;
175 + value |= opt->defval;
176 + return set_int_value(opt, flags, value);
177 + }
178
179 case OPTION_COUNTUP:
180 if (*(int *)opt->value < 0)
@@ -647,12 +650,12 @@ static void parse_options_check(const struct option *opts)
650 case OPTION_SET_INT:
651 case OPTION_BIT:
652 case OPTION_NEGBIT:
653 + case OPTION_BITOP:
654 if (!signed_int_fits(opts->defval, opts->precision))
655 optbug(opts, "has invalid defval");
656 /* fallthru */
657 case OPTION_COUNTUP:
658 case OPTION_NUMBER:
655 - case OPTION_BITOP:
659 if ((opts->flags & PARSE_OPT_OPTARG) ||
660 !(opts->flags & PARSE_OPT_NOARG))
661 optbug(opts, "should not accept an argument");
parse-options.h
+1
@@ -240,6 +240,7 @@ struct option {
240 .short_name = (s), \
241 .long_name = (l), \
242 .value = (v), \
243 + .precision = sizeof(*v), \
244 .help = (h), \
245 .flags = PARSE_OPT_NOARG|PARSE_OPT_NONEG, \
246 .defval = (set), \