gopalshankar / address-sanitizer

Automatically exported from code.google.com/p/address-sanitizer
0 stars 0 forks source link

Infinite recursion in the dynamic runtime on 10.8 #116

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
On a 10.7 machine:

$ cat t.c 
#include <stdlib.h>
int main() { 
free((void*)0x1234567);
 return 0; }

$ build/Release+Asserts/bin/clang -faddress-sanitizer t.c -o t  -v              

clang version 3.2 (trunk 165105) (llvm/trunk 165119)
Target: x86_64-apple-darwin11.4.2
Thread model: posix
 "/Users/glider/src/asan/llvm/build/Release+Asserts/bin/clang" -cc1 -triple x86_64-apple-macosx10.7.0 -emit-obj -mrelax-all -disable-free -main-file-name t.c -pic-level 2 -mdisable-fp-elim -masm-verbose -munwind-tables -target-cpu core2 -target-linker-version 133.3 -v -resource-dir /Users/glider/src/asan/llvm/build/Release+Asserts/bin/../lib/clang/3.2 -fmodule-cache-path /var/folders/00/0k0r8000h01000cxqpysvccm002831/T/clang-module-cache -fdebug-compilation-dir /Users/glider/src/asan/llvm -ferror-limit 19 -fmessage-length 186 -faddress-sanitizer -stack-protector 1 -mstackrealign -fblocks -fobjc-runtime=macosx-10.7.0 -fobjc-dispatch-method=mixed -fobjc-default-synthesize-properties -fdiagnostics-show-option -fcolor-diagnostics -o /var/folders/00/0k0r8000h01000cxqpysvccm002831/T/t-t64Sky.o -x c t.c
clang -cc1 version 3.2 based upon LLVM 3.2svn default target 
x86_64-apple-darwin11.4.2
ignoring nonexistent directory "/usr/local/include"
#include "..." search starts here:
#include <...> search starts here:
 /Users/glider/src/asan/llvm/build/Release+Asserts/bin/../lib/clang/3.2/include
 /usr/include
 /System/Library/Frameworks (framework directory)
 /Library/Frameworks (framework directory)
End of search list.
 "/usr/llvm-gcc-4.2/libexec/gcc/i686-apple-darwin11/4.2.1/ld" -demangle -dynamic -arch x86_64 -macosx_version_min 10.7.0 -o t -lcrt1.10.6.o /var/folders/00/0k0r8000h01000cxqpysvccm002831/T/t-t64Sky.o /Users/glider/src/asan/llvm/build/Release+Asserts/bin/../lib/clang/3.2/lib/darwin/libclang_rt.asan_osx_dynamic.dylib -lstdc++ -framework CoreFoundation -lSystem /Users/glider/src/asan/llvm/build/Release+Asserts/bin/../lib/clang/3.2/lib/darwin/libclang_rt.osx.a

$ otool -L 
/Users/glider/src/asan/llvm/build/Release+Asserts/bin/../lib/clang/3.2/lib/darwi
n/libclang_rt.asan_osx_dynamic.dylib
/Users/glider/src/asan/llvm/build/Release+Asserts/bin/../lib/clang/3.2/lib/darwi
n/libclang_rt.asan_osx_dynamic.dylib:
    @loader_path/libclang_rt.asan_osx_dynamic.dylib (compatibility version 0.0.0, current version 0.0.0)
    /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 833.25.0)
    /usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 52.0.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)
    /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 635.21.0)

On a 10.6 machine:

$ ./t
==4833== AddressSanitizer CHECK failed: 
/Users/glider/src/asan/llvm/projects/compiler-rt/lib/sanitizer_common/sanitizer_
mac.cc:99 "((env_ptr)) != (0)" (0x0, 0x0)
Stats: 0M malloced (0M for red zones) by 0 calls
Stats: 0M realloced by 0 calls
Stats: 0M freed by 0 calls
Stats: 0M really freed by 0 calls
Stats: 0M (0 full pages) mmaped in 0 calls
  mmaps   by size class: 
  mallocs by size class: 
  frees   by size class: 
  rfrees  by size class: 
Stats: malloc large: 0 small slow: 0

Original issue reported on code.google.com by ramosian.glider@gmail.com on 3 Oct 2012 at 4:45

GoogleCodeExporter commented 9 years ago
10.7 again:
$ ./t
ASAN:SIGSEGV
=================================================================
==52310== ERROR: AddressSanitizer crashed on unknown address 0x00000123455f (pc 
0x00010c07fddc sp 0x7fff6bc70300 bp 0x7fff6bc70b30 T0)
AddressSanitizer can not provide additional info.
    #0 0x10c07fddb (/Users/glider/src/asan/llvm/./libclang_rt.asan_osx_dynamic.dylib+0x8ddb)
    #1 0x10c071e67 (/Users/glider/src/asan/llvm/./t+0x100000e67)
    #2 0x10c071d73 (/Users/glider/src/asan/llvm/./t+0x100000d73)
    #3 0x0
Stats: 0M malloced (0M for red zones) by 0 calls
Stats: 0M realloced by 0 calls
Stats: 0M freed by 0 calls
Stats: 0M really freed by 0 calls
Stats: 0M (0 full pages) mmaped in 0 calls
  mmaps   by size class: 
  mallocs by size class: 
  frees   by size class: 
  rfrees  by size class: 
Stats: malloc large: 0 small slow: 0
==52310== ABORTING

Original comment by ramosian.glider@gmail.com on 3 Oct 2012 at 4:46

GoogleCodeExporter commented 9 years ago
On a 10.8 machine:

$ ./t
ASAN:SIGSEGV
=================================================================
==87734== ERROR: AddressSanitizer crashed on unknown address 0x00000123455f (pc 
0x00010000bddc sp 0x7fff5fbff3c0 bp 0x7fff5fbffbf0 T0)
AddressSanitizer can not provide additional info.
    #0 0x10000bddb (/Users/glider/./libclang_rt.asan_osx_dynamic.dylib+0x8ddb)
    #1 0x100000e67 (/Users/glider/./t+0x100000e67)
    #2 0x100000d53 (/Users/glider/./t+0x100000d53)
    #3 0x0 (/Users/glider/./t+0x0)
Segmentation fault: 11

Original comment by ramosian.glider@gmail.com on 3 Oct 2012 at 4:48

GoogleCodeExporter commented 9 years ago
This has nothing to do with copying the files to other machines, i.e. the test 
really behaves this way when built on 10.6 and 10.8.
I've opened issue 117 to track the CHECK failure from _NSGetEnviron() on 10.6, 
so let the current issue remain for the segfault on 10.8

Original comment by ramosian.glider@gmail.com on 4 Oct 2012 at 12:40

GoogleCodeExporter commented 9 years ago

Original comment by ramosian.glider@gmail.com on 4 Oct 2012 at 12:41

GoogleCodeExporter commented 9 years ago
The problem is not ASan-specific and is related to resolver function 
interposition being broken on Mac.
# ===========================================
$ cat t.c
#include <stdlib.h>

void *moomove(void *s1, void *s2, size_t n) {
  return memmove(s1, s2, n);
}

size_t moolen(const char *s) {
  return strlen(s);
}

int main() { 
 volatile int a[20];
 a[0] = moolen("Hello");
 moomove(&a[0], &a[10], 2);
 return 0;
}
# ===========================================
$ cat v.cc
#include <unistd.h>
#include <string.h>

size_t my_strlen(const char *s) {
//  write(2, "strlen\n", 7);
  return strlen(s);
}

void *my_memmove(void *s1, const void *s2, size_t n) {
//  write(2, "memmove\n", 8);
  return memmove(s1, s2, n);
}

struct interpose_substitution {
  const void* replacement;
  const void* original;
};

#define INTERPOSE_FUNCTION(function) \
    { reinterpret_cast<const void*>(my_##function), \
      reinterpret_cast<const void*>(function) }

__attribute__((used))
const interpose_substitution substitutions[]
    __attribute__((section("__DATA, __interpose"))) = {
  INTERPOSE_FUNCTION(strlen),
  INTERPOSE_FUNCTION(memmove),
};
# ===========================================
# v.dylib is an library that interposes strlen() and memmove()
$ g++ v.cc -dynamiclib -o v.dylib
# t is a program that calls strlen() and memmove()
$ gcc t.c -o t v.dylib -w
$ DYLD_INSERT_LIBRARIES=`pwd`/v.dylib ./t
Segmentation fault: 11

This actually happens because of the infinite recursion in my_memmove()
$  gdb t
(gdb) set env DYLD_INSERT_LIBRARIES=/Users/glider/src/asan/llvm/interp/v.dylib
(gdb) set start-with-shell 0
(gdb) r
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x00007fff5f3ffff8
0x0000000100003eea in my_memmove ()
...
#2976 0x0000000100003eef in my_memmove ()
#2977 0x0000000100003eef in my_memmove ()
#2978 0x0000000100003eef in my_memmove ()

Original comment by ramosian.glider@gmail.com on 15 Oct 2012 at 2:38

GoogleCodeExporter commented 9 years ago

Original comment by ramosian.glider@gmail.com on 15 Oct 2012 at 3:33

GoogleCodeExporter commented 9 years ago
This is a bug in the interposition of resolver functions (radar://12455091).
As a temporary solution the wrappers for such functions (e.g. memmove) now call 
our own implementations (e.g. internal_memmove).

Another solution from Nick Kledzik is to make a call via a pointer to the 
original function:

void (*pMemcpy)(void *, const void *, uptr n) = &memcpy;

void *internal_memcpy(void *dest, const void *src, uptr n) {
  // stuff
  return (*pMemcpy)(dest, src, n);
}

Original comment by ramosian.glider@gmail.com on 29 Oct 2012 at 11:30

GoogleCodeExporter commented 9 years ago
They say the problem is fixed in 10.9. We'll need to revisit this bug when we 
stop supporting 10.8 (around the time 10.10 is out)

Original comment by ramosian.glider@gmail.com on 7 May 2014 at 9:08