<html>
<head>
<base href="http://llvm.org/bugs/" />
</head>
<body><table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Bug ID</th>
<td><a class="bz_bug_link
bz_status_NEW "
title="NEW --- - -fstack-protector + C11 atomics: binaries may crash"
href="http://llvm.org/bugs/show_bug.cgi?id=16498">16498</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>-fstack-protector + C11 atomics: binaries may crash
</td>
</tr>
<tr>
<th>Product</th>
<td>libraries
</td>
</tr>
<tr>
<th>Version</th>
<td>trunk
</td>
</tr>
<tr>
<th>Hardware</th>
<td>PC
</td>
</tr>
<tr>
<th>OS</th>
<td>FreeBSD
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Severity</th>
<td>normal
</td>
</tr>
<tr>
<th>Priority</th>
<td>P
</td>
</tr>
<tr>
<th>Component</th>
<td>Backend: X86
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>ed@80386.nl
</td>
</tr>
<tr>
<th>CC</th>
<td>llvmbugs@cs.uiuc.edu
</td>
</tr>
<tr>
<th>Classification</th>
<td>Unclassified
</td>
</tr></table>
<p>
<div>
<pre>Consider the two following separate source files:
--- Begin source file 1 ---
#include <stddef.h>
#include <string.h>
typedef struct { char data[15]; } T;
void boom(_Atomic(T) *);
int
main(void)
{
_Atomic(T) x;
T y = {};
__c11_atomic_init(&x, y);
boom(&x);
}
#pragma redefine_extname __atomic_load_c __atomic_load
void
__atomic_load_c(int size, void *src, void *dest, int model)
{
memcpy(dest, src, size);
}
--- End source file 1 ---
--- Begin source file 2 ---
typedef struct { char data[15]; } T;
void
boom(_Atomic(T) *v)
{
__c11_atomic_load(v, __ATOMIC_SEQ_CST);
}
--- End source file 2 ---
In other words, source file 1 implements atomic_load() by doing a simple
memcpy() and calls a function in another compilation unit that ends up invoking
atomic_load() for a 15-byte structure type.
If we compile these two source files as follows, the resulting binary works
correctly:
$ clang -fstack-protector -o f f1.c f2.c
$ ./f
$
Now if we compile it as follows, it breaks:
$ clang -O2 -fstack-protector -o f f1.c f2.c
$ ./f
zsh: abort (core dumped) ./f
$
When both pieces of code are placed in the same compilation unit, or if stack
protection is disabled, the code runs correctly at any optimisation level. The
boom() function is compiled to the following machine code:
--- Begin with -fstack-protector ---
0000000000000000 <boom>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 83 ec 20 sub $0x20,%rsp
8: 48 89 f8 mov %rdi,%rax
b: 48 8b 0d 00 00 00 00 mov 0x0(%rip),%rcx # 12 <boom+0x12>
12: 48 89 4d f8 mov %rcx,-0x8(%rbp)
16: 48 8d 55 e9 lea -0x17(%rbp),%rdx
1a: bf 10 00 00 00 mov $0x10,%edi
1f: 48 89 c6 mov %rax,%rsi
22: b9 05 00 00 00 mov $0x5,%ecx
27: e8 00 00 00 00 callq 2c <boom+0x2c>
2c: 48 8b 05 00 00 00 00 mov 0x0(%rip),%rax # 33 <boom+0x33>
33: 48 3b 45 f8 cmp -0x8(%rbp),%rax
37: 75 06 jne 3f <boom+0x3f>
39: 48 83 c4 20 add $0x20,%rsp
3d: 5d pop %rbp
3e: c3 retq
3f: e8 00 00 00 00 callq 44 <boom+0x44>
--- End with -fstack-protector ---
--- Begin without -fstack-protector ---
0000000000000000 <boom>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 83 ec 10 sub $0x10,%rsp
8: 48 89 f8 mov %rdi,%rax
b: 48 8d 55 f1 lea -0xf(%rbp),%rdx
f: bf 10 00 00 00 mov $0x10,%edi
14: 48 89 c6 mov %rax,%rsi
17: b9 05 00 00 00 mov $0x5,%ecx
1c: e8 00 00 00 00 callq 21 <boom+0x21>
21: 48 83 c4 10 add $0x10,%rsp
25: 5d pop %rbp
26: c3 retq
--- End without -fstack-protector ---</pre>
</div>
</p>
<hr>
<span>You are receiving this mail because:</span>
<ul>
<li>You are on the CC list for the bug.</li>
</ul>
</body>
</html>