Skip to content

Commit

Permalink
Improve -fno-strict-overflow description
Browse files Browse the repository at this point in the history
Add -ftrapv and -fsanitize=signed-integer-overflow as alternative option

Signed-off-by: Thomas Nyman <[email protected]>
  • Loading branch information
thomasnyman committed Dec 12, 2024
1 parent 4b9c0c3 commit 79d4dd9
Showing 1 changed file with 11 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ Table 2: Recommended compiler options that enable run-time protection mechanisms
| [`-fPIE -pie`](#-fPIE_-pie) | Binutils 2.16.0<br/>Clang 5.0.0 | Build as position-independent executable. Can impact performance on 32-bit architectures. |
| [`-fPIC -shared`](#-fPIC_-shared) | < Binutils 2.6.0<br/>Clang 5.0.0 | Build as position-independent code. Can impact performance on 32-bit architectures. |
| [`-fno-delete-null-pointer-checks`](#-fno-delete-null-pointer-checks) | GCC 3.0.0<br/>Clang 7.0.0 | Force retention of null pointer checks |
| [`-fno-strict-overflow`](#-fno-strict-overflow) | GCC 4.2.0 | Integer overflow may occur |
| [`-fno-strict-overflow`](#-fno-strict-overflow) | GCC 4.2.0 | Define behavior for signed integer and pointer arithmetic overflows |
| [`-fno-strict-aliasing`](#-fno-strict-aliasing) | GCC 2.95.3<br/>Clang 2.9.0 | Do not assume strict aliasing |
| [`-ftrivial-auto-var-init`](#-ftrivial-auto-var-init) | GCC 12.0.0<br/>Clang 8.0.0 | Perform trivial auto variable initialization |
| [`-fexceptions`](#-fexceptions) | GCC 2.95.3<br/>Clang 2.6.0 | Enable exception propagation to harden multi-threaded C code |
Expand Down Expand Up @@ -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
| Compiler Flag | Supported since | Description |
|:------------------------------------------------------------- |:---------------:|:----------------------------------------------------------------- |
| <span id="-fno-strict-overflow">`-fno-strict-overflow`</span> | GCC 4.2.0 | Integer overflow may occur |
| Compiler Flag | Supported since | Description |
|:------------------------------------------------------------- |:---------------:|:---------------------------------------------------------------------------------------------------------------------------------------------- |
| <span id="-fno-strict-overflow">`-fno-strict-overflow`</span> | GCC 8.5.0 | Signed integer overflows on addition, subtraction, multiplication, and pointer arithmetic wraps around using two's-completment representation |
| <span id="-fwrapv">`-fwrapv`</span> | GCC 3.4.0 | Signed integer overflows on addition, subtraction, and multiplication wraps around using twos-completment representation |
| <span id="-fwrapv-pointer">`-fwrapv-pointer`</span> | GCC 8.5.0 | Pointer arithmetic and multiplication wraps around using two's-complement representation |
| <span id="-ftrapv">`-ftrapv`</span> | GCC 3.3.0 | Signed integer overflows on addition, subtraction and multiplication trap with `SIGABRT` |
#### 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.
For example, here is some code from `fs/open.c` of the Linux kernel [^Wang2012]:
Expand All @@ -967,9 +970,9 @@ A developer *might* expect that the computation `offset + len` would produce a u

The Linux kernel enables `-no-strict-overflow` to reduce the likelihood that important security checks in the source code will be silently ignored by the compiler.

An alternative option is to use the `-fwrapv` option. With `-fwrapv`, integer signed overflow wraps (and is thus defined).
Alternatives to `-no-strict-overflow` are the `-fwrapv` and `-ftrapv` options. With `-fwrapv`, integer signed overflow wraps (and is thus defined). With `-ftrapv`, signed integer overflows trap, e.g., on x86 an overflow causes a `SIGABRT` signal to the application.

Note that GCC and Clang interpret this option slightly differently. On clang, this option is considered a synonym for `-fwrapv`. On GCC, this option does not fully enforce two's complement on signed integers, allowing for additional optimizations. [^Wang2012]
Since GCC 8.5 `-no-strict-overflow` is equivalent to `-fwrapv -fwrapv-pointer` while GCC documentation recommends `-fsanitize=signed-integer-overflow` for diagnosing signed integer overflow issues during testing and debugging. In prior GCC versions `-no-strict-overflow` does not fully enforce two's complement on signed integers, allowing for additional optimizations[^Wang2012]. In Clang, `-no-strict-overflow` option is considered a synonym for `-fwrapv`.

---

Expand Down

0 comments on commit 79d4dd9

Please sign in to comment.