reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
  197
  198
  199
  200
  201
  202
  203
  204
  205
  206
  207
  208
  209
  210
  211
  212
  213
  214
  215
  216
  217
  218
  219
  220
  221
================
MemorySanitizer
================

.. contents::
   :local:

Introduction
============

MemorySanitizer is a detector of uninitialized reads. It consists of a
compiler instrumentation module and a run-time library.

Typical slowdown introduced by MemorySanitizer is **3x**.

How to build
============

Build LLVM/Clang with `CMake <https://llvm.org/docs/CMake.html>`_.

Usage
=====

Simply compile and link your program with ``-fsanitize=memory`` flag.
The MemorySanitizer run-time library should be linked to the final
executable, so make sure to use ``clang`` (not ``ld``) for the final
link step. When linking shared libraries, the MemorySanitizer run-time
is not linked, so ``-Wl,-z,defs`` may cause link errors (don't use it
with MemorySanitizer). To get a reasonable performance add ``-O1`` or
higher. To get meaningful stack traces in error messages add
``-fno-omit-frame-pointer``. To get perfect stack traces you may need
to disable inlining (just use ``-O1``) and tail call elimination
(``-fno-optimize-sibling-calls``).

.. code-block:: console

    % cat umr.cc
    #include <stdio.h>

    int main(int argc, char** argv) {
      int* a = new int[10];
      a[5] = 0;
      if (a[argc])
        printf("xx\n");
      return 0;
    }

    % clang -fsanitize=memory -fno-omit-frame-pointer -g -O2 umr.cc

If a bug is detected, the program will print an error message to
stderr and exit with a non-zero exit code.

.. code-block:: console

    % ./a.out
    WARNING: MemorySanitizer: use-of-uninitialized-value
        #0 0x7f45944b418a in main umr.cc:6
        #1 0x7f45938b676c in __libc_start_main libc-start.c:226

By default, MemorySanitizer exits on the first detected error. If you
find the error report hard to understand, try enabling
:ref:`origin tracking <msan-origins>`.

``__has_feature(memory_sanitizer)``
------------------------------------

In some cases one may need to execute different code depending on
whether MemorySanitizer is enabled. :ref:`\_\_has\_feature
<langext-__has_feature-__has_extension>` can be used for this purpose.

.. code-block:: c

    #if defined(__has_feature)
    #  if __has_feature(memory_sanitizer)
    // code that builds only under MemorySanitizer
    #  endif
    #endif

``__attribute__((no_sanitize("memory")))``
-----------------------------------------------

Some code should not be checked by MemorySanitizer.  One may use the function
attribute ``no_sanitize("memory")`` to disable uninitialized checks in a
particular function.  MemorySanitizer may still instrument such functions to
avoid false positives.  This attribute may not be supported by other compilers,
so we suggest to use it together with ``__has_feature(memory_sanitizer)``.

Blacklist
---------

MemorySanitizer supports ``src`` and ``fun`` entity types in
:doc:`SanitizerSpecialCaseList`, that can be used to relax MemorySanitizer
checks for certain source files and functions. All "Use of uninitialized value"
warnings will be suppressed and all values loaded from memory will be
considered fully initialized.

Report symbolization
====================

MemorySanitizer uses an external symbolizer to print files and line numbers in
reports. Make sure that ``llvm-symbolizer`` binary is in ``PATH``,
or set environment variable ``MSAN_SYMBOLIZER_PATH`` to point to it.

.. _msan-origins:

Origin Tracking
===============

MemorySanitizer can track origins of uninitialized values, similar to
Valgrind's --track-origins option. This feature is enabled by
``-fsanitize-memory-track-origins=2`` (or simply
``-fsanitize-memory-track-origins``) Clang option. With the code from
the example above,

.. code-block:: console

    % cat umr2.cc
    #include <stdio.h>

    int main(int argc, char** argv) {
      int* a = new int[10];
      a[5] = 0;
      volatile int b = a[argc];
      if (b)
        printf("xx\n");
      return 0;
    }

    % clang -fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer -g -O2 umr2.cc
    % ./a.out
    WARNING: MemorySanitizer: use-of-uninitialized-value
        #0 0x7f7893912f0b in main umr2.cc:7
        #1 0x7f789249b76c in __libc_start_main libc-start.c:226

      Uninitialized value was stored to memory at
        #0 0x7f78938b5c25 in __msan_chain_origin msan.cc:484
        #1 0x7f7893912ecd in main umr2.cc:6

      Uninitialized value was created by a heap allocation
        #0 0x7f7893901cbd in operator new[](unsigned long) msan_new_delete.cc:44
        #1 0x7f7893912e06 in main umr2.cc:4

By default, MemorySanitizer collects both allocation points and all
intermediate stores the uninitialized value went through.  Origin
tracking has proved to be very useful for debugging MemorySanitizer
reports. It slows down program execution by a factor of 1.5x-2x on top
of the usual MemorySanitizer slowdown and increases memory overhead.

Clang option ``-fsanitize-memory-track-origins=1`` enables a slightly
faster mode when MemorySanitizer collects only allocation points but
not intermediate stores.

Use-after-destruction detection
===============================

You can enable experimental use-after-destruction detection in MemorySanitizer.
After invocation of the destructor, the object will be considered no longer
readable, and using underlying memory will lead to error reports in runtime.

This feature is still experimental, in order to enable it at runtime you need
to:

#. Pass addition Clang option ``-fsanitize-memory-use-after-dtor`` during
   compilation.
#. Set environment variable `MSAN_OPTIONS=poison_in_dtor=1` before running
   the program.

Handling external code
======================

MemorySanitizer requires that all program code is instrumented. This
also includes any libraries that the program depends on, even libc.
Failing to achieve this may result in false reports.
For the same reason you may need to replace all inline assembly code that writes to memory
with a pure C/C++ code.

Full MemorySanitizer instrumentation is very difficult to achieve. To
make it easier, MemorySanitizer runtime library includes 70+
interceptors for the most common libc functions. They make it possible
to run MemorySanitizer-instrumented programs linked with
uninstrumented libc. For example, the authors were able to bootstrap
MemorySanitizer-instrumented Clang compiler by linking it with
self-built instrumented libc++ (as a replacement for libstdc++).

Supported Platforms
===================

MemorySanitizer is supported on the following OS:

* Linux
* NetBSD
* FreeBSD

Limitations
===========

* MemorySanitizer uses 2x more real memory than a native run, 3x with
  origin tracking.
* MemorySanitizer maps (but not reserves) 64 Terabytes of virtual
  address space. This means that tools like ``ulimit`` may not work as
  usually expected.
* Static linking is not supported.
* Older versions of MSan (LLVM 3.7 and older) didn't work with
  non-position-independent executables, and could fail on some Linux
  kernel versions with disabled ASLR. Refer to documentation for older versions
  for more details.
* MemorySanitizer might be incompatible with position-independent executables
  from FreeBSD 13 but there is a check done at runtime and throws a warning
  in this case.

Current Status
==============

MemorySanitizer is known to work on large real-world programs
(like Clang/LLVM itself) that can be recompiled from source, including all
dependent libraries.

More Information
================

`<https://github.com/google/sanitizers/wiki/MemorySanitizer>`_