Skip to content
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

Improve -fno-strict-overflow description #694

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

thomasnyman
Copy link
Contributor

@thomasnyman thomasnyman commented Nov 14, 2024

Improve -fno-strict-overflow description and document changes in GCC 8.5.

Add -ftrapv and -fsanitize=signed-integer-overflow as alternative options.
Add missing "When not to use?", "Performance implications", and "Other considerations subsections"

Fixes #685

@thomasnyman thomasnyman force-pushed the fno-strict-overflow-improvement branch 2 times, most recently from 253f354 to 79d4dd9 Compare December 12, 2024 12:46

#### Synopsis

In C and C++ unsigned integers have long been defined as "wrapping around". However, for many years C and C++ have assumed that overflows do not occur in many other circumstances. Overflow when doing arithmetic with signed numbers is considered undefined by many versions of the official specifications, This approach also allows the compiler to assume strict pointer semantics: if adding an offset to a pointer does not produce a pointer to the same object. In practice, this means that important security checks written in the source code may be silently ignored when generating executable code.
In C and C++ unsigned integers have long been defined as "wrapping around". However, C and C++ compilers, by default, assume that overflows do not occur in other circumstances. Overflow when doing arithmetic with signed numbers is considered undefined the language specifications. This allows the compiler to assume strict pointer semantics: if adding an offset to a pointer does not produce a pointer to the same object, the addition is undefined. In practice, this means that important security checks written in the source code may be silently ignored when generating executable code.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"undefined the language" -> "undefined in the language"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in e667c2f.

@@ -937,15 +937,18 @@ There are normally no significant performance implications. Null pointer checks

---

### Integer overflow may occur
### Define behavior for signed integer and pointer arithmetic overflows
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of these don't define behavior, they complain about it, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The options we cover here make signed-integers-arithmetic and pointer-arithmetic overflows either wrap-around or trap so I think it's justifiable to characterize that as defined behavior (as opposed to the default undefined behavior which allows for the optimizations that may case problems). We don't cover warnings here, so I'd be inclined to leave "defined" as it is.


#### When not to use?

Standards-compliant C and C++ should not require any particular behavior for signed arithmetic overflows. Code which requires a specific behavior, such as a two's-complement representation becomes less portable in a very subtle way. Consequently, strictly standard-compliant C and C++ should not need the flags described in this section, and we recommend striving to write code that does not assume specific arithmetic overflow behavior. However, mistakes are inevitable and consequently we believe most code will benefit from `-fno-strict-overflow` or its alternatives.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure? Let's check. Newer standards may require twos-complement.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed you are right. In addition to C++20 which Gabriel pointed us to also C23 now requires two's complement representation for signed integers. Fixed in 203728f.


#### Performance implications

Each of these options gives the compiler less freedom for optimizing the resulting machine code compared to the default `-fstrict-overflow` behavior. For example, under `-fstrict-overflow` semantics, expressions such as `i + 10 > i` will always be true for signed `i`, allowing the expression to be replaced at compile time with a constant value. As discussed above, if such expressions occur in condition checks the compiler may optimize away entire code paths when the expression can be evaluated at compile time. In contrast, under `-fno-strict-overflow` those expression must be evaluated at run-time in case of overflows that wrap around the value, thus preventing some optimizations. On the other hand, treating overflows as undefined behavior will only yield optimal behavior if the programmer can be certain the program will never inputs that cause overflows.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"will never inputs" -> "will never accept inputs"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 203728f.

Add -ftrapv and -fsanitize=signed-integer-overflow as alternative option

Signed-off-by: Thomas Nyman <[email protected]>
@thomasnyman thomasnyman force-pushed the fno-strict-overflow-improvement branch from fc2d0ff to 203728f Compare January 9, 2025 12:55
@thomasnyman thomasnyman self-assigned this Jan 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Consider -ftrapv for C and C++ Compiler Hardening Guide
2 participants