Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between a direct and indirect leak?

I got the following output from the LeakSanitizer tool. What is the difference between a direct and indirect leak, as the tool understands it?

13: ==29107==ERROR: LeakSanitizer: detected memory leaks
13: 
13: Direct leak of 288 byte(s) in 6 object(s) allocated from:
13:     #0 0x7f2ce0089050 in __interceptor_malloc (/nix/store/zahs1kwq4742f6l6h7yy4mdj44zzc1kd-gcc-7-20170409-lib/lib/libasan.so+0xd9050)
13:     #1 0x7f2cdfb974fe in qdr_core_subscribe ../src/router_core/route_tables.c:149
13:     #2 0x7f2cdfb47ff0 in IoAdapter_init ../src/python_embedded.c:548
13:     #3 0x7f2cde966ecd in type_call (/nix/store/1snk2wkpv97an87pk1842fgskl1vqhkr-python-2.7.14/lib/libpython2.7.so.1.0+0x9fecd)
13: 
13: Indirect leak of 2368 byte(s) in 1 object(s) allocated from:
13:     #0 0x7f2ce0089b88 in __interceptor_posix_memalign (/nix/store/zahs1kwq4742f6l6h7yy4mdj44zzc1kd-gcc-7-20170409-lib/lib/libasan.so+0xd9b88)
13:     #1 0x7f2cdfbcc8ea in qd_alloc ../src/alloc_pool.c:182
13:     #2 0x7f2cdfbb6c6b in qd_server_connection ../src/server.c:500
13:     #3 0x7f2cdfbbe27d in on_accept ../src/server.c:531
13:     #4 0x7f2cdfbbe27d in handle_listener ../src/server.c:701
13:     #5 0x7f2cdfbbe27d in handle ../src/server.c:844
13:     #6 0x7f2cdfbc2837 in thread_run ../src/server.c:921
13:     #7 0x7f2cdf0ba233 in start_thread (/nix/store/zpg78y1mf0di6127q6r51kgx2q8cxsvv-glibc-2.25-49/lib/libpthread.so.0+0x7233)
[...]
like image 474
user7610 Avatar asked Oct 04 '17 20:10

user7610


People also ask

What is indirect leak?

An indirect leak is a heap object that is reachable by a pointer to its start address, but with all such pointers originating in leaked objects. Leaks can be thought of as trees, with the top-level object the direct leaks and all child objects indirect leaks.

What is leak sanitizer?

LeakSanitizer is a run-time memory leak detector. It can be combined with AddressSanitizer to get both memory error and leak detection, or used in a stand-alone mode. LSan adds almost no performance overhead until the very end of the process, at which point there is an extra leak detection phase.


2 Answers

The LSan wiki design document states:

Another useful feature is being able to distinguish between directly leaked blocks (not reachable from anywhere) and indirectly leaked blocks (reachable from other leaked blocks).

Stated another way, indirect leaks are a result of direct leaks. Fixing direct leaks should make the indirect leaks become either fixed or direct leaks themselves (depending on whether their memory management is implemented correctly or not, respectively).

like image 179
Nick Desaulniers Avatar answered Sep 26 '22 16:09

Nick Desaulniers


The accepted answer isn't quite correct. In particular

Stated another way, indirect leaks are a result of direct leaks.

is wrong in that it's possible to have only indirect leaks. This situation may arise when a self-referential structure is built and leaked.

Example:

#include <malloc.h>

struct Foo {
  struct Foo *other;
};

void fn(int depth)
{
  if (depth > 0) {
    // recursion is only necessary to avoid LSan finding "stray" pointers
    // and not reporting any leaks at all.
    fn(depth - 1);
  } else {
    struct Foo *f1 = malloc(sizeof(*f1));
    struct Foo *f2 = malloc(sizeof(*f2));
    f1->other = f2;
    f2->other = f1;
  }
}

int main()
{
  fn(10);
  return 0;
}
clang -g -fsanitize=address  t.c && ./a.out

=================================================================
==845196==ERROR: LeakSanitizer: detected memory leaks

Indirect leak of 8 byte(s) in 1 object(s) allocated from:
    #0 0x49832d in malloc (/tmp/a.out+0x49832d)
    #1 0x4c7f8e in fn /tmp/t.c:15:22
    #2 0x4c7f71 in fn /tmp/t.c:12:5
    #3 0x4c7f71 in fn /tmp/t.c:12:5
    #4 0x4c7f71 in fn /tmp/t.c:12:5
    #5 0x4c7f71 in fn /tmp/t.c:12:5
    #6 0x4c7f71 in fn /tmp/t.c:12:5
    #7 0x4c7f71 in fn /tmp/t.c:12:5
    #8 0x4c7f71 in fn /tmp/t.c:12:5
    #9 0x4c7f71 in fn /tmp/t.c:12:5
    #10 0x4c7f71 in fn /tmp/t.c:12:5
    #11 0x4c7f71 in fn /tmp/t.c:12:5
    #12 0x4c8028 in main /tmp/t.c:23:3
    #13 0x7f147d3a7d09 in __libc_start_main csu/../csu/libc-start.c:308:16

Indirect leak of 8 byte(s) in 1 object(s) allocated from:
    #0 0x49832d in malloc (/tmp/a.out+0x49832d)
    #1 0x4c7f80 in fn /tmp/t.c:14:22
    #2 0x4c7f71 in fn /tmp/t.c:12:5
    #3 0x4c7f71 in fn /tmp/t.c:12:5
    #4 0x4c7f71 in fn /tmp/t.c:12:5
    #5 0x4c7f71 in fn /tmp/t.c:12:5
    #6 0x4c7f71 in fn /tmp/t.c:12:5
    #7 0x4c7f71 in fn /tmp/t.c:12:5
    #8 0x4c7f71 in fn /tmp/t.c:12:5
    #9 0x4c7f71 in fn /tmp/t.c:12:5
    #10 0x4c7f71 in fn /tmp/t.c:12:5
    #11 0x4c7f71 in fn /tmp/t.c:12:5
    #12 0x4c8028 in main /tmp/t.c:23:3
    #13 0x7f147d3a7d09 in __libc_start_main csu/../csu/libc-start.c:308:16

SUMMARY: AddressSanitizer: 16 byte(s) leaked in 2 allocation(s).

Note: no direct leaks, only indirect ones.

like image 23
Employed Russian Avatar answered Sep 25 '22 16:09

Employed Russian