Safe compilerSvace static analyzer
The safe compiler avoids introducing new vulnerabilities in program’s binary code w.r.t. its source code when aggressively optimizing (e.g., when making use of source code constructs exhibiting undefined behavior). The compiler tries to restrict optimizations as little as possible, which allows avoiding the large performance drop compared to the solution with all optimizations turned off.
Features and advantages
The safe compiler is based on the GCC compiler and can act as a drop-in replacement for GCC (for example, when building the complete Linux distribution). The compiler retains the generated code quality and produces the ready-to-use safe build of a program.
The safe compiler provides:
- Refined compiler optimizations for conservative treatment of source code places with undefined behavior so that for these places program semantics gets defined safely and naturally.
- Forced initialization for uninitialized automatic variables.
- Issuing warnings when detecting undefined behavior.
- Adding dynamic checks for certain constructs to prevent exhibiting undefined behavior during program execution.
- Diversifying code generation during either compilation or program execution.
- No need to modify either source code or build system configuration, which makes using the compiler as simple as possible.
- Three different safety levels that provide trade-offs between generated code safety and performance. The lowest level is the third; the highest is the first one.
The safe compiler performs the following actions:
On the third level:
- Avoiding integer overflow, accessing objects via pointers of incompatible types, dereferencing null pointers, using compiler builtins instead of standard library implementations for input/output functions and for functions working with memory.
- Detecting division by zero, incorrect bitwise shifts, accesses beyond stack frames, array loads/stores outside of the memory allocated for the array. Detecting automatic variables that are stored in registers during function calls.
On the second level:
- Analyzing arguments of bitwise shifts, redundant memory operations, data alignment when working with vector instructions, address arithmetic when optimizing memory accesses and changing their order.
- Initializing all automatic variables (with zero) that are not initialized explicitly by the user.
- Treating certain compiler warnings as errors and stopping compilation when they are issued.
On the first level:
- Generating unique memory layout for function code either statically during compilation or when performing dynamic linking.
- Adding machine code that aborts the program when detecting undefined behavior during program execution (sanitization) in the following situations:
1) Integer and floating point operations:
- loading a non-boolean value in a boolean variable;
- floating point conversion that results in either integer or floating point overflow;
- performing a bitwise shift with a negative shift value or with a shift value that is equal or greater than the shifted type width;
- signed integer operation with the result that is non representable in the output type;
- integer division or module with the divisor equal to zero.
2) Pointer and array operations:
- loads/stores via incorrectly aligned or null pointer;
- array loads/stores using the address outside of the memory allocated for the array;
- passing null pointer as a function parameter marked with the nonnull attribute;
- address arithmetic resulting in integer overflow;
- returning null value out of function that is marked with the returns_nonnull attribute;
- allocating an automatic VLA array with incorrect size (zero or negative).
3) Function operations:
- a function pointer call via a pointer whose type does not match the function prototype;
- returning from a non-void function without actually executing the return statement;
- calling a compiler builtin with incorrect arguments;
- reaching a program point during program execution that is marked in the source code as unreachable.
Who is the safe compiler target audience?
- Operating system developers.
- Companies developing high-level safe and secure software.
Safe compiler deployment stories
The safe compiler is deployed in a number of Russian companies and government institutions as an add-on to the ISP Crusher framework.
Linux-based OS (for x86 32/64 and ARMv7; Windows (MinGW).