bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: results of gnulib tests with -fcheck-pointer-bounds


From: Bruno Haible
Subject: Re: results of gnulib tests with -fcheck-pointer-bounds
Date: Sat, 20 May 2017 15:06:39 +0200
User-agent: KMail/5.1.3 (Linux/4.4.0-75-generic; KDE/5.18.0; x86_64; ; )

Hi Paul,

> > The message "Saw a #BR!" is a bit cryptic
> > Does someone understand this argp-help.c code?
> 
> I didn't, but after looking at the code for a bit I see a problem that 
> could explain the symptoms you observe. hol_append subtracts pointers 
> into different arrays, which has undefined behavior in C, and 
> -fcheck-pointer-bounds can catch this after the resulting offset is used 
> to calculate a pointer and the pointer is then later used. This is 
> clearly a portability bug so I installed the first attached patch. Does 
> it fix the problem on your platform?

Yes, it fixes the problem. Great! Thanks.

> I also tested argp under -fsanitize=undefined and found a different bug,
> fixed in the 2nd attached patch.

Sorry, I don't understand this patch: it avoids the undefined behaviour
on left-shift, but still makes assumptions about the "implementation-
defined" behaviour of right-shift [1], here:
        user_key = shifted_user_key >> GROUP_BITS;
[1] 
http://stackoverflow.com/questions/7622/are-the-shift-operators-arithmetic-or-logical-in-c

How about this? The intended operation (in terms of bits) is:

      z.......abcdefghijklmnopqrstuvwx
->    zzzzzzzzabcdefghijklmnopqrstuvwx

AFAIK, bit operations (&, |, ~) don't have undefined or implementation-defined
behaviour on signed integer types. Once we assume two's complement - which your
comment already states - they are unambiguous. Proposed patch:


2017-05-20  Bruno Haible  <address@hidden>

        argp: Simplify bit manipulation.
        * lib/argp-parse.c (parser_parse_opt): Use &, |, ~ instead of shifts
        on a signed integer type.

diff --git a/lib/argp-parse.c b/lib/argp-parse.c
index 4723a2b..fb04a4a 100644
--- a/lib/argp-parse.c
+++ b/lib/argp-parse.c
@@ -743,15 +743,8 @@ parser_parse_opt (struct parser *parser, int opt, char 
*val)
     /* A long option.  Preserve the sign in the user key, without
        invoking undefined behavior.  Assume two's complement.  */
     {
-      unsigned uopt = opt;
-      unsigned ushifted_user_key = uopt << GROUP_BITS;
-      int shifted_user_key = ushifted_user_key;
-      int user_key;
-      if (-1 >> 1 == -1)
-        user_key = shifted_user_key >> GROUP_BITS;
-      else
-        user_key = ((ushifted_user_key >> GROUP_BITS)
-                    - (shifted_user_key < 0 ? 1 << USER_BITS : 0));
+      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);






reply via email to

[Prev in Thread] Current Thread [Next in Thread]