246 lines · plain
1================2MemorySanitizer3================4 5.. contents::6 :local:7 8Introduction9============10 11MemorySanitizer is a detector of uninitialized memory use. It consists of a12compiler instrumentation module and a run-time library.13 14Typical slowdown introduced by MemorySanitizer is **3x**.15 16Here is a not comprehensive of list cases when MemorySanitizer will report an error:17 18* Uninitialized value was used in a conditional branch.19* Uninitialized pointer was used for memory accesses.20* Uninitialized value was passed or returned from a function call, which is considered an undefined behavior. The check can be disabled with ``-fno-sanitize-memory-param-retval``.21* Uninitialized data was passed into some libc calls.22 23How to build24============25 26Build LLVM/Clang with `CMake <https://llvm.org/docs/CMake.html>`_.27 28Usage29=====30 31Simply compile and link your program with ``-fsanitize=memory`` flag.32The MemorySanitizer run-time library should be linked to the final33executable, so make sure to use ``clang`` (not ``ld``) for the final34link step. When linking shared libraries, the MemorySanitizer run-time35is not linked, so ``-Wl,-z,defs`` may cause link errors (don't use it36with MemorySanitizer). To get a reasonable performance add ``-O1`` or37higher. To get meaningful stack traces in error messages add38``-fno-omit-frame-pointer``. To get perfect stack traces you may need39to disable inlining (just use ``-O1``) and tail call elimination40(``-fno-optimize-sibling-calls``).41 42.. code-block:: console43 44 % cat umr.cc45 #include <stdio.h>46 47 int main(int argc, char** argv) {48 int* a = new int[10];49 a[5] = 0;50 if (a[argc])51 printf("xx\n");52 return 0;53 }54 55 % clang -fsanitize=memory -fno-omit-frame-pointer -g -O2 umr.cc56 57If a bug is detected, the program will print an error message to58stderr and exit with a non-zero exit code.59 60.. code-block:: console61 62 % ./a.out63 WARNING: MemorySanitizer: use-of-uninitialized-value64 #0 0x7f45944b418a in main umr.cc:665 #1 0x7f45938b676c in __libc_start_main libc-start.c:22666 67By default, MemorySanitizer exits on the first detected error. If you68find the error report hard to understand, try enabling69:ref:`origin tracking <msan-origins>`.70 71``__has_feature(memory_sanitizer)``72------------------------------------73 74In some cases one may need to execute different code depending on75whether MemorySanitizer is enabled. :ref:`\_\_has\_feature76<langext-__has_feature-__has_extension>` can be used for this purpose.77 78.. code-block:: c79 80 #if defined(__has_feature)81 # if __has_feature(memory_sanitizer)82 // code that builds only under MemorySanitizer83 # endif84 #endif85 86``__attribute__((no_sanitize("memory")))``87-----------------------------------------------88 89Some code should not be checked by MemorySanitizer. One may use the function90attribute ``no_sanitize("memory")`` to disable uninitialized checks in a91particular function. MemorySanitizer may still instrument such functions to92avoid false positives. This attribute may not be supported by other compilers,93so we suggest to use it together with ``__has_feature(memory_sanitizer)``.94 95``__attribute__((disable_sanitizer_instrumentation))``96--------------------------------------------------------97 98The ``disable_sanitizer_instrumentation`` attribute can be applied to functions99to prevent all kinds of instrumentation. As a result, it may introduce false100positives and therefore should be used with care, and only if absolutely101required; for example for certain code that cannot tolerate any instrumentation102and resulting side-effects. This attribute overrides ``no_sanitize("memory")``.103 104Ignorelist105----------106 107MemorySanitizer supports ``src`` and ``fun`` entity types in108:doc:`SanitizerSpecialCaseList`, that can be used to relax MemorySanitizer109checks for certain source files and functions. All "Use of uninitialized value"110warnings will be suppressed and all values loaded from memory will be111considered fully initialized.112 113Report symbolization114====================115 116MemorySanitizer uses an external symbolizer to print files and line numbers in117reports. Make sure that ``llvm-symbolizer`` binary is in ``PATH``,118or set environment variable ``MSAN_SYMBOLIZER_PATH`` to point to it.119 120.. _msan-origins:121 122Origin Tracking123===============124 125MemorySanitizer can track origins of uninitialized values, similar to126Valgrind's --track-origins option. This feature is enabled by127``-fsanitize-memory-track-origins=2`` (or simply128``-fsanitize-memory-track-origins``) Clang option. With the code from129the example above,130 131.. code-block:: console132 133 % cat umr2.cc134 #include <stdio.h>135 136 int main(int argc, char** argv) {137 int* a = new int[10];138 a[5] = 0;139 volatile int b = a[argc];140 if (b)141 printf("xx\n");142 return 0;143 }144 145 % clang -fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer -g -O2 umr2.cc146 % ./a.out147 WARNING: MemorySanitizer: use-of-uninitialized-value148 #0 0x7f7893912f0b in main umr2.cc:7149 #1 0x7f789249b76c in __libc_start_main libc-start.c:226150 151 Uninitialized value was stored to memory at152 #0 0x7f78938b5c25 in __msan_chain_origin msan.cc:484153 #1 0x7f7893912ecd in main umr2.cc:6154 155 Uninitialized value was created by a heap allocation156 #0 0x7f7893901cbd in operator new[](unsigned long) msan_new_delete.cc:44157 #1 0x7f7893912e06 in main umr2.cc:4158 159By default, MemorySanitizer collects both allocation points and all160intermediate stores the uninitialized value went through. Origin161tracking has proved to be very useful for debugging MemorySanitizer162reports. It slows down program execution by a factor of 1.5x-2x on top163of the usual MemorySanitizer slowdown and increases memory overhead.164 165Clang option ``-fsanitize-memory-track-origins=1`` enables a slightly166faster mode when MemorySanitizer collects only allocation points but167not intermediate stores.168 169Use-after-destruction detection170===============================171 172MemorySanitizer includes use-after-destruction detection. After invocation of173the destructor, the object will be considered no longer readable, and using174underlying memory will lead to error reports in runtime. Refer to the standard175for `lifetime <https://eel.is/c++draft/basic.life#1>`_ definition.176 177This feature can be disabled with either:178 179#. Pass additional Clang option ``-fno-sanitize-memory-use-after-dtor`` during180 compilation.181#. Set environment variable `MSAN_OPTIONS=poison_in_dtor=0` before running182 the program.183 184Handling external code185======================186 187MemorySanitizer requires that all program code is instrumented. This188also includes any libraries that the program depends on, even libc.189Failing to achieve this may result in false reports.190For the same reason you may need to replace all inline assembly code that writes to memory191with a pure C/C++ code.192 193Full MemorySanitizer instrumentation is very difficult to achieve. To194make it easier, MemorySanitizer runtime library includes 70+195interceptors for the most common libc functions. They make it possible196to run MemorySanitizer-instrumented programs linked with197uninstrumented libc. For example, the authors were able to bootstrap198MemorySanitizer-instrumented Clang compiler by linking it with199self-built instrumented libc++ (as a replacement for libstdc++).200 201Security Considerations202=======================203 204MemorySanitizer is a bug detection tool and its runtime is not meant to be205linked against production executables. While it may be useful for testing,206MemorySanitizer's runtime was not developed with security-sensitive207constraints in mind and may compromise the security of the resulting executable.208 209Supported Platforms210===================211 212MemorySanitizer is supported on the following OS:213 214* Linux215* NetBSD216* FreeBSD217 218Limitations219===========220 221* MemorySanitizer uses 2x more real memory than a native run, 3x with222 origin tracking.223* MemorySanitizer maps (but not reserves) 64 Terabytes of virtual224 address space. This means that tools like ``ulimit`` may not work as225 usually expected.226* Static linking is not supported.227* Older versions of MSan (LLVM 3.7 and older) didn't work with228 non-position-independent executables, and could fail on some Linux229 kernel versions with disabled ASLR. Refer to documentation for older versions230 for more details.231* MemorySanitizer might be incompatible with position-independent executables232 from FreeBSD 13 but there is a check done at runtime and throws a warning233 in this case.234 235Current Status236==============237 238MemorySanitizer is known to work on large real-world programs239(like Clang/LLVM itself) that can be recompiled from source, including all240dependent libraries.241 242More Information243================244 245`<https://github.com/google/sanitizers/wiki/MemorySanitizer>`_246