[Bug c/87392] UBSAN behavior on left-shifting 1 into the sign bit is dependent on C standard

roscaeugeniu at gmail dot com gcc-bugzilla@gcc.gnu.org
Wed Sep 26 23:46:00 GMT 2018


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87392

--- Comment #8 from Eugeniu Rosca <roscaeugeniu at gmail dot com> ---
On 2018-09-25 at 08:53:34 UTC, Jonathan Wakely wrote in comment #6:

> He already did. Comment 1 quotes the GCC manual which references
> the relevant sections of the standards.

Comment 1 does indeed reference "(C90 6.3, C99 and C11 6.5)". But if you check
my first post again, you'll see that neither C89->"3.3.7 Bitwise shift
operators" [18] nor its C90 [19] counterpart C90->"6.3.7 Bitwise shift
operators" says a word about signed integers in the definition of the '<<'
operator. This is in contrast with later C standards which supplement the
definition of "E1 << E2" by "If E1 has a signed type ...". It is simply not
possible to conclude from C89->3.3.7 or from C90->6.3.7 that "left-shifting of
signed integer into the sign bit" is implementation-defined behavior. The
C89/C90 sections conveying this message are:
 - C89: "A.6.3 Implementation-defined behavior" -> "A.6.3.4 Integers"
 - C90: "G.3 Implementation-defined behavior" -> "G.3.5 Integers"

The latter is referenced by you in Comment 6, but not in Comment 1.

> > - Since U-Boot is compiled using '-std=gnu11' and since UBSAN reports
> > (1 << 31) as undefined behavior and since C11 standard says that
> > encountering an UB the compiler may "ignore the situation completely
> > with unpredictable results",

> It may do that, or it may do other things (like print a UBsan error).

I wish there was an "and" relationship between the two, i.e. the error to be
dependent on the UB, with no false positives.

> > what are there real-life issues expected from shifting signed
> > integers into (*not past*) the sign bit? What to expect in the worst case?

> I think with GCC the worst that will happen is you get a UBsan error (which
> might make the program abort, depending on the options used to compile it).

In U-Boot/Linux kernel execution goes on, so the latter is not of concern.
I am quite surprised that, in spite of no harm expected from shifting a signed
integer into the sign bit, GCC (std=c99, std=c11) still decides to fire a
warning. It seems like the idea behind UBSAN is to inform the user about what C
standard says on paper rather than how it is implemented. This is quite
unfortunate.

> You've already been given the link to the GCC documentation which says
> that GCC doesn't treat it as undefined in C99 and C11, even though the
> standards (and UBsan) say it's undefined.

Ok, let's come back to it. Here is what you refer to:

-----8<-----
As an extension to the C language, GCC does not use the latitude given in C99
and C11 only to treat certain aspects of signed ‘<<’ as undefined. However,
-fsanitize=shift (and -fsanitize=undefined) will diagnose such cases.
-----8<-----

I am not sure if you or anybody else cares, but this sounds pretty similar to
"Some children study too hard to succeed" [20]. I can understand the above
excerpt in two ways:

1. As an extension to the C language, GCC does not use the latitude given in
C99 and C11 in order to treat only certain aspects of signed ‘<<’ as undefined.
[..]

2. As an extension to the C language, GCC does not use the latitude given in
C99 and C11 of only treating certain aspects of signed ‘<<’ as undefined. [..]

Regardless of the variant I pick, without GCC community support I'm still
clueless about:
- what kind of latitude is provided by C99/C11 standards.
- which gcc aspects of signed ‘<<’ diverge from the C99/C11 standards and which
 do not.

> There is no bug here. It's correct for UBsan to depend on the C standard chosen,
> because what is and isn't undefined depends on the standard.

As expressed above, my expectation was that UBSAN reflects how compiler
implements the standard rather than what standard itself says. I am still
surprised that this expectation is broken, but I will just accept it and keep
going. It's also unfortunate that, as a user, I can't disable the UBSAN warning
of shifting into (not past) the sign bit. Enabling either
-fsanitize=shift-exponent or -fsanitize=shift-base alone would disable other
precious UBSAN warnings as a side effect, which is not acceptable.

All in all, the summary which I take from this discussion is "don't be
concerned about left shifting into the sign bit, even if UBSAN annoys you with
a warning".

If there is no way GCC folks can support communities like U-Boot/coreboot to at
least individually turn off benign UBSAN warnings, I have no choice but to
finally agree with the status of this bug report.

Thanks and regards,
Eugeniu.

[18] http://port70.net/~nsz/c/c89/c89-draft.html
[19]
http://read.pudn.com/downloads133/doc/565041/ANSI_ISO%2B9899-1990%2B[1].pdf
[20]
https://guinlist.wordpress.com/2016/02/08/124-structures-with-a-double-meaning/


More information about the Gcc-bugs mailing list