diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2018-01-16 15:44:34 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2018-01-16 15:26:23 +0000 |
commit | 6165f644c98238036fd7353f2b1de6f07376c30a (patch) | |
tree | f3d23925c9b16cfe7bca800f78e41558f8916e12 | |
parent | d9483eb79086970df1dd875f6914bd0a442e8566 (diff) |
Avoid undefined behavior in argp-parse.cQtCreator4.6.2QtCreator4.6.0-rc1QtCreator4.6.0-beta1QtCreator4.6.04.6
The shifting-instead-of-masking trick outlined there is very clever, but
only works incidentally. Explicitly preserve the sign, and still shift,
but shift unsigned values for which left-shifting bits out is defined.
make distcheck complains about the previous code with sufficiently
recent compilers with UB sanitizers.
Change-Id: I6f2942f307a2c154ea7d414a85c60e4f088fc918
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
-rw-r--r-- | libgnu/argp-parse.c | 15 |
1 files changed, 9 insertions, 6 deletions
diff --git a/libgnu/argp-parse.c b/libgnu/argp-parse.c index 3f723bc8..dc3106e7 100644 --- a/libgnu/argp-parse.c +++ b/libgnu/argp-parse.c @@ -740,12 +740,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); + { + uint maskable = (uint)(opt < 0 ? -opt : opt); + maskable = (maskable << GROUP_BITS) >> GROUP_BITS; + int masked = opt < 0 ? -(int)maskable : (int)maskable; + + err = + group_parse (&parser->groups[group_key - 1], &parser->state, + masked, parser->opt_data.optarg); + } if (err == EBADKEY) /* At least currently, an option not recognized is an error in the |