xref: /llvm-project/clang/docs/MemorySanitizer.rst (revision baa51ffd9c417c9ec272c601673c484bc4335319)
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