https://sourceware.org/bugzilla/show_bug.cgi?id=28101
Bug ID: 28101 Summary: elf_strptr slow with address sanitizer, passes entire section range to memrchr. Product: elfutils Version: unspecified Status: UNCONFIRMED Severity: enhancement Priority: P2 Component: libelf Assignee: unassigned at sourceware dot org Reporter: jan.smets at nokia dot com CC: elfutils-devel at sourceware dot org Target Milestone: --- This code block calls out to validate_str which calls to memrchr. The to= is the size of the entire section. I believe Address Sanitizer does validate the entire memory range. Passing the entire range to the memrchr null char check makes it very costly. 191 else if (likely (strscn->data_list_rear == NULL)) 192 { 193 // XXX The above is currently correct since elf_newdata will 194 // make sure to convert the rawdata into the datalist if 195 // necessary. But it would be more efficient to keep the rawdata 196 // unconverted and only then iterate over the rest of the (newly 197 // added data) list. Note that when the ELF file is mmapped 198 // rawdata_base can be set while rawdata.d hasn't been 199 // initialized yet (when data_read is zero). So we cannot just 200 // look at the rawdata.d.d_size. 201 202 /* Make sure the string is NUL terminated. Start from the end, 203 which very likely is a NUL char. */ 204 if (likely (validate_str (strscn->rawdata_base, offset, sh_size))) 205 result = &strscn->rawdata_base[offset]; 206 else 207 __libelf_seterrno (ELF_E_INVALID_INDEX); 208 } * libelf compiled with HAVE_DECL_MEMRCHR (default) * recent GCC toolchain (GCC6 and up) * files themselves don't even need to be compiled with asan, just enabling it at link time so the runtime wrapping/intercepting of libc et all fires. Testcase: test.c is attached. Generate a source file with dummy symbols to populate the symbol table. for i in {A..Z}{A..Z}{A..Z}{A..Z}; do echo "int sym$i;"; done > symbols.c gcc -c symbols.c -o symbols.o gcc -c test.c -o test.o -I /tmp/jan-test/elfutils/libelf/ #-fsanitize=address gcc test.o symbols.o -o test -l:libelf.a -L/tmp/jan-test/elfutils/libelf/ -lz -fsanitize=address echo -n "default asan:" time ./test test echo -n "asan disabled" gcc test.o symbols.o -o test -l:libelf.a -L/tmp/jan-test/elfutils/libelf/ -lz time ./test test I don't know of any ASAN_OPTIONS parameter that would change this behavior and make it less strict. On my machine the asan testcase takes 5+ sec, whereas the non-asan 0.04s. Can this code please be optimized to reduce the range passed to memrchr? Is this NUL check even required? -- You are receiving this mail because: You are on the CC list for the bug.