<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/91565>91565</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Stack misalignment on AVX-512 with asan + detect_stack_use_after_return=0
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
glandium
</td>
</tr>
</table>
<pre>
Self-sufficient reproducer:
```
void qux(int& y);
struct alignas(64) Foo {
int a[16] = {};
};
void hoge(Foo x);
void foo() {
int x, y, z;
qux(x);
qux(y);
qux(z);
hoge(Foo());
}
```
Call the above `foo.cc`, and add the following as `main.cc` for an executable reproducer:
```
extern "C" const char *__asan_default_options() {
return "detect_stack_use_after_return=0";
}
void qux(int& y) {}
struct alignas(64) Foo {
int a[16] = {};
};
void hoge(Foo x) {}
void foo();
int main() {
foo();
return 0;
}
```
Compile with `clang++ -o foo foo.cc main.cc -fsanitize=address -O2 -mavx512f -g`. Running the program crashes:
```
Program received signal SIGSEGV, Segmentation fault.
0x0000559c458fd95c in foo () at foo.cc:14
14 hoge(Foo());
(gdb) disassemble $rip,$rip+1
Dump of assembler code from 0x559c458fd95c to 0x559c458fd95d:
=> 0x0000559c458fd95c <_Z3foov+236>: vmovaps %zmm0,(%rsp)
End of assembler dump.
(gdb) p/x $rsp
$1 = 0x7ffc7c389ce0
```
vmovaps with zmm registers requires 64-bytes alignment but rsp does not have enough alignment.
The relevant parts of the assembly code path:
```
and rsp, -64 // function prologue aligns the stack to 64-bytes and
sub rsp, 192 // resizes it in a 64-bytes-aligned way
(...)
mov r14, rsp
add r14, -96 // this is an alloca in the function prologue, triggered
// when __asan_stack_malloc_1 returns 0, which it does when
// detect_stack_use_after_return=0 or when it's out of fake
// stack.
and r14, -32 // align the stack to... 32-bytes.
mov rsp, r14
(...)
sub rsp, 64 // move the stack for argument passing. The stack is still
// 32-bytes aligned at this point.
(...)
vmovaps zmmword ptr [rsp], zmm0 // copy argument to the stack, aka CRASH.
```
This started with 51fbab134560ece663517bf1e8c2a30300d08f1a (#77210) and `-mllvm -asan-use-stack-safety=0` fixes it.
This all comes down to the asan pass setting the alloca to 32-bytes alignment:
```
%MyAlloca = alloca i8, i64 96, align 32
```
With `-mllvm -asan-use-stack-safety=0`, the alloca becomes:
```
%MyAlloca = alloca i8, i64 224, align 64
```
It's worth noting that it's only 32 because that's the default value of asan-realign-stack. With `-mllvm -asan-realign-stack=1` it gets down to 16.
Essentially, this kind of worked by chance before because the stack poisoner was doing the argument passing alloca too, so MyAlloca was sized and aligned for it. But now that's not the case anymore with stack-safety, MyAlloca doesn't contain and is not aligned for that alloca.
The function call to `hoge` has a proper `align 64` annotation on the `byval`. I guess one way to look at the problem is that the function call should take that into account and realign the stack pointer. In theory, I guess this could happen in other scenarios than ASan, but I couldn't get it to happen using an actual `alloca()` call in C/C++. The alloca for the call to `hoge` always ends up before the manual `alloca()` in the IR in my attempts.
Another way to look at it is that MyAlloca should have extra alignment based on all the allocas, including the "non interesting" ones, but that sounds hackish.
Cc: @MaskRay
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy0WFtv47oR_jXMy8CCRF1sP_ghsTeneThosTk4LfoS0NJIYiOROiTlS359MaR8y2V3gaLGAmuLw5lvZr65KMJa2SjEFcsfWL65E6NrtVk1nVCVHPu7ra6Oq2fs6pkd61qWEpUDg4PR1ViiYek9izcsvmdFPP3zP3daVvDXeGB8IZVjvIAj40uWPoRj68xYOhCdbJSwjC-KjPElPGoNbD7JAABI5UCw_CEpWL4Blm788XxzVnT93dtsdYOML0jT4dqiP6y1ZnxBlj5YOTC-JoxreDvfobPgw42q6dmNQxfRt_ePL4iC7etzgv9Z-Nai68C1CGKrdwisiGuto7IkAb4GoSoQVeUlat11ei9VA8KSYC-kCpJQawNCAR6wHJ3YdvgLicODQ6OAcb5mnEOplXVQtsIA4_cvL8IK9VJhLcbOvejBSa3sh5AadGPQUaHD0r1YJ8rXl9Hii6gdmpcgwNJNzDj_JBg_oNCJAFeC_xcyfU2pTxDckuudDjJLSfmMeR_vnIIX_5wjuh9kh7CXrqXEl51QDeMPjD_ATJNqCKSBiRIwq61Q0sk3ZOlGVJVBa2H2dw6zXuwOecJrmDWsiCP4PipFlCKCDUY3RvRQGmFbtF8R5x-TmMES5Q4roL4iOnh--u35229_Em2fselROUGsAU-hKNyND3Ecx3m-LLN8UVfLvASpvAdT0ISbfGHpfZKFS0n249Lii6ba0uVKWmEt9lQAjGdGDozIHb48JEF8M_YD6BpOkgZKXSHURvcQH26gOX37pLqEJN2w9Bt84g5L1y__Tmutd4w_8LRg6TeW3sOu1zsxWGA8f-v72ONaMJ4bO5AvXuk3Vd0Cq8Z-iN47OTD-ePDu2eF0liWe5fFhXtflvEwXyxLjT5M30XhC4xn11lMuG2kdGgsG_xqlQQtFNtseHdpQbpRO2I4OjB2g0mhBaQet2CGg0mPTXsSia0t_tNSLOtwJ5WAQxlly0Te84OYxhH8Qrv2KcDB9qBnSx8dsDbMio1-MPzL-CPWoSk-3wehONyMGQNbb8m2J0nlxSlW3yu24vVaeLPmVcoNWvqEF6Yiu4qxm5m1gBXtxPOcpiqJzSk_ae70L2pOMtJ9T55v71cFsWVyZda20IAksiK7TpSDrfhS8d5buOiObBg2-c-yzz6R_36KCqdWHzt17Oy_J1Jws-Cm0b2XZkvM-8XTrl038dC6ANgGHdIzPLejREUNq8YqTkUmTVxF9wYgpeul10nxubtIfRRGkPKQu-iJBIf3m1Hu-yOc7thTZyWhPU_xi0w9m04y-fAZawVQTwR_nc2nBOtl1t66eMMKJXsIFLgxaXurrc2Sn0n7r-702FQzOAMsfCGi-8VtP38fnGJV6OF4AOn2B7rePVwHr7_fPf4t-0Ev-aL0TwjiqA2ooeVJvxTZJs7yIscSiSPNkvq0TXJRcpHEax1W8qBMRen46n_Mk9r1fVTTeZn3X7XqYES1no8WZxzOzokZ39KsEbTzy4Osx-gCFFqpS92ih0nt18omU-QSARedOE2-qKqffhZyi8XU3Yjz__XgfrlLbPdXmgmImiwyWhY-e51_KfxC7f04T_Vdc9iV-wbxF7-T_gJLz7AKzyH4A8ymU5l4b11LfD-ET7lyzqjtCygmTGC36M39AeKcdEnaiGzHMN6FmBr3d4GgEnwbiRoalm4QSLx006C7JTYobCnyzFpWTouuOIWDSwqsMg3WvzStWsD3SmqtKhC3W2uAV7FNZDlpardDAXpClM13eVfKFP5qMWQ3niNNFmhlVWOGnOqZ2IF0ED6MDpfeXQNEwJQulsAhCHXvC5Yvphgl8fbFAvVgxPne0ujtBc0lV1FBI17VBn6mA9MNoPg-S0r-HaMqB37WKGFphQdCEGdDQ8zNRihiEUnpa73TosayIt8ed6PxW-QTNSCunVkijkRR3Wr-GPuYXzW2HPYH14NwHJLbVY1eBE684MU05DaIs9Ui7vapgIsdt0pRDE8GTf6qNj9cJimdC6bW2Yhho4CjQrkUDtkQljNQejYL7Z6HoJm07T-FKiHODxHhyZtIwBhIoEKUbRReCRHGeltQiDt5IBWvGH9dhZw_9f6JOSBB-Fn_R7cXRAqrKwjicyErCvVBfmJv2g6fv9K0_gnAO-8HZm8Tfq-D3u8zQcjMl5EyyKQ9hzzs4I663QWGxovSfX2H9Hev7iyq7sTrVDeNcaQq4Q4OW2ge9cWqF9hRnb9XqkXxtRfkqbXsDeU3vA8Cy-HdhX7-LI9xVq7Rapktxh6tknuQ8nS-z5V27Kngd1_m2Tub5IqmTtMwE8nm2wLIoiqUo7-SKxzyL83gZF_kyXkZivi2rRTwv6ipdZrxgWYy9kF1ErSjSprmT1o64WiZ5kd91Youd9X9E4VzhHvwhvd3mmzuzojuz7dhYlsWdtM5etDjpOlw9e6720l4CqRXc__mvWZ7wUPJ-VtHL3U-Xp7vRdKvWucHPAT_SG-nacRuVumf8kWxP_80Go_-DpWP80SO2jD96j_4bAAD__5cAcYw">