Clang 12 documentation

Clang 12 Documentation includes a range of tools such as AddressSanitizer, ThreadSanitizer, LeakSanitizer, LibTooling, and more.

  1. The clang AddressSanitizer
  2. The clang MemorySanitizer
  3. The clang LeakSanitizer
  4. The clang UndefinedBehaviorSanitizer
  5. The clang of the Hardware – assisted – AddressSanitizer
  6. The clang SafeStack
  7. The clang ShadowCallStack
  8. The clang ThreadSanitizer
  9. The clang of the Thread – Safety – Analysis
  10. The clang DataFlowSanitizer

This section is to document clang clang 12 documentation UndefinedBehaviorSanitizer translation. For reference only.

introduce

What is UndefinedBehavior?

So, what is undefined behavior? Undefined behavior happens when your code has correct syntax but its behavior is not within the bounds of what the language allows.

In short: the code is syntactically correct, but the behavior is actually wrong. Such as integer division by zero, signed integer overflow and similar operations.

The C and C++ standards define UndefinedBehavior similarly:

Undefined behavior: Behavior for which this international standard imposes no requirements.

UndefinedBehaviorSanitizer (UBSan) is a rapid test procedure in undefined behavior. UBSan makes some changes to the program code at compile time to catch various undefined behaviors in the program at run time, such as:

  • Use unaligned or null Pointers
  • Overflow of signed integers
  • Overflow that can result from conversions to floating-point types

The full list can be viewed here.

UBSan has an additional runtime library that provides better error reporting. The run-time cost of the detection operation is small and has no impact on the address space layout or ABI.

How to build

Use CMake to build LLVM/Clang.

usage

With the flag -fsanitize=undefined, clang++ can be used to compile and link programs. Be sure to use clang++ (not ld) as the linker so that the executable can compile the correct UBSan runtime libraries into the executable. If you compile and link C code, you can use Clang ++ instead of Clang.

% 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'
Copy the code

You can turn on only some of the checks in UBSan and define the options for each check:

  • -fsanitize=… : prints verbose error reports and continues execution (default);
  • -fno-sanitize-recover=… : Prints verbose error reports and exits the program;
  • -fsanitize-trap=… : Executes a trap instruction (not required)UBSanRuntime support).

Note: The Trap/Recover option does not enable the corresponding Sanitizer, which usually requires the appropriate -fsanitize= tag.

For example, you can compile a linker:

% clang++ -fsanitize=signed-integer-overflow,null,alignment -fno-sanitize-recover=null -fsanitize-trap=alignment
Copy the code

When signed integer overflows occur, execution continues. Exits on the first illegal use of a null pointer. Fires the operating system’s trap instruction on the first encounter with the use of a misaligned pointer.

Additional checks

There are additional checks as follows:

  • -fSANitize =alignment: Use of unaligned Pointers or creation of unaligned references. Other attributes like alignment are also checked.
  • -fSANitize =bool: loads a bool that is neither true nor false.
  • -fsanitize=builtin: passed an invalid value built into the compiler.
  • -fsanitize=bounds: Array out of bounds (in a scenario where array range can be statically determined). This check includes-fsanitize=array-bounds-fsanitize=local-bounds. Pay attention to-fsanitize=local-boundsNot included in-fsanitize=undefinedIn the.
  • -fSANitize =enum: For an enumeration type, load those values that are not in its specified representation range.
  • -fsanitize= floating-cast-overflow: Converts using floating-point types, which may result in overflow. Because Clang supports a range of representation values for all floating-point types[-inf, +inf]. The only exception is converting a floating-point type to an integer type.
  • -fsanitize= floating-separate-by-zero: indicates floating-point division by zero. This isC/C++The behavior is undefined in the standard library, but Clang (as well as ISO/IEC/IEEE 60559 /IEEE 754) defines it as producing an infinity or NaN value, so it is not included in-fsanitize=undefinedIn the.
  • -fsanitize=function: calls a function indirectly through a function pointer of the wrong type. (support Darwin/Linux, C++ and x86/x86_64 only)
  • -fsanitize=implicit-unsigned-integer-truncation, -fsanitize=implicit-signed-integer-truncation: Implicitly convert an integer with a larger bit width to an integer with a smaller bit width, in the case of data loss as a result. That is, the degraded value, and then converted back to the original value, is based on the original value is not equal to the degraded conversion. When at least one of the types is signed,-fsanitize=implicit-unsigned-integer-truncationHandles conversions between two unsigned types,-fsanitize=implicit-signed-integer-truncationHandle the rest of the conversions (that is, signed types). This type of error is not undefined behavior, but it often happens inadvertently.
  • -fsanitize=implicit-integer-sign-change: indicates that the sign of a value is changed because of the implicit conversion between integer types. That is, if the initial value is negative and the new value is positive (or zero), or if the initial value is positive and the new value is negative. The problem with this type of capture is not undefined behavior, but it often happens inadvertently.
  • -fsanitize= integer-separate-by-zero: integer divided by zero.
  • -fsanitize=nonnull-attribute: The null pointer is passed in as a function parameter that cannot be null.
  • -fsanitize= NULL: Uses a null pointer or creates a null reference.
  • -fsanitize= Nullability -arg: Passes NULL to an annotation called_NonnullFunction argument of.
  • -fsanitize= Nullability -assign: Passes NULL to an annotated as_NonnullThe value of the.
  • -fsanitize= Nullability -return: Returns from the annotation_NonnullValue returns a NULL in the function.
  • -fsanitize= objC-cast: Implicitly converts the objC object pointer to a mismatched type. This often happens inadvertently, but it is not undefined behavior, so the check item is not part of undefined behavior. Currently supported only on Darwin.
  • -fsanitize=object-size: You might try to use bytes that the compiler can determine, but that are not part of the object being accessed. An attempt to potentially use bytes which the optimizer can determine are not part of the object being.) This also checks for types of undefined behavior that may not have direct access to memory but are indeed illegal in terms of object size, such as downcasts and using illegal Pointers to call methods. These tests are based on__builtin_object_sizeTherefore, it may be used to check for more problems at higher optimization levels.
  • -fsanitize=pointer-overflow: perform pointer operation, but result in overflow, or the old or new pointer value is a null pointer (or in C, they are both null Pointers).
  • -fsanitize=return: in C++ code, when a function is about to end, no value is returned.
  • -fsanitize=returns-nonnull-attribute: A null pointer is returned in a function that does not 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 operation, it also checks for signed overflow in C and unsigned overflow in C++. You can use-fsanitize=shift-baseor-fsanitize=shift-exponentTo only examine the left or right side of the Shift operation respectively.
  • -fsanitize=signed-integer-overflow: The result of an operation on a signed integer cannot be represented by its type, that is, the signed integer overflows. Includes all uses-ftrapv, and overflow for signed division (INT_MIN/-1), but does not include implicit conversions that exist before an operation and cause a loss of precision (see-fsanitize=implicit-conversion). Both types of questions can be used-fsanitize=implicit-conversionProblem group.
  • -fsanitize=unreachable: Control flow enters an unreachable program code.
  • -fsanitize=unsigned-integer-overflow: unsigned integers overflow and the result of an unsigned integer calculation cannot be represented by its type class. Unlike signed integer overflow, unsigned integer overflow is not undefined, but it often happens inadvertently. Prior to this type of computation, Sanitizer does not check for lossy implicit transformations, (see-fsanitize=implicit-conversion).
  • -fsanitize=vla-bound: an array of variable lengths with non-positive bounds.
  • -fsanitize= VPTR: use an object, but its virtual pointer table (vptr) indicates that it is an incorrect dynamic type, or that its life cycle has not started or has ended. Can’t with-fno-rttiCompatible. You must use theclang++(rather than clang) to ensure that the runtime library andC++In the standard libraryC++Certain parts can be used normally.

You can also use the following inspection groups:

  • -fsanitize=undefined: contains all of the above items except floating-point division by zero, unsigned integer overflow, implicit conversion, local bounds, andnullability-The inspection.
  • -fsanitize=undefined trap: the trap has been deprecated-fsanitize=undefined.
  • – fSANitize = implicit-integer-TRUNCation: captures lossy integer conversion. openimplicit-signed-integer-truncationimplicit-unsigned-integer-truncation.
  • -fsanitize= implicit-integer-integral-value-change: capture implicit conversions that can change the result of integer operations. openimplicit-signed-integer-truncationimplicit-integer-sign-change.
  • -fsanitize=implicit-conversion: checks for suspicious behaviors in implicit conversion. openimplicit-unsigned-integer-truncation,implicit-signed-integer-truncationimplicit-integer-sign-change.
  • -fsanitize= INTEGER: undefined or suspicious integer behavior (such as undefined integer overflow). Enable these options:signed-integer-overflow, unsigned-integer-overflow, shift, integer-divide-by-zero, implicit-unsigned-integer-truncation, implicit-signed-integer-truncation, and implicit-integer-sign-change.
  • – fsanitize = nullability: open itnullability-arg,nullability-assign, andnullability-return. Due to theviolating nullabilityThere is no undefined behavior, but it often happens inadvertently, so UBSan catches it.

Volatile

The volatile keyword disallows compiler instruction reordering.

Null, alignment, object size, local boundaries, and VPTR checks do not apply to Pointers to types under volatile. (the original: The null, alignment, object-size, local-bounds, And VPTR checks do not apply to different types with the volatile qualifier.)

Minimum runtime

This is the smallest UBSan runtime available for a production environment. This runtime has a small attack surface. -fsanitize=function and -fsanitize= VPTR checks are not supported. The minimal runtime can be used by adding -fsanitize-minimal- Runtime to the clang command line argument. For example, if you are used to compiling with -fsanitize=undefined, use -fsanitize=undefined – fsanitize-minimal-Runtime.

Stack information and symbolic reports

If you use UBSan to print symbolic stack information for each error report, do this:

  1. use-g-fno-omit-frame-pointerTo compile the code to get the correct debugging information.
  2. Using environment variablesUBSAN_OPTIONS=print_stacktrace=1To run the program.
  3. Make sure thatllvm-symbolizerBinary in$PATHIn the path.

record

The default log file for diagnostics is the standard error output stderr. If you want to log diagnostics to another file, you can set the flag UBSAN_OPTIONS=log_path=…. .

Overflow of unsigned integers is not reported

Set UBSAN_OPTIONS=silence_unsigned_overflow=1 to ignore unsigned integer overflow. This feature is used in conjunction with the ***-fsanitize-recover=unsigned-integer-overflow***, This is especially useful for ***providing fuzzing signal without blowing up logs.

The problem out

UndefinedBehaviorSanitizer will not produce false positives. If you find false positives, look carefully; It’s usually the right report.

It is prohibited to useattribute((no_sanitize(“undefined”)))To insert the pile

You can use attribute((no_sanitize(“undefined”))) to disable UBSan checking for specific functions. You can use all values of the -fsanitize= flag in this compiler property setting. For example, if a function deliberately wants to include possible signed integer overflow, you can use the compiler attribute((no_sanitize(“signed-integer-overflow”)).

The compiler property may not be supported by other compilers, so it is used with #if Defined (clang).

Eliminate errors in recompiled code

In a particular case of the Sanitizer list, UndefinedBehaviorSanitizer support SRC and fun entity types, it can be used to eliminate errors in the specified file or function.

Runtime Suppressions

Sometimes, it is possible to cull UBSan error reports for specific files, functions, or libraries without recompiling the code. You need to use the UBSAN_OPTIONS environment variable to pass a file path that holds the culled error report.

UBSAN_OPTIONS=suppressions=MyUBSan.supp
Copy the code

You need to specify the type of error report to cull and error location, for example:

signed-integer-overflow:file-with-known-overflow.cpp
alignment:function_doing_unaligned_access
vptr:shared_object_with_vptr_failures.so
Copy the code

There are several limitations:

  • In some cases, the binary must contain enough debugging information or symbol tables so that the runtime can find the source file or function name corresponding to the error report culling.
  • Only recoverable tests can be excluded. As in the example above, you can pass additional parameters-fsanitize-recover=signed-integer-overflow,alignment,vptrAlthough most UBSan checks are recoverable by default.
  • The action of culling files cannot be used for inspection groups (similarundefined), supported onlyfine-grainedThe inspection.

Supported Platforms

UndefinedBehaviorSanitizer supports the following operating systems:

  • Android
  • Linux
  • NetBSD
  • FreeBSD
  • OpenBSD
  • macOS
  • Windows

The runtime library is portable and platform independent. If the operating system, not listed in the above UndefinedBehaviorSanitizer may still apply, or only a little bit of migration.

The current state

Since LLVM 3.3 UndefinedBehaviorSanitizer will have support a particular platform. The test suite is integrated into the CMake build and can be run using the check-ubsan command.

Additional configuration

UndefinedBehaviorSanitizer can add static checking for each data, except trap mode. Check that the data contains the complete file name. This information can be removed with the option ***-fsanitize-undefined-strip-path-components=N. If N is a positive number, UndefinedBehaviorSanitizer * * * generated file information will lose the file path of the first N directory name. If N is negative, the last N directory names are retained.

case

For the source file */code/library/file.cpp8, the resulting file information will look like this:

  • Default (No flag, or -fsanitize-undefined-strip-path-components=0): /code/library/file.cpp
  • -fsanitize-undefined-strip-path-components=1: code/library/file.cpp
  • -fsanitize-undefined-strip-path-components=2: library/file.cpp
  • -fsanitize-undefined-strip-path-components=-1: file.cpp
  • -fsanitize-undefined-strip-path-components=-2: library/file.cpp

For more information

  • What Every C Programmer Should Know About Undefined Behavior
  • From John Regehr’s Embedded in Academia blog: A Guide to Undefined Behavior in C and C++