-
Notifications
You must be signed in to change notification settings - Fork 172
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Undefined behavior due to shifts on signed integers #84
Comments
Maybe something like this: https://github.com/erikd/libsndfile/blob/master/src/common.h#L1090-L1112 |
The left shift will run into UB if the range of an int is reached. Interestingly this UB makes it produce the expected The right shift is... interesting. It relies on 2s-complement or at least that the highest bit is 1 for negative numbers. I haven't found a clear definition what happens for negation of negative numbers as it isn't defined that 2s-complement is used. In C++20 left and right shifts are fully defined though: https://en.cppreference.com/w/cpp/language/operator_arithmetic I don't have a solution. Just suggestion: In the linked functions make the shift value unsigned. A negative shift is UB. And maybe add an assertion on |
Why would you add an assertion? Aren't all the shifts constant values? Casting from signed to unsigned, performing the shift and casting back should keep the C compiler happy. Doing this in an inline function (if the shifts are constant, they can be embedded in the actual function) seems like the solution. |
The assertion should be on the |
I tired using the undefined behavior sanitizer on x86_64 and found no issues related to shifts at all. Eg
|
UBSAN not erroring out is not a guarantee that there is no UB. The code uses e.g.
Above I linked 1 compiler (I admit a rather special one) that does not use SAR but SHR which will lead to wrong results. |
In this case it actually is, but whatever. The potential for undefined behavior at that that has still not been demonstrated to be the cause of the problem seen on PowerPC. The obvious way to determine whether this undefined behavior is the cause the PowerPC issue is to replace |
I double checked and you are right: No shift is UB as the only problematic shift is in However it does run into implementation defined behavior due to the right shift of a signed long in The cause for the PowerPC problem is not the shift but a buggy |
I 100% believe that PowerPC (or more likley the compiler) has a problem but you have yet to provide any real evidence that UB is happening here. You need to provide that evidence. |
As written there is no UB, but only implementation defined behaviour which is in
Solution: Use code like this:
|
I will ask yet again, where is the evidence that this is UB? Did you even try my suggestion of:
|
I don't understand the question. With the steps described above a right shift of a negative signed integer is performed. Do you agree with that? What else do you need?
No, why? I don't even have a buggy PowerPC platform and the shift is unrelated to the bug reported in #65. The current implementation works because a right shift of a signed int is "usually" defined (by the compiler in use!) to be an arithmetic shift, but a compiler on another platform may not do that (which is the meaning of "implementation defined"), see also https://stackoverflow.com/a/7636/1930508 or Wikipedia:
|
I am very hesitant to change code without evidence that the change actually fixes something. |
Sure: My proposed code does not rely on implementation defined behavior (fixes this issue) and additionally does not run into the bug @janstary has with his machines
|
With that change (to the current git), the test fails with
|
That is expected:
So: |
As found in #65 (comment) using bit shifts on signed integers is undefined behavior. Reason for that is the difference between a "regular shift" (shr) and "arithmetic shift" (sar) where the former just shifts bits while the latter preserves the sign bit in all cases. Also there is a rounding difference for positive and negative numbers.
Examples:
This may not be a problem in practice as usually
int >> value
is translated tosar
but I found 1 compiler where it is translated toshr
: https://godbolt.org/z/sj_uO6Not sure if/how to solve this as
i >> value
is meant asfloor(i/2^value)
while(int)(i/2^value)
istrunc(i/2^value)
and hence cannot be "optimized" to a shift.The text was updated successfully, but these errors were encountered: