Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ When compiling C or C++ code on compilers such as GCC and clang, turn on these f

| When | Additional options flags |
|:------------------------------------------------------- |:---------------------------------------------------------------------------------------------------------|
| using GCC | `-Wtrampolines` |
| using GCC | `-Wtrampolines -fzero-init-padding-bits=all` |
| using GCC and only left-to-right writing in source code | `-Wbidi-chars=any` |
| for executables | `-fPIE -pie` |
| for shared libraries | `-fPIC -shared` |
Expand Down Expand Up @@ -117,6 +117,8 @@ How you apply this guide depends on your circumstances:

Applications should work towards compiling warning-free. This takes time, but warnings indicate a potential problem. Once done, any new warning indicates a potential problem.

We encourage developers to always use the approach guaranteed by standards to do something, as long as it's supported by their build processes. For example, in C23 or C++, assigning `{}` to a union guarantees the clearing of a whole union including padding bits (except for static storage duration initialization). Assigning `{0}` to a union does not guarantee clearing the whole union (e.g., in GCC 14 and below, this cleared a union, but in GCC 15[^gcc-release-notes-15] it does not). Using the standards' approach greatly reduces the risk that using a different compiler or a different compiler version will cause problems. That said, there may be no mechanism in the standards to ensure a particular property, sometimes compilers don't implement the standard way, and developers sometimes make mistakes. Thus, using option flags in addition to working within the standards where practical can be a powerful combination.

### What does compiler options hardening not do?

Compiler options hardening is not a silver bullet; it is not sufficient to rely solely on security features and functions to achieve secure software. Security is an emergent property of the entire system that relies on building and integrating all parts properly. However, if properly used, secure compiler options will complement existing processes, such as static and dynamic analysis, secure coding practices, negative test suites, profiling tools, and most importantly: security hygiene as a part of a solid design and architecture.
Expand Down Expand Up @@ -235,6 +237,7 @@ Table 2: Recommended compiler options that enable run-time protection mechanisms
| [`-fexceptions`](#-fexceptions) | GCC 2.95.3<br/>Clang 2.6.0 | Enable exception propagation to harden multi-threaded C code |
| [`-fhardened`](#-fhardened) | GCC 14.0.0 | Enable pre-determined set of hardening options in GCC |
| [`-Wl,--as-needed`](#-Wl,--as-needed)<br/>[`-Wl,--no-copy-dt-needed-entries`](#-Wl,--no-copy-dt-needed-entries) | Binutils 2.20.0 | Allow linker to omit libraries specified on the command line to link against if they are not used |
| [`-fzero-init-padding-bits=all`](#-fzero-init-padding-bits=all) | GCC 15.0.0 | Guarantee zero initialization of padding bits in all automatic variable initializers |

[^Guelton20]: The implementation of `-D_FORTIFY_SOURCE={1,2,3}` in the GNU libc (glibc) relies heavily on implementation details within GCC. Clang implements its own style of fortified function calls (originally introduced for Android’s bionic libc) but as of Clang / LLVM 14.0.6 incorrectly produces non-fortified calls to some glibc functions with `_FORTIFY_SOURCE` . Code set to be fortified with Clang will still compile, but may not always benefit from the fortified function variants in glibc. For more information see: Guelton, Serge, [Toward _FORTIFY_SOURCE parity between Clang and GCC. Red Hat Developer](https://developers.redhat.com/blog/2020/02/11/toward-_fortify_source-parity-between-clang-and-gcc), Red Hat Developer, 2020-02-11 and Poyarekar, Siddhesh, [D91677 Avoid simplification of library functions when callee has an implementation](https://reviews.llvm.org/D91677), LLVM Phabricator, 2020-11-17.

Expand Down Expand Up @@ -1154,6 +1157,25 @@ In rare cases applications may link to libraries solely for the purpose of runni

---

### Guarantee zero initialization of padding bits in automatic variable initializers

| Compiler Flag | Supported since | Description |
|:----------------------------------------------------------------------------------- |:---------------:|:---------------------------------------------------------------------------------------------- |
| <span id="-fzero-init-padding-bits=all">`-fzero-init-padding-bits=all`</span> | GCC 15.0.0 | Guarantee zero initialization of padding bits in all automatic variable initializers |
| <span id="-fzero-init-padding-bits=union">`-fzero-init-padding-bits=union`</span> | GCC 15.0.0 | Guarantee zero initialization of padding bits in unions on top of what the standards guarantee |

#### Synopsis

The `-fzero-init-padding-bits=all` option in GCC guarantees zero initialization of padding bits of structures and unions and reduces the risk that an incomplete initialization reveals sensitive information.

We recommend the use of `{}` initializers for unions as this is a standards-compliant way to zero-initialize a whole union, including its paddings bits, in the C23 and C++ standards. However, older code may use a different approach, some compilers may not support it, and developers sometimes make mistakes, so this option reduces the risk of such problems.

Since version 15, GCC adopted a stricter standards-compliant implementation of struct and union initializers.[^gcc-release-notes-15] Until GCC 14, `{0}` initializers would zero-initialize the whole union. With GCC 15 and later `{0}` initializer in C or C++ for unions no longer guarantees clearing of the whole union (except for static storage duration initialization). Only the first union member is initialized to zero. The `-fzero-init-padding-bits=unions` option in GCC 15 restores the old GCC behavior.

[^gcc-release-notes-15]: GCC team, [GCC 15 Release Series Changes, New Features, and Fixes](https://gcc.gnu.org/gcc-15/changes.html), 2025-05-30.

---

## Discouraged Compiler Options

This section describes discouraged compiler and linker option flags that may lead to potential defects with security implications in produced binaries.
Expand Down