-
Notifications
You must be signed in to change notification settings - Fork 15.2k
Closed
Labels
compiler-rt:asanAddress sanitizerAddress sanitizerllvm:SelectionDAGSelectionDAGISel as wellSelectionDAGISel as well
Description
Consider this program on 32-bit x86, where arguments are passed on the stack:
$ cat /tmp/a.cc
#include <math.h>
#include <stdio.h>
double __attribute__((noinline)) g(double a, double b) { return a + b; }
double __attribute__((noinline)) f(double a) {
double foo = sin(a);
double bar = cos(a);
double z = g(bar + 3.14, foo);
return z;
}
int main() {
printf("%f\n", f(3.14));
return 0;
}
After 3073c3c, it fails under ASan:
$ build/bin/clang.bad -target i386-unknown-linux-gnu -lm -fsanitize=address -fno-math-errno -O2 /tmp/a.cc && ASAN_OPTIONS=external_symbolizer_path=$PWD/build/bin/llvm-symbolizer ./a.out
AddressSanitizer:DEADLYSIGNAL
=================================================================
==3898196==ERROR: AddressSanitizer: SEGV on unknown address 0x27eb4300 (pc 0x566160ed bp 0xffab1898 sp 0xffab1470 T0)
==3898196==The signal is caused by a READ memory access.
#0 0x566160ed in QuickCheckForUnpoisonedRegion /work/llvm-project/compiler-rt/lib/asan/asan_interceptors_memintrinsics.h:37:7
#1 0x566160ed in sincos /work/llvm-project/compiler-rt/lib/asan/../sanitizer_common/sanitizer_common_interceptors.inc:5167:12
#2 0x566b25b1 in f(double) (/work/llvm-project/a.out+0x1085b1)
#3 0x566b25f3 in main (/work/llvm-project/a.out+0x1085f3)
#4 0xf7c29b84 (/lib/i386-linux-gnu/libc.so.6+0x23b84) (BuildId: d16f2b0239d79fbec67438094f9a9443121ab72d)
#5 0xf7c29c47 in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x23c47) (BuildId: d16f2b0239d79fbec67438094f9a9443121ab72d)
#6 0x565c43a6 in _start (/work/llvm-project/a.out+0x1a3a6)
==3898196==Register values:
eax = 0x27eb4300 ebx = 0x27eb4303 ecx = 0x27eb4300 edx = 0x3f5a1819
edi = 0x07eb4303 esi = 0x07eb4302 ebp = 0xffab1898 esp = 0xffab1470
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/work/llvm-project/a.out+0x1085b1) in f(double)
==3898196==ABORTING
The calls to sin and cos will get folded to a sincos call. After 3073c3c, the call looks like this:
37: 89 e6 mov %esp,%esi
39: 8d 44 24 18 lea 0x18(%esp),%eax
3d: 89 44 24 0c mov %eax,0xc(%esp) // <-- cos
41: 8d 46 08 lea 0x8(%esi),%eax
44: 89 44 24 08 mov %eax,0x8(%esp) // <-- sin
48: f2 0f 11 04 24 movsd %xmm0,(%esp) // <-- x
4d: e8 fc ff ff ff call 4e <_Z1fd+0x2e>
4e: R_386_PLT32 sincos
Look at the value of the sin argument: it's 0x8(%esi) = 0x8(%esp) which is the stack slot for foo in the following call to g. But it's also the stack slot used for sin in the sincos call. This seems dangerous.
Since it's a 64-bit value, when sincos does *sin = ... it will clobber both the sin and cos arguments. ASan happens to notice, because it intercepts sincos and checks the validity of the pointers afterwards.
MacDue
Metadata
Metadata
Assignees
Labels
compiler-rt:asanAddress sanitizerAddress sanitizerllvm:SelectionDAGSelectionDAGISel as wellSelectionDAGISel as well