Alexey, Alexander,
Thanks for the suggestions. I tried removing the flag SA_NODEFER
but it didn’t do any good… I have been digging into the problem with the null_deref test today but I was unable to clearly identify the problem. I suspect that it was either a bug with the calling convention/unwinding that lead to the flags() pointer to get corrupted. It is also possible that it was related with endianess issues caused by some bug in the pointer arithmetic inserted by the sanitizer code (there are many type and bit casts which makes hard to follow the references). I decided to upgrade the compiler I was using to build clang which made the problem with this testcase to go away (!).
Nevertheless, I still got problems in other testcases that may be potentially related with the problem I was getting before. E.g., in the new_array_cookie_test I am getting an infinite loop in the destructor of the array (delete operator). I noticed that the references passed to __asan_poison_cxx_array_cookie and __asan_load_cxx_array_cookie were pointing to values differing in the 4 most significant bytes, which made me suspect that the problem is related with endianess. I am reproducing part of the IR generated for this test:
store i64 %0, i64* %9, align 8, !dbg !35, !nosanitize !2
call void @__asan_poison_cxx_array_cookie(i64* %9), !dbg !35
%10 = getelementptr inbounds i8* %call, i64 8, !dbg !35
%11 = bitcast i8* %10 to %struct.C*, !dbg !35
call void @llvm.dbg.value(metadata !{%struct.C* %11}, i64 0, metadata !23), !dbg !36
%x = bitcast i8* %call to i32*, !dbg !37
%12 = ptrtoint i32* %x to i64, !dbg !37
%13 = lshr i64 %12, 3, !dbg !37
%14 = add i64 %13, 2199023255552, !dbg !37
%15 = inttoptr i64 %14 to i8*, !dbg !37
%16 = load i8* %15, !dbg !37
%17 = icmp ne i8 %16, 0, !dbg !37
br i1 %17, label %18, label %24, !dbg !37, !prof !38
; :18 ; preds = %entry
%19 = and i64 %12, 7, !dbg !37
%20 = add i64 %19, 3, !dbg !37
%21 = trunc i64 %20 to i8, !dbg !37
%22 = icmp sge i8 %21, %16, !dbg !37
br i1 %22, label %23, label %24
; :23 ; preds = %18
call void @__asan_report_store4(i64 %12), !dbg !37
call void asm sideeffect “”, “”()
unreachable
; :24 ; preds = %18, %entry
store i32 10, i32* %x, align 4, !dbg !37, !tbaa !39
%25 = call i64 @__asan_load_cxx_array_cookie(i64* %9), !dbg !44
In this code, %9 and %x alias but have different types (i64* and i32*), which makes the code in ‘store i32 10, i32* %x, align 4, !dbg !37, !tbaa !39’ to produce different results in machines with different endianess. In a big-endian machine the value 10 is written to the 4 most-significant bytes of the memory referenced by %9.
As I mentioned before, I don’t know the sanitizer implementation well so it is possible I may be missing something. Can anyone shed some light on this?
Thanks again!
Samuel
Alexander Potapenko —09/05/2014 02:06:43 AM—Note that I’ve set the SA_NODEFER flag for the SEGV handler in the ASan runtime only a couple of day