-
Notifications
You must be signed in to change notification settings - Fork 144
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
Avoid overflows in left shifts #545
Conversation
Left-shifting uint8_t types kinda works because of integer promotion rules. However, this is incorrect on platforms with 16-bit int types. We should explicitly use 32-bit unsigned integers to get the correct behavior on all platforms (and avoid warnings by undefined behavior sanitizer).
I don't understand why we should use 32 bit variables for 8bit results? we use explicitly defined 32 bit variable which stores 32 bits and then we place each byte to separate 1 byte variable. where is here undefined behavior? Anyway, we need here 32 bits to store crc32. And we don't tell that we support 16-bits platforms, so it's not our problem that old platform can't work with *32_t types. |
@Lagovas, the issue is with this expression: result = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3); Regardless of the This means that if byteN are uint8_t and unsigned int is 16-bit then the compiler is free to interpret the shifts as unsigned left shifts of 16-bit values, making Obviously, * It’s not like that. After reading through Intel’s manual it seems that if the shifts are** interpreted as 16-bit on x86 then the byte values will be really lost and the carry flag will contain some undefined value. ARM is the same if it has 16-bit registers. ** gcc and clang do not generate 16-bit code anymore, so again we’re ‘safe’. Switching the types to uint32_t is the cleanest way to avoid this issue. Keeping the variables uint8_t and inserting explicit casts into that expression will work too, but that’s less readable and produces the same machine code. |
but our left operand has enough size to store result value. |
The type of the |
we don't support 16-bit platforms, we haven't tried even testing on 'em |
Left-shifting uint8_t types kinda works because of integer promotion rules. However, this is incorrect on platforms with 16-bit int types. We should explicitly use 32-bit unsigned integers to get the correct behavior on all platforms (and avoid warnings by undefined behavior sanitizer).