llvm-project/clang/docs/UndefinedBehaviorSanitizer.rst

205 lines
7.6 KiB
ReStructuredText

==========================
UndefinedBehaviorSanitizer
==========================
.. contents::
:local:
Introduction
============
UndefinedBehaviorSanitizer (UBSan) is a fast undefined behavior detector.
UBSan modifies the program at compile-time to catch various kinds of undefined
behavior during program execution, for example:
* Using misaligned or null pointer
* Signed integer overflow
* Conversion to, from, or between floating-point types which would
overflow the destination
See the full list of available :ref:`checks <ubsan-checks>` below.
UBSan has an optional run-time library which provides better error reporting.
The checks have small runtime cost and no impact on address space layout or ABI.
How to build
============
Build LLVM/Clang with `CMake <http://llvm.org/docs/CMake.html>`_.
Usage
=====
Use ``clang++`` to compile and link your program with ``-fsanitize=undefined``
flag. Make sure to use ``clang++`` (not ``ld``) as a linker, so that your
executable is linked with proper UBSan runtime libraries. You can use ``clang``
instead of ``clang++`` if you're compiling/linking C code.
.. code-block:: console
% cat test.cc
int main(int argc, char **argv) {
int k = 0x7fffffff;
k += argc;
return 0;
}
% clang++ -fsanitize=undefined test.cc
% ./a.out
test.cc:3:5: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int'
You can enable only a subset of :ref:`checks <ubsan-checks>` offered by UBSan,
and define the desired behavior for each kind of check:
* print a verbose error report and continue execution (default);
* print a verbose error report and exit the program;
* execute a trap instruction (doesn't require UBSan run-time support).
For example if you compile/link your program as:
.. code-block:: console
% clang++ -fsanitize=signed-integer-overflow,null,alignment -fno-sanitize-recover=null -fsanitize-trap=alignment
the program will continue execution after signed integer overflows, exit after
the first invalid use of a null pointer, and trap after the first use of misaligned
pointer.
.. _ubsan-checks:
Availablle checks
=================
Available checks are:
- ``-fsanitize=alignment``: Use of a misaligned pointer or creation
of a misaligned reference.
- ``-fsanitize=bool``: Load of a ``bool`` value which is neither
``true`` nor ``false``.
- ``-fsanitize=bounds``: Out of bounds array indexing, in cases
where the array bound can be statically determined.
- ``-fsanitize=enum``: Load of a value of an enumerated type which
is not in the range of representable values for that enumerated
type.
- ``-fsanitize=float-cast-overflow``: Conversion to, from, or
between floating-point types which would overflow the
destination.
- ``-fsanitize=float-divide-by-zero``: Floating point division by
zero.
- ``-fsanitize=function``: Indirect call of a function through a
function pointer of the wrong type (Linux, C++ and x86/x86_64 only).
- ``-fsanitize=integer-divide-by-zero``: Integer division by zero.
- ``-fsanitize=nonnull-attribute``: Passing null pointer as a function
parameter which is declared to never be null.
- ``-fsanitize=null``: Use of a null pointer or creation of a null
reference.
- ``-fsanitize=object-size``: An attempt to use bytes which the
optimizer can determine are not part of the object being
accessed. The sizes of objects are determined using
``__builtin_object_size``, and consequently may be able to detect
more problems at higher optimization levels.
- ``-fsanitize=return``: In C++, reaching the end of a
value-returning function without returning a value.
- ``-fsanitize=returns-nonnull-attribute``: Returning null pointer
from a function which is declared to never return null.
- ``-fsanitize=shift``: Shift operators where the amount shifted is
greater or equal to the promoted bit-width of the left hand side
or less than zero, or where the left hand side is negative. For a
signed left shift, also checks for signed overflow in C, and for
unsigned overflow in C++. You can use ``-fsanitize=shift-base`` or
``-fsanitize=shift-exponent`` to check only left-hand side or
right-hand side of shift operation, respectively.
- ``-fsanitize=signed-integer-overflow``: Signed integer overflow,
including all the checks added by ``-ftrapv``, and checking for
overflow in signed division (``INT_MIN / -1``).
- ``-fsanitize=unreachable``: If control flow reaches
``__builtin_unreachable``.
- ``-fsanitize=unsigned-integer-overflow``: Unsigned integer
overflows.
- ``-fsanitize=vla-bound``: A variable-length array whose bound
does not evaluate to a positive value.
- ``-fsanitize=vptr``: Use of an object whose vptr indicates that
it is of the wrong dynamic type, or that its lifetime has not
begun or has ended. Incompatible with ``-fno-rtti``. Link must
be performed by ``clang++``, not ``clang``, to make sure C++-specific
parts of the runtime library and C++ standard libraries are present.
You can also use the following check groups:
- ``-fsanitize=undefined``: All of the checks listed above other than
``unsigned-integer-overflow``.
- ``-fsanitize=undefined-trap``: Deprecated alias of
``-fsanitize=undefined``.
- ``-fsanitize=integer``: Checks for undefined or suspicious integer
behavior (e.g. unsigned integer overflow).
Stack traces and report symbolization
=====================================
If you want UBSan to print symbolized stack trace for each error report, you
will need to:
#. Compile with ``-g`` and ``-fno-omit-frame-pointer`` to get proper debug
information in your binary.
#. Run your program with environment variable
``UBSAN_OPTIONS=print_stacktrace=1``.
#. Make sure ``llvm-symbolizer`` binary is in ``PATH``.
Issue Suppression
=================
UndefinedBehaviorSanitizer is not expected to produce false positives.
If you see one, look again; most likely it is a true positive!
Disabling Instrumentation with ``__attribute__((no_sanitize("undefined")))``
----------------------------------------------------------------------------
You disable UBSan checks for particular functions with
``__attribute__((no_sanitize("undefined")))``. You can use all values of
``-fsanitize=`` flag in this attribute, e.g. if your function deliberately
contains possible signed integer overflow, you can use
``__attribute__((no_sanitize("signed-integer-overflow")))``.
This attribute may not be
supported by other compilers, so consider using it together with
``#if defined(__clang__)``.
Suppressing Errors in Recompiled Code (Blacklist)
-------------------------------------------------
UndefinedBehaviorSanitizer supports ``src`` and ``fun`` entity types in
:doc:`SanitizerSpecialCaseList`, that can be used to suppress error reports
in the specified source files or functions.
Supported Platforms
===================
UndefinedBehaviorSanitizer is supported on the following OS:
* Android
* Linux
* FreeBSD
* OS X 10.6 onwards
and for the following architectures:
* i386/x86\_64
* ARM
* AArch64
* PowerPC64
* MIPS/MIPS64
Current Status
==============
UndefinedBehaviorSanitizer is available on selected platforms starting from LLVM
3.3. The test suite is integrated into the CMake build and can be run with
``check-ubsan`` command.
More Information
================
* From LLVM project blog:
`What Every C Programmer Should Know About Undefined Behavior
<http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html>`_
* From John Regehr's *Embedded in Academia* blog:
`A Guide to Undefined Behavior in C and C++
<http://blog.regehr.org/archives/213>`_