| Issue |
115323
|
| Summary |
`sincos` args may get clobbered after #108401 when passed on the stack
|
| Labels |
compiler-rt:asan,
llvm:SelectionDAG
|
| Assignees |
MacDue
|
| Reporter |
zmodem
|
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 3073c3c2290a6d9b12fbaefa40dd22eef6312895, 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 3073c3c2290a6d9b12fbaefa40dd22eef6312895, 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.
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs