Skip to content
Snippets Groups Projects

Pass -fwrapv to GCC compilation flags

Merged Hanicef requested to merge Hanicef/SRB2Classic:use-fwrapv-gcc-flag into next
2 unresolved threads

in case you weren't aware, integer overflows and underflows are undefined behavior in C, and that of course means that anything goes with them. that said, though, GCC has been (ab)using this for optimization reasons, which is something that has lead to countless security holes and in the past, and also the well-known (or, at least if you work with this stuff a lot) article "GCC undefined behaviors are getting wild".

the problem, however, is that we rely on integer overflows and underflows a ton. in fact, angle_t actively exploits integer overflows to be able to perform rotations beyond 360 degrees. this puts us in a dangerous spot since it's very possible that GCC can start "optimizing" away important checks which can cause runtime bugs that only happens in release builds -- hell, this might've already happened without any of us being aware of it!

fortunately, there is a switch that fixes this: -fwrapv. it tells GCC to assume that numbers are in two's complement, and optimizes accordingly. this disables some performance optimizations and enables others, but at it's core, it fixes the integer overflow problems and stops any optimization bugs of this category from appearing.

Merge request reports

Loading
Loading

Activity

Filter activity
  • Approvals
  • Assignees & reviewers
  • Comments (from bots)
  • Comments (from users)
  • Commits & branches
  • Edits
  • Labels
  • Lock status
  • Mentions
  • Merge request status
  • Tracking
  • Hanicef added 1 commit

    added 1 commit

    • 6d650728 - Update CMake and XCode build systems

    Compare with previous version

  • Hanicef resolved all threads

    resolved all threads

  • 160 160 endif
    161 161 endif
    162 162
    163 ifdef GCC34
  • Hanicef added 1 commit

    added 1 commit

    • 80475ada - Always apply -fwrapv on builds

    Compare with previous version

  • Alam Ed Arias approved this merge request

    approved this merge request

  • in case you weren't aware, integer overflows and underflows are undefined behavior in C

    It is probably important to mention that the statement 'integer overflows and underflows are undefined behavior in C' is referring to signed integers and not unsigned integers. Looking at the C99 standard:

    A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type."

    https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf#page=46

    in fact, angle_t actively exploits integer overflows to be able to perform rotations beyond 360 degrees

    angle_t is typedefed to UINT32: https://git.do.srb2.org/STJr/SRB2/-/blob/1470d099e338aff3aad25178894e15bb6d1e8232/src/tables.h#L69 (and UINT32 is defined as uint32_t, which is unsigned)

    The GCC docs as well describe -fwrapv as This option instructs the compiler to assume that signed arithmetic overflow of addition, subtraction and multiplication wraps around using twos-complement representation...: https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html

    This is just for the sake of clarification and not a comment on the changes themselves. For debugging, there is another flag called -ftrapv which tells gcc to trigger exceptions on integer overflows, ofc there is also UBSAN on glibc (You can use CFLAGS="-fsanitize=address,undefined" LDFLAGS="-fsanitize=address,undefined" make -C src).

    Testing it myself with UBSAN I did see signed integer overflows in r_fps.c, p_enemy.c, blua/lvm.c, p_floor.c, p_maputl.c, p_user.c, p_spec.c, st_stuff.c, f_finale.c, etc. with some involving fixed_t, which is signed. Ofc those are best for a separate issue. I also noticed a lot of shift of negative integer errors, which are also UB, when calling these functions: https://git.do.srb2.org/STJr/SRB2/-/blob/1470d099e338aff3aad25178894e15bb6d1e8232/src/v_video.h#L158-170.

    If I missed something, feel free to correct me.

    Correction: twos-complement integers will become mandatory in C23 but integer overflows will still be undefined behavior and C23 adds extra functions for checking if an overflow has occurred.

    Edited by oreo639
  • Logan Aerl Arias mentioned in commit 2cf26236

    mentioned in commit 2cf26236

  • added Ecosystem label

  • Please register or sign in to reply
    Loading