1================ 2MemorySanitizer 3================ 4 5.. contents:: 6 :local: 7 8Introduction 9============ 10 11MemorySanitizer is a detector of uninitialized memory use. It consists of a 12compiler 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 build 24============ 25 26Build LLVM/Clang with `CMake <https://llvm.org/docs/CMake.html>`_. 27 28Usage 29===== 30 31Simply compile and link your program with ``-fsanitize=memory`` flag. 32The MemorySanitizer run-time library should be linked to the final 33executable, so make sure to use ``clang`` (not ``ld``) for the final 34link step. When linking shared libraries, the MemorySanitizer run-time 35is not linked, so ``-Wl,-z,defs`` may cause link errors (don't use it 36with MemorySanitizer). To get a reasonable performance add ``-O1`` or 37higher. To get meaningful stack traces in error messages add 38``-fno-omit-frame-pointer``. To get perfect stack traces you may need 39to disable inlining (just use ``-O1``) and tail call elimination 40(``-fno-optimize-sibling-calls``). 41 42.. code-block:: console 43 44 % cat umr.cc 45 #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.cc 56 57If a bug is detected, the program will print an error message to 58stderr and exit with a non-zero exit code. 59 60.. code-block:: console 61 62 % ./a.out 63 WARNING: MemorySanitizer: use-of-uninitialized-value 64 #0 0x7f45944b418a in main umr.cc:6 65 #1 0x7f45938b676c in __libc_start_main libc-start.c:226 66 67By default, MemorySanitizer exits on the first detected error. If you 68find the error report hard to understand, try enabling 69:ref:`origin tracking <msan-origins>`. 70 71``__has_feature(memory_sanitizer)`` 72------------------------------------ 73 74In some cases one may need to execute different code depending on 75whether MemorySanitizer is enabled. :ref:`\_\_has\_feature 76<langext-__has_feature-__has_extension>` can be used for this purpose. 77 78.. code-block:: c 79 80 #if defined(__has_feature) 81 # if __has_feature(memory_sanitizer) 82 // code that builds only under MemorySanitizer 83 # endif 84 #endif 85 86``__attribute__((no_sanitize("memory")))`` 87----------------------------------------------- 88 89Some code should not be checked by MemorySanitizer. One may use the function 90attribute ``no_sanitize("memory")`` to disable uninitialized checks in a 91particular function. MemorySanitizer may still instrument such functions to 92avoid 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 functions 99to prevent all kinds of instrumentation. As a result, it may introduce false 100positives and therefore should be used with care, and only if absolutely 101required; for example for certain code that cannot tolerate any instrumentation 102and resulting side-effects. This attribute overrides ``no_sanitize("memory")``. 103 104Ignorelist 105---------- 106 107MemorySanitizer supports ``src`` and ``fun`` entity types in 108:doc:`SanitizerSpecialCaseList`, that can be used to relax MemorySanitizer 109checks for certain source files and functions. All "Use of uninitialized value" 110warnings will be suppressed and all values loaded from memory will be 111considered fully initialized. 112 113Report symbolization 114==================== 115 116MemorySanitizer uses an external symbolizer to print files and line numbers in 117reports. 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 Tracking 123=============== 124 125MemorySanitizer can track origins of uninitialized values, similar to 126Valgrind's --track-origins option. This feature is enabled by 127``-fsanitize-memory-track-origins=2`` (or simply 128``-fsanitize-memory-track-origins``) Clang option. With the code from 129the example above, 130 131.. code-block:: console 132 133 % cat umr2.cc 134 #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.cc 146 % ./a.out 147 WARNING: MemorySanitizer: use-of-uninitialized-value 148 #0 0x7f7893912f0b in main umr2.cc:7 149 #1 0x7f789249b76c in __libc_start_main libc-start.c:226 150 151 Uninitialized value was stored to memory at 152 #0 0x7f78938b5c25 in __msan_chain_origin msan.cc:484 153 #1 0x7f7893912ecd in main umr2.cc:6 154 155 Uninitialized value was created by a heap allocation 156 #0 0x7f7893901cbd in operator new[](unsigned long) msan_new_delete.cc:44 157 #1 0x7f7893912e06 in main umr2.cc:4 158 159By default, MemorySanitizer collects both allocation points and all 160intermediate stores the uninitialized value went through. Origin 161tracking has proved to be very useful for debugging MemorySanitizer 162reports. It slows down program execution by a factor of 1.5x-2x on top 163of the usual MemorySanitizer slowdown and increases memory overhead. 164 165Clang option ``-fsanitize-memory-track-origins=1`` enables a slightly 166faster mode when MemorySanitizer collects only allocation points but 167not intermediate stores. 168 169Use-after-destruction detection 170=============================== 171 172MemorySanitizer includes use-after-destruction detection. After invocation of 173the destructor, the object will be considered no longer readable, and using 174underlying memory will lead to error reports in runtime. Refer to the standard 175for `lifetime <https://eel.is/c++draft/basic.life#1>`_ definition. 176 177This feature can be disabled with either: 178 179#. Pass addition Clang option ``-fno-sanitize-memory-use-after-dtor`` during 180 compilation. 181#. Set environment variable `MSAN_OPTIONS=poison_in_dtor=0` before running 182 the program. 183 184Handling external code 185====================== 186 187MemorySanitizer requires that all program code is instrumented. This 188also 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 memory 191with a pure C/C++ code. 192 193Full MemorySanitizer instrumentation is very difficult to achieve. To 194make it easier, MemorySanitizer runtime library includes 70+ 195interceptors for the most common libc functions. They make it possible 196to run MemorySanitizer-instrumented programs linked with 197uninstrumented libc. For example, the authors were able to bootstrap 198MemorySanitizer-instrumented Clang compiler by linking it with 199self-built instrumented libc++ (as a replacement for libstdc++). 200 201Security Considerations 202======================= 203 204MemorySanitizer is a bug detection tool and its runtime is not meant to be 205linked against production executables. While it may be useful for testing, 206MemorySanitizer's runtime was not developed with security-sensitive 207constraints in mind and may compromise the security of the resulting executable. 208 209Supported Platforms 210=================== 211 212MemorySanitizer is supported on the following OS: 213 214* Linux 215* NetBSD 216* FreeBSD 217 218Limitations 219=========== 220 221* MemorySanitizer uses 2x more real memory than a native run, 3x with 222 origin tracking. 223* MemorySanitizer maps (but not reserves) 64 Terabytes of virtual 224 address space. This means that tools like ``ulimit`` may not work as 225 usually expected. 226* Static linking is not supported. 227* Older versions of MSan (LLVM 3.7 and older) didn't work with 228 non-position-independent executables, and could fail on some Linux 229 kernel versions with disabled ASLR. Refer to documentation for older versions 230 for more details. 231* MemorySanitizer might be incompatible with position-independent executables 232 from FreeBSD 13 but there is a check done at runtime and throws a warning 233 in this case. 234 235Current Status 236============== 237 238MemorySanitizer is known to work on large real-world programs 239(like Clang/LLVM itself) that can be recompiled from source, including all 240dependent libraries. 241 242More Information 243================ 244 245`<https://github.com/google/sanitizers/wiki/MemorySanitizer>`_ 246