From: Adhemerval Zanella Date: Wed, 7 May 2025 14:17:28 +0000 (-0300) Subject: argp: Fix shift bug X-Git-Tag: glibc-2.42~177 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1642570563434ff0f15b36edc0b92ab3c7c934ee;p=thirdparty%2Fglibc.git argp: Fix shift bug From gnulib commits 06094e390b0 and 88033d3779362a. Reviewed-by: Florian Weimer --- diff --git a/argp/argp-parse.c b/argp/argp-parse.c index 82c7b784de..99f8d9ecd4 100644 --- a/argp/argp-parse.c +++ b/argp/argp-parse.c @@ -735,12 +735,15 @@ parser_parse_opt (struct parser *parser, int opt, char *val) } } else - /* A long option. We use shifts instead of masking for extracting - the user value in order to preserve the sign. */ - err = - group_parse (&parser->groups[group_key - 1], &parser->state, - (opt << GROUP_BITS) >> GROUP_BITS, - parser->opt_data.optarg); + /* A long option. Preserve the sign in the user key, without + invoking undefined behavior. Assume two's complement. */ + { + int user_key = + ((opt & (1 << (USER_BITS - 1))) ? ~USER_MASK : 0) | (opt & USER_MASK); + err = + group_parse (&parser->groups[group_key - 1], &parser->state, + user_key, parser->opt_data.optarg); + } if (err == EBADKEY) /* At least currently, an option not recognized is an error in the