xref: /openbsd-src/gnu/llvm/clang/docs/MemorySanitizer.rst (revision 12c855180aad702bbcca06e0398d774beeafb155)
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
88``__attribute__((disable_sanitizer_instrumentation))``
89--------------------------------------------------------
90
91The ``disable_sanitizer_instrumentation`` attribute can be applied to functions
92to prevent all kinds of instrumentation. As a result, it may introduce false
93positives and therefore should be used with care, and only if absolutely
94required; for example for certain code that cannot tolerate any instrumentation
95and resulting side-effects. This attribute overrides ``no_sanitize("memory")``.
96
97Ignorelist
98----------
99
100MemorySanitizer supports ``src`` and ``fun`` entity types in
101:doc:`SanitizerSpecialCaseList`, that can be used to relax MemorySanitizer
102checks for certain source files and functions. All "Use of uninitialized value"
103warnings will be suppressed and all values loaded from memory will be
104considered fully initialized.
105
106Report symbolization
107====================
108
109MemorySanitizer uses an external symbolizer to print files and line numbers in
110reports. Make sure that ``llvm-symbolizer`` binary is in ``PATH``,
111or set environment variable ``MSAN_SYMBOLIZER_PATH`` to point to it.
112
113.. _msan-origins:
114
115Origin Tracking
116===============
117
118MemorySanitizer can track origins of uninitialized values, similar to
119Valgrind's --track-origins option. This feature is enabled by
120``-fsanitize-memory-track-origins=2`` (or simply
121``-fsanitize-memory-track-origins``) Clang option. With the code from
122the example above,
123
124.. code-block:: console
125
126    % cat umr2.cc
127    #include <stdio.h>
128
129    int main(int argc, char** argv) {
130      int* a = new int[10];
131      a[5] = 0;
132      volatile int b = a[argc];
133      if (b)
134        printf("xx\n");
135      return 0;
136    }
137
138    % clang -fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer -g -O2 umr2.cc
139    % ./a.out
140    WARNING: MemorySanitizer: use-of-uninitialized-value
141        #0 0x7f7893912f0b in main umr2.cc:7
142        #1 0x7f789249b76c in __libc_start_main libc-start.c:226
143
144      Uninitialized value was stored to memory at
145        #0 0x7f78938b5c25 in __msan_chain_origin msan.cc:484
146        #1 0x7f7893912ecd in main umr2.cc:6
147
148      Uninitialized value was created by a heap allocation
149        #0 0x7f7893901cbd in operator new[](unsigned long) msan_new_delete.cc:44
150        #1 0x7f7893912e06 in main umr2.cc:4
151
152By default, MemorySanitizer collects both allocation points and all
153intermediate stores the uninitialized value went through.  Origin
154tracking has proved to be very useful for debugging MemorySanitizer
155reports. It slows down program execution by a factor of 1.5x-2x on top
156of the usual MemorySanitizer slowdown and increases memory overhead.
157
158Clang option ``-fsanitize-memory-track-origins=1`` enables a slightly
159faster mode when MemorySanitizer collects only allocation points but
160not intermediate stores.
161
162Use-after-destruction detection
163===============================
164
165MemorySanitizer includes use-after-destruction detection. After invocation of
166the destructor, the object will be considered no longer readable, and using
167underlying memory will lead to error reports in runtime. Refer to the standard
168for `lifetime <https://eel.is/c++draft/basic.life#1>`_ definition.
169
170This feature can be disabled with either:
171
172#. Pass addition Clang option ``-fno-sanitize-memory-use-after-dtor`` during
173   compilation.
174#. Set environment variable `MSAN_OPTIONS=poison_in_dtor=0` before running
175   the program.
176
177Handling external code
178======================
179
180MemorySanitizer requires that all program code is instrumented. This
181also includes any libraries that the program depends on, even libc.
182Failing to achieve this may result in false reports.
183For the same reason you may need to replace all inline assembly code that writes to memory
184with a pure C/C++ code.
185
186Full MemorySanitizer instrumentation is very difficult to achieve. To
187make it easier, MemorySanitizer runtime library includes 70+
188interceptors for the most common libc functions. They make it possible
189to run MemorySanitizer-instrumented programs linked with
190uninstrumented libc. For example, the authors were able to bootstrap
191MemorySanitizer-instrumented Clang compiler by linking it with
192self-built instrumented libc++ (as a replacement for libstdc++).
193
194Supported Platforms
195===================
196
197MemorySanitizer is supported on the following OS:
198
199* Linux
200* NetBSD
201* FreeBSD
202
203Limitations
204===========
205
206* MemorySanitizer uses 2x more real memory than a native run, 3x with
207  origin tracking.
208* MemorySanitizer maps (but not reserves) 64 Terabytes of virtual
209  address space. This means that tools like ``ulimit`` may not work as
210  usually expected.
211* Static linking is not supported.
212* Older versions of MSan (LLVM 3.7 and older) didn't work with
213  non-position-independent executables, and could fail on some Linux
214  kernel versions with disabled ASLR. Refer to documentation for older versions
215  for more details.
216* MemorySanitizer might be incompatible with position-independent executables
217  from FreeBSD 13 but there is a check done at runtime and throws a warning
218  in this case.
219
220Current Status
221==============
222
223MemorySanitizer is known to work on large real-world programs
224(like Clang/LLVM itself) that can be recompiled from source, including all
225dependent libraries.
226
227More Information
228================
229
230`<https://github.com/google/sanitizers/wiki/MemorySanitizer>`_
231