This guide is intended to help you determine which flags you should use to compile your C Code using GCC, Clang or MSVC, in order to:
Disclaimer:
The flags selected and recommended here were chosen to maximize the number of
classes of detected errors which could have a security benefit when enabled.
Code generation options (such as -fstack-protector-strong
) can also have
performance impacts. It is up to you to assess the impact on your code base
and choose the right set of command line options.
Comments are of course welcome.
Always use the following warnings and flags on the command line:
-O2
-Werror
-Wall -Wextra -Wpedantic -Wformat=2 -Wformat-overflow=2 -Wformat-truncation=2 -Wformat-security -Wnull-dereference -Wstack-protector -Wtrampolines -Walloca -Wvla -Warray-bounds=2 -Wimplicit-fallthrough=3 -Wtraditional-conversion -Wshift-overflow=2 -Wcast-qual -Wstringop-overflow=4 -Wconversion -Warith-conversion -Wlogical-op -Wduplicated-cond -Wduplicated-branches -Wformat-signedness -Wshadow -Wstrict-overflow=4 -Wundef -Wstrict-prototypes -Wswitch-default -Wswitch-enum -Wstack-usage=1000000 -Wcast-align=strict
-D_FORTIFY_SOURCE=3
-fstack-protector-strong -fstack-clash-protection -fPIE
-fsanitize=bounds -fsanitize-undefined-trap-on-error
-Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -Wl,-z,separate-code
On legacy code bases, some of the warnings may produce some false positives. On code where the behavior is intended, pragmas can be used to disable the specific warning locally.
Run debug/test builds with sanitizers (in addition to the flags above): AddressSanitizer + UndefinedBehaviorSanitizer:
-fsanitize=address -fsanitize=pointer-compare -fsanitize=pointer-subtract -fsanitize=leak -fno-omit-frame-pointer -fsanitize=undefined -fsanitize=bounds-strict -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow
export ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1:detect_invalid_pointer_pairs=2
If your program is multi-threaded, run with -fsanitize=thread
(incompatible with ASan).
Finally, use -fanalyzer
to spot potential issues.
First compile with:
-O2
-Werror
-Walloca -Wcast-qual -Wconversion -Wformat=2 -Wformat-security -Wnull-dereference -Wstack-protector -Wvla -Warray-bounds -Warray-bounds-pointer-arithmetic -Wassign-enum -Wbad-function-cast -Wconditional-uninitialized -Wconversion -Wfloat-equal -Wformat-type-confusion -Widiomatic-parentheses -Wimplicit-fallthrough -Wloop-analysis -Wpointer-arith -Wshift-sign-overflow -Wshorten-64-to-32 -Wswitch-enum -Wtautological-constant-in-range-compare -Wunreachable-code-aggressive -Wthread-safety -Wthread-safety-beta -Wcomma
-D_FORTIFY_SOURCE=3
-fstack-protector-strong -fsanitize=safe-stack -fPIE -fstack-clash-protection
-fsanitize=bounds -fsanitize-undefined-trap-on-error
-Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -Wl,-z,separate-code
On legacy code bases, some of the warnings may produce some false positives. On code where the behavior is intended, pragmas can be used to disable the specific warning locally.
Run debug/test builds with sanitizers, in addition to the flags above (and after removing -fsanitize=safe-stack
, which is incompatible with LeakSanitizer):
AddressSanitizer + UndefinedBehaviorSanitizer:
-fsanitize=address -fsanitize=leak -fno-omit-frame-pointer -fsanitize=undefined -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fsanitize=integer
export ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1:detect_invalid_pointer_pairs=2
If your program is multi-threaded, run with -fsanitize=thread
(incompatible with ASan).
Finally, use scan-build
to spot potential issues.
In addition, you can build production code with -fsanitize=integer -fsanitize-minimal-runtime -fno-sanitize-recover
to catch integer overflows.
/Wall /sdl /guard:cf /guard:ehcont /CETCOMPAT
/fsanitize=address
/analyze
Written by Raphaël Rigo and reviewed by Sarah Zennou @ Airbus Security lab, 2021.
Please open an issue if you notice any error, imprecision or have comments or improvements ideas.
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.