[PATCH 10/11] argp: Fix shift bug
Florian Weimer
fw@deneb.enyo.de
Wed May 7 19:42:58 GMT 2025
* Adhemerval Zanella:
>>From gnulib commits 06094e390b0 and 88033d3779362a.
> ---
> argp/argp-parse.c | 15 +++++++++------
> 1 file changed, 9 insertions(+), 6 deletions(-)
>
> 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);
Would this be clearer?
(int) ((unsigned int) opt << GROUP_BITS) >> GROUP_BITS,
Or does ubsan flag that as well? Conversion to negative int is a GCC
extension:
| For conversion to a type of width N, the value is reduced modulo 2^N
| to be within range of the type; no signal is raised.
<https://gcc.gnu.org/onlinedocs/gcc-15.1.0/gcc/Integers-implementation.html>
More information about the Libc-alpha
mailing list