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