Sean Silva | bf9b4cd | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 1 | ================ |
| 2 | AddressSanitizer |
| 3 | ================ |
| 4 | |
| 5 | .. contents:: |
| 6 | :local: |
| 7 | |
| 8 | Introduction |
| 9 | ============ |
| 10 | |
Dmitri Gribenko | 7ac0cc3 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 11 | AddressSanitizer is a fast memory error detector. It consists of a compiler |
| 12 | instrumentation module and a run-time library. The tool can detect the |
| 13 | following types of bugs: |
Sean Silva | bf9b4cd | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 14 | |
Dmitri Gribenko | 7ac0cc3 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 15 | * Out-of-bounds accesses to heap, stack and globals |
| 16 | * Use-after-free |
Vitaly Buka | ca2f9d1 | 2016-08-02 17:51:48 +0000 | [diff] [blame] | 17 | * Use-after-return (runtime flag `ASAN_OPTIONS=detect_stack_use_after_return=1`) |
| 18 | * Use-after-scope (clang flag `-fsanitize-address-use-after-scope`) |
Dmitri Gribenko | 7ac0cc3 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 19 | * Double-free, invalid free |
Sergey Matveev | ae5b1d4 | 2013-12-11 09:14:36 +0000 | [diff] [blame] | 20 | * Memory leaks (experimental) |
Sean Silva | bf9b4cd | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 21 | |
| 22 | Typical slowdown introduced by AddressSanitizer is **2x**. |
| 23 | |
| 24 | How to build |
| 25 | ============ |
| 26 | |
Alexey Samsonov | 3a433f6 | 2015-02-18 22:26:20 +0000 | [diff] [blame] | 27 | Build LLVM/Clang with `CMake <http://llvm.org/docs/CMake.html>`_. |
Sean Silva | bf9b4cd | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 28 | |
| 29 | Usage |
| 30 | ===== |
| 31 | |
Dmitri Gribenko | 7ac0cc3 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 32 | Simply compile and link your program with ``-fsanitize=address`` flag. The |
| 33 | AddressSanitizer run-time library should be linked to the final executable, so |
| 34 | make sure to use ``clang`` (not ``ld``) for the final link step. When linking |
| 35 | shared libraries, the AddressSanitizer run-time is not linked, so |
| 36 | ``-Wl,-z,defs`` may cause link errors (don't use it with AddressSanitizer). To |
| 37 | get a reasonable performance add ``-O1`` or higher. To get nicer stack traces |
| 38 | in error messages add ``-fno-omit-frame-pointer``. To get perfect stack traces |
| 39 | you may need to disable inlining (just use ``-O1``) and tail call elimination |
| 40 | (``-fno-optimize-sibling-calls``). |
Sean Silva | bf9b4cd | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 41 | |
Dmitri Gribenko | 7ac0cc3 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 42 | .. code-block:: console |
Sean Silva | bf9b4cd | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 43 | |
| 44 | % cat example_UseAfterFree.cc |
| 45 | int main(int argc, char **argv) { |
| 46 | int *array = new int[100]; |
| 47 | delete [] array; |
| 48 | return array[argc]; // BOOM |
| 49 | } |
| 50 | |
Sean Silva | bf9b4cd | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 51 | # Compile and link |
Anna Zaks | 136e9f4 | 2016-12-15 22:55:21 +0000 | [diff] [blame] | 52 | % clang++ -O1 -g -fsanitize=address -fno-omit-frame-pointer example_UseAfterFree.cc |
Sean Silva | bf9b4cd | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 53 | |
Dmitri Gribenko | 7ac0cc3 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 54 | or: |
Sean Silva | bf9b4cd | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 55 | |
Dmitri Gribenko | 7ac0cc3 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 56 | .. code-block:: console |
Sean Silva | bf9b4cd | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 57 | |
| 58 | # Compile |
Anna Zaks | 136e9f4 | 2016-12-15 22:55:21 +0000 | [diff] [blame] | 59 | % clang++ -O1 -g -fsanitize=address -fno-omit-frame-pointer -c example_UseAfterFree.cc |
Sean Silva | bf9b4cd | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 60 | # Link |
Anna Zaks | 136e9f4 | 2016-12-15 22:55:21 +0000 | [diff] [blame] | 61 | % clang++ -g -fsanitize=address example_UseAfterFree.o |
Sean Silva | bf9b4cd | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 62 | |
Dmitri Gribenko | 7ac0cc3 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 63 | If a bug is detected, the program will print an error message to stderr and |
Anna Zaks | 8264a8c | 2015-06-25 23:36:44 +0000 | [diff] [blame] | 64 | exit with a non-zero exit code. AddressSanitizer exits on the first detected error. |
| 65 | This is by design: |
| 66 | |
| 67 | * This approach allows AddressSanitizer to produce faster and smaller generated code |
| 68 | (both by ~5%). |
| 69 | * Fixing bugs becomes unavoidable. AddressSanitizer does not produce |
| 70 | false alarms. Once a memory corruption occurs, the program is in an inconsistent |
| 71 | state, which could lead to confusing results and potentially misleading |
| 72 | subsequent reports. |
| 73 | |
| 74 | If your process is sandboxed and you are running on OS X 10.10 or earlier, you |
| 75 | will need to set ``DYLD_INSERT_LIBRARIES`` environment variable and point it to |
| 76 | the ASan library that is packaged with the compiler used to build the |
| 77 | executable. (You can find the library by searching for dynamic libraries with |
| 78 | ``asan`` in their name.) If the environment variable is not set, the process will |
| 79 | try to re-exec. Also keep in mind that when moving the executable to another machine, |
| 80 | the ASan library will also need to be copied over. |
| 81 | |
| 82 | Symbolizing the Reports |
| 83 | ========================= |
| 84 | |
| 85 | To make AddressSanitizer symbolize its output |
Alexander Potapenko | c754900 | 2014-01-16 13:46:29 +0000 | [diff] [blame] | 86 | you need to set the ``ASAN_SYMBOLIZER_PATH`` environment variable to point to |
Alexander Potapenko | f47e667 | 2014-01-16 14:01:39 +0000 | [diff] [blame] | 87 | the ``llvm-symbolizer`` binary (or make sure ``llvm-symbolizer`` is in your |
| 88 | ``$PATH``): |
Sean Silva | bf9b4cd | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 89 | |
Dmitri Gribenko | 7ac0cc3 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 90 | .. code-block:: console |
Sean Silva | bf9b4cd | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 91 | |
Alexander Potapenko | c754900 | 2014-01-16 13:46:29 +0000 | [diff] [blame] | 92 | % ASAN_SYMBOLIZER_PATH=/usr/local/bin/llvm-symbolizer ./a.out |
Sean Silva | bf9b4cd | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 93 | ==9442== ERROR: AddressSanitizer heap-use-after-free on address 0x7f7ddab8c084 at pc 0x403c8c bp 0x7fff87fb82d0 sp 0x7fff87fb82c8 |
| 94 | READ of size 4 at 0x7f7ddab8c084 thread T0 |
| 95 | #0 0x403c8c in main example_UseAfterFree.cc:4 |
| 96 | #1 0x7f7ddabcac4d in __libc_start_main ??:0 |
| 97 | 0x7f7ddab8c084 is located 4 bytes inside of 400-byte region [0x7f7ddab8c080,0x7f7ddab8c210) |
| 98 | freed by thread T0 here: |
| 99 | #0 0x404704 in operator delete[](void*) ??:0 |
| 100 | #1 0x403c53 in main example_UseAfterFree.cc:4 |
| 101 | #2 0x7f7ddabcac4d in __libc_start_main ??:0 |
| 102 | previously allocated by thread T0 here: |
| 103 | #0 0x404544 in operator new[](unsigned long) ??:0 |
| 104 | #1 0x403c43 in main example_UseAfterFree.cc:2 |
| 105 | #2 0x7f7ddabcac4d in __libc_start_main ??:0 |
| 106 | ==9442== ABORTING |
| 107 | |
Alexander Potapenko | c754900 | 2014-01-16 13:46:29 +0000 | [diff] [blame] | 108 | If that does not work for you (e.g. your process is sandboxed), you can use a |
| 109 | separate script to symbolize the result offline (online symbolization can be |
Alexander Potapenko | 108bc03 | 2014-01-16 13:48:16 +0000 | [diff] [blame] | 110 | force disabled by setting ``ASAN_OPTIONS=symbolize=0``): |
Alexander Potapenko | c754900 | 2014-01-16 13:46:29 +0000 | [diff] [blame] | 111 | |
| 112 | .. code-block:: console |
| 113 | |
Alexander Potapenko | 108bc03 | 2014-01-16 13:48:16 +0000 | [diff] [blame] | 114 | % ASAN_OPTIONS=symbolize=0 ./a.out 2> log |
Alexander Potapenko | c754900 | 2014-01-16 13:46:29 +0000 | [diff] [blame] | 115 | % projects/compiler-rt/lib/asan/scripts/asan_symbolize.py / < log | c++filt |
| 116 | ==9442== ERROR: AddressSanitizer heap-use-after-free on address 0x7f7ddab8c084 at pc 0x403c8c bp 0x7fff87fb82d0 sp 0x7fff87fb82c8 |
| 117 | READ of size 4 at 0x7f7ddab8c084 thread T0 |
| 118 | #0 0x403c8c in main example_UseAfterFree.cc:4 |
| 119 | #1 0x7f7ddabcac4d in __libc_start_main ??:0 |
| 120 | ... |
| 121 | |
| 122 | Note that on OS X you may need to run ``dsymutil`` on your binary to have the |
| 123 | file\:line info in the AddressSanitizer reports. |
| 124 | |
Anna Zaks | 8264a8c | 2015-06-25 23:36:44 +0000 | [diff] [blame] | 125 | Additional Checks |
| 126 | ================= |
Sean Silva | bf9b4cd | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 127 | |
Anna Zaks | 8264a8c | 2015-06-25 23:36:44 +0000 | [diff] [blame] | 128 | Initialization order checking |
| 129 | ----------------------------- |
| 130 | |
| 131 | AddressSanitizer can optionally detect dynamic initialization order problems, |
| 132 | when initialization of globals defined in one translation unit uses |
| 133 | globals defined in another translation unit. To enable this check at runtime, |
| 134 | you should set environment variable |
| 135 | ``ASAN_OPTIONS=check_initialization_order=1``. |
| 136 | |
| 137 | Note that this option is not supported on OS X. |
| 138 | |
| 139 | Memory leak detection |
| 140 | --------------------- |
| 141 | |
| 142 | For more information on leak detector in AddressSanitizer, see |
Francis Ricci | 8ae4e79 | 2017-09-13 19:40:10 +0000 | [diff] [blame] | 143 | :doc:`LeakSanitizer`. The leak detection is turned on by default on Linux, |
| 144 | and can be enabled using ``ASAN_OPTIONS=detect_leaks=1`` on OS X; |
Anna Zaks | 8264a8c | 2015-06-25 23:36:44 +0000 | [diff] [blame] | 145 | however, it is not yet supported on other platforms. |
| 146 | |
| 147 | Issue Suppression |
| 148 | ================= |
| 149 | |
| 150 | AddressSanitizer is not expected to produce false positives. If you see one, |
| 151 | look again; most likely it is a true positive! |
| 152 | |
| 153 | Suppressing Reports in External Libraries |
| 154 | ----------------------------------------- |
| 155 | Runtime interposition allows AddressSanitizer to find bugs in code that is |
| 156 | not being recompiled. If you run into an issue in external libraries, we |
| 157 | recommend immediately reporting it to the library maintainer so that it |
| 158 | gets addressed. However, you can use the following suppression mechanism |
| 159 | to unblock yourself and continue on with the testing. This suppression |
| 160 | mechanism should only be used for suppressing issues in external code; it |
| 161 | does not work on code recompiled with AddressSanitizer. To suppress errors |
| 162 | in external libraries, set the ``ASAN_OPTIONS`` environment variable to point |
| 163 | to a suppression file. You can either specify the full path to the file or the |
| 164 | path of the file relative to the location of your executable. |
| 165 | |
| 166 | .. code-block:: bash |
| 167 | |
| 168 | ASAN_OPTIONS=suppressions=MyASan.supp |
| 169 | |
| 170 | Use the following format to specify the names of the functions or libraries |
| 171 | you want to suppress. You can see these in the error report. Remember that |
| 172 | the narrower the scope of the suppression, the more bugs you will be able to |
| 173 | catch. |
| 174 | |
| 175 | .. code-block:: bash |
| 176 | |
| 177 | interceptor_via_fun:NameOfCFunctionToSuppress |
| 178 | interceptor_via_fun:-[ClassName objCMethodToSuppress:] |
| 179 | interceptor_via_lib:NameOfTheLibraryToSuppress |
| 180 | |
| 181 | Conditional Compilation with ``__has_feature(address_sanitizer)`` |
| 182 | ----------------------------------------------------------------- |
Sean Silva | bf9b4cd | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 183 | |
Dmitri Gribenko | 7ac0cc3 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 184 | In some cases one may need to execute different code depending on whether |
| 185 | AddressSanitizer is enabled. |
| 186 | :ref:`\_\_has\_feature <langext-__has_feature-__has_extension>` can be used for |
| 187 | this purpose. |
Sean Silva | bf9b4cd | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 188 | |
Dmitri Gribenko | 7ac0cc3 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 189 | .. code-block:: c |
Sean Silva | bf9b4cd | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 190 | |
| 191 | #if defined(__has_feature) |
Dmitri Gribenko | 7ac0cc3 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 192 | # if __has_feature(address_sanitizer) |
| 193 | // code that builds only under AddressSanitizer |
| 194 | # endif |
Sean Silva | bf9b4cd | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 195 | #endif |
| 196 | |
Anna Zaks | 8264a8c | 2015-06-25 23:36:44 +0000 | [diff] [blame] | 197 | Disabling Instrumentation with ``__attribute__((no_sanitize("address")))`` |
| 198 | -------------------------------------------------------------------------- |
Sean Silva | bf9b4cd | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 199 | |
Evgeniy Stepanov | 2b61d12 | 2018-06-21 00:16:32 +0000 | [diff] [blame] | 200 | Some code should not be instrumented by AddressSanitizer. One may use |
| 201 | the attribute ``__attribute__((no_sanitize("address")))`` (which has |
| 202 | deprecated synonyms `no_sanitize_address` and |
| 203 | `no_address_safety_analysis`) to disable instrumentation of a |
| 204 | particular function. This attribute may not be supported by other |
| 205 | compilers, so we suggest to use it together with |
Saleem Abdulrasool | 7f66d75 | 2015-10-19 01:24:08 +0000 | [diff] [blame] | 206 | ``__has_feature(address_sanitizer)``. |
Sean Silva | bf9b4cd | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 207 | |
Evgeniy Stepanov | 2b61d12 | 2018-06-21 00:16:32 +0000 | [diff] [blame] | 208 | The same attribute used on a global variable prevents AddressSanitizer |
| 209 | from adding redzones around it and detecting out of bounds accesses. |
| 210 | |
Anna Zaks | 8264a8c | 2015-06-25 23:36:44 +0000 | [diff] [blame] | 211 | Suppressing Errors in Recompiled Code (Blacklist) |
| 212 | ------------------------------------------------- |
Alexey Samsonov | 2de6833 | 2013-08-07 08:23:32 +0000 | [diff] [blame] | 213 | |
| 214 | AddressSanitizer supports ``src`` and ``fun`` entity types in |
| 215 | :doc:`SanitizerSpecialCaseList`, that can be used to suppress error reports |
| 216 | in the specified source files or functions. Additionally, AddressSanitizer |
| 217 | introduces ``global`` and ``type`` entity types that can be used to |
| 218 | suppress error reports for out-of-bound access to globals with certain |
| 219 | names and types (you may only specify class or struct types). |
| 220 | |
| 221 | You may use an ``init`` category to suppress reports about initialization-order |
| 222 | problems happening in certain source files or with certain global variables. |
| 223 | |
| 224 | .. code-block:: bash |
| 225 | |
| 226 | # Suppress error reports for code in a file or in a function: |
| 227 | src:bad_file.cpp |
| 228 | # Ignore all functions with names containing MyFooBar: |
| 229 | fun:*MyFooBar* |
| 230 | # Disable out-of-bound checks for global: |
| 231 | global:bad_array |
| 232 | # Disable out-of-bound checks for global instances of a given class ... |
Alexey Samsonov | a0ac3c2 | 2014-10-17 22:37:33 +0000 | [diff] [blame] | 233 | type:Namespace::BadClassName |
Alexey Samsonov | 2de6833 | 2013-08-07 08:23:32 +0000 | [diff] [blame] | 234 | # ... or a given struct. Use wildcard to deal with anonymous namespace. |
Alexey Samsonov | a0ac3c2 | 2014-10-17 22:37:33 +0000 | [diff] [blame] | 235 | type:Namespace2::*::BadStructName |
Alexey Samsonov | 2de6833 | 2013-08-07 08:23:32 +0000 | [diff] [blame] | 236 | # Disable initialization-order checks for globals: |
| 237 | global:bad_init_global=init |
| 238 | type:*BadInitClassSubstring*=init |
| 239 | src:bad/init/files/*=init |
| 240 | |
Alexey Samsonov | 710d9f8 | 2016-01-22 01:35:45 +0000 | [diff] [blame] | 241 | Suppressing memory leaks |
| 242 | ------------------------ |
| 243 | |
| 244 | Memory leak reports produced by :doc:`LeakSanitizer` (if it is run as a part |
| 245 | of AddressSanitizer) can be suppressed by a separate file passed as |
| 246 | |
| 247 | .. code-block:: bash |
| 248 | |
| 249 | LSAN_OPTIONS=suppressions=MyLSan.supp |
| 250 | |
| 251 | which contains lines of the form `leak:<pattern>`. Memory leak will be |
| 252 | suppressed if pattern matches any function name, source file name, or |
| 253 | library name in the symbolized stack trace of the leak report. See |
| 254 | `full documentation |
| 255 | <https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer#suppressions>`_ |
| 256 | for more details. |
| 257 | |
Sean Silva | bf9b4cd | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 258 | Limitations |
| 259 | =========== |
| 260 | |
Dmitri Gribenko | 7ac0cc3 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 261 | * AddressSanitizer uses more real memory than a native run. Exact overhead |
| 262 | depends on the allocations sizes. The smaller the allocations you make the |
| 263 | bigger the overhead is. |
| 264 | * AddressSanitizer uses more stack memory. We have seen up to 3x increase. |
| 265 | * On 64-bit platforms AddressSanitizer maps (but not reserves) 16+ Terabytes of |
| 266 | virtual address space. This means that tools like ``ulimit`` may not work as |
| 267 | usually expected. |
| 268 | * Static linking is not supported. |
Sean Silva | bf9b4cd | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 269 | |
Anna Zaks | 8264a8c | 2015-06-25 23:36:44 +0000 | [diff] [blame] | 270 | Supported Platforms |
| 271 | =================== |
| 272 | |
| 273 | AddressSanitizer is supported on: |
| 274 | |
| 275 | * Linux i386/x86\_64 (tested on Ubuntu 12.04) |
| 276 | * OS X 10.7 - 10.11 (i386/x86\_64) |
| 277 | * iOS Simulator |
| 278 | * Android ARM |
David Carlier | 59a339ab | 2018-07-25 13:55:06 +0000 | [diff] [blame] | 279 | * NetBSD i386/x86\_64 |
Anna Zaks | 8264a8c | 2015-06-25 23:36:44 +0000 | [diff] [blame] | 280 | * FreeBSD i386/x86\_64 (tested on FreeBSD 11-current) |
| 281 | |
| 282 | Ports to various other platforms are in progress. |
| 283 | |
Sean Silva | bf9b4cd | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 284 | Current Status |
| 285 | ============== |
| 286 | |
Dmitri Gribenko | 7ac0cc3 | 2012-12-15 21:10:51 +0000 | [diff] [blame] | 287 | AddressSanitizer is fully functional on supported platforms starting from LLVM |
| 288 | 3.1. The test suite is integrated into CMake build and can be run with ``make |
| 289 | check-asan`` command. |
Sean Silva | bf9b4cd | 2012-12-13 01:10:46 +0000 | [diff] [blame] | 290 | |
| 291 | More Information |
| 292 | ================ |
| 293 | |
Alexey Samsonov | 2e2469d | 2015-12-04 00:38:13 +0000 | [diff] [blame] | 294 | `<https://github.com/google/sanitizers/wiki/AddressSanitizer>`_ |