1================ 2MemorySanitizer 3================ 4 5.. contents:: 6 :local: 7 8Introduction 9============ 10 11MemorySanitizer is a detector of uninitialized reads. It consists of a 12compiler instrumentation module and a run-time library. 13 14Typical slowdown introduced by MemorySanitizer is **3x**. 15 16How to build 17============ 18 19Build LLVM/Clang with `CMake <https://llvm.org/docs/CMake.html>`_. 20 21Usage 22===== 23 24Simply compile and link your program with ``-fsanitize=memory`` flag. 25The MemorySanitizer run-time library should be linked to the final 26executable, so make sure to use ``clang`` (not ``ld``) for the final 27link step. When linking shared libraries, the MemorySanitizer run-time 28is not linked, so ``-Wl,-z,defs`` may cause link errors (don't use it 29with MemorySanitizer). To get a reasonable performance add ``-O1`` or 30higher. To get meaningful stack traces in error messages add 31``-fno-omit-frame-pointer``. To get perfect stack traces you may need 32to disable inlining (just use ``-O1``) and tail call elimination 33(``-fno-optimize-sibling-calls``). 34 35.. code-block:: console 36 37 % cat umr.cc 38 #include <stdio.h> 39 40 int main(int argc, char** argv) { 41 int* a = new int[10]; 42 a[5] = 0; 43 if (a[argc]) 44 printf("xx\n"); 45 return 0; 46 } 47 48 % clang -fsanitize=memory -fno-omit-frame-pointer -g -O2 umr.cc 49 50If a bug is detected, the program will print an error message to 51stderr and exit with a non-zero exit code. 52 53.. code-block:: console 54 55 % ./a.out 56 WARNING: MemorySanitizer: use-of-uninitialized-value 57 #0 0x7f45944b418a in main umr.cc:6 58 #1 0x7f45938b676c in __libc_start_main libc-start.c:226 59 60By default, MemorySanitizer exits on the first detected error. If you 61find the error report hard to understand, try enabling 62:ref:`origin tracking <msan-origins>`. 63 64``__has_feature(memory_sanitizer)`` 65------------------------------------ 66 67In some cases one may need to execute different code depending on 68whether MemorySanitizer is enabled. :ref:`\_\_has\_feature 69<langext-__has_feature-__has_extension>` can be used for this purpose. 70 71.. code-block:: c 72 73 #if defined(__has_feature) 74 # if __has_feature(memory_sanitizer) 75 // code that builds only under MemorySanitizer 76 # endif 77 #endif 78 79``__attribute__((no_sanitize("memory")))`` 80----------------------------------------------- 81 82Some code should not be checked by MemorySanitizer. One may use the function 83attribute ``no_sanitize("memory")`` to disable uninitialized checks in a 84particular function. MemorySanitizer may still instrument such functions to 85avoid false positives. This attribute may not be supported by other compilers, 86so we suggest to use it together with ``__has_feature(memory_sanitizer)``. 87 88Blacklist 89--------- 90 91MemorySanitizer supports ``src`` and ``fun`` entity types in 92:doc:`SanitizerSpecialCaseList`, that can be used to relax MemorySanitizer 93checks for certain source files and functions. All "Use of uninitialized value" 94warnings will be suppressed and all values loaded from memory will be 95considered fully initialized. 96 97Report symbolization 98==================== 99 100MemorySanitizer uses an external symbolizer to print files and line numbers in 101reports. Make sure that ``llvm-symbolizer`` binary is in ``PATH``, 102or set environment variable ``MSAN_SYMBOLIZER_PATH`` to point to it. 103 104.. _msan-origins: 105 106Origin Tracking 107=============== 108 109MemorySanitizer can track origins of uninitialized values, similar to 110Valgrind's --track-origins option. This feature is enabled by 111``-fsanitize-memory-track-origins=2`` (or simply 112``-fsanitize-memory-track-origins``) Clang option. With the code from 113the example above, 114 115.. code-block:: console 116 117 % cat umr2.cc 118 #include <stdio.h> 119 120 int main(int argc, char** argv) { 121 int* a = new int[10]; 122 a[5] = 0; 123 volatile int b = a[argc]; 124 if (b) 125 printf("xx\n"); 126 return 0; 127 } 128 129 % clang -fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer -g -O2 umr2.cc 130 % ./a.out 131 WARNING: MemorySanitizer: use-of-uninitialized-value 132 #0 0x7f7893912f0b in main umr2.cc:7 133 #1 0x7f789249b76c in __libc_start_main libc-start.c:226 134 135 Uninitialized value was stored to memory at 136 #0 0x7f78938b5c25 in __msan_chain_origin msan.cc:484 137 #1 0x7f7893912ecd in main umr2.cc:6 138 139 Uninitialized value was created by a heap allocation 140 #0 0x7f7893901cbd in operator new[](unsigned long) msan_new_delete.cc:44 141 #1 0x7f7893912e06 in main umr2.cc:4 142 143By default, MemorySanitizer collects both allocation points and all 144intermediate stores the uninitialized value went through. Origin 145tracking has proved to be very useful for debugging MemorySanitizer 146reports. It slows down program execution by a factor of 1.5x-2x on top 147of the usual MemorySanitizer slowdown and increases memory overhead. 148 149Clang option ``-fsanitize-memory-track-origins=1`` enables a slightly 150faster mode when MemorySanitizer collects only allocation points but 151not intermediate stores. 152 153Use-after-destruction detection 154=============================== 155 156You can enable experimental use-after-destruction detection in MemorySanitizer. 157After invocation of the destructor, the object will be considered no longer 158readable, and using underlying memory will lead to error reports in runtime. 159 160This feature is still experimental, in order to enable it at runtime you need 161to: 162 163#. Pass addition Clang option ``-fsanitize-memory-use-after-dtor`` during 164 compilation. 165#. Set environment variable `MSAN_OPTIONS=poison_in_dtor=1` before running 166 the program. 167 168Handling external code 169====================== 170 171MemorySanitizer requires that all program code is instrumented. This 172also includes any libraries that the program depends on, even libc. 173Failing to achieve this may result in false reports. 174For the same reason you may need to replace all inline assembly code that writes to memory 175with a pure C/C++ code. 176 177Full MemorySanitizer instrumentation is very difficult to achieve. To 178make it easier, MemorySanitizer runtime library includes 70+ 179interceptors for the most common libc functions. They make it possible 180to run MemorySanitizer-instrumented programs linked with 181uninstrumented libc. For example, the authors were able to bootstrap 182MemorySanitizer-instrumented Clang compiler by linking it with 183self-built instrumented libc++ (as a replacement for libstdc++). 184 185Supported Platforms 186=================== 187 188MemorySanitizer is supported on the following OS: 189 190* Linux 191* NetBSD 192* FreeBSD 193 194Limitations 195=========== 196 197* MemorySanitizer uses 2x more real memory than a native run, 3x with 198 origin tracking. 199* MemorySanitizer maps (but not reserves) 64 Terabytes of virtual 200 address space. This means that tools like ``ulimit`` may not work as 201 usually expected. 202* Static linking is not supported. 203* Older versions of MSan (LLVM 3.7 and older) didn't work with 204 non-position-independent executables, and could fail on some Linux 205 kernel versions with disabled ASLR. Refer to documentation for older versions 206 for more details. 207* MemorySanitizer might be incompatible with position-independent executables 208 from FreeBSD 13 but there is a check done at runtime and throws a warning 209 in this case. 210 211Current Status 212============== 213 214MemorySanitizer is known to work on large real-world programs 215(like Clang/LLVM itself) that can be recompiled from source, including all 216dependent libraries. 217 218More Information 219================ 220 221`<https://github.com/google/sanitizers/wiki/MemorySanitizer>`_ 222