-
Notifications
You must be signed in to change notification settings - Fork 15.3k
Description
| Bugzilla Link | 11376 |
| Resolution | FIXED |
| Resolved on | Dec 08, 2011 21:38 |
| Version | trunk |
| OS | Linux |
| CC | @chandlerc,@lattner,@efriedma-quic |
Extended Description
Three one-byte loads are illegally combined into one 4-byte load
Observed on r144590
The test below triggers SEGV, but the bug is obvious from disassembly.
% cat t.cc
#include <sys/mman.h>
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
inline char Check(const char& v) {
return v ? 1 : 0;
}
__attribute((noinline))
char foo(char *X) {
return Check(X[0]) | Check(X[1]) | Check(X[2]);
}
static const int kPageSize = 4096;
int main() {
// poor man's electric fence:
// allocate two pages and lock the second one.
char mem = (char)mmap(0, kPageSize * 2, PROT_READ | PROT_WRITE,
MAP_PRIVATE|MAP_ANON, 0, 0);
assert(mem != (char*)-1);
mprotect(mem + kPageSize, kPageSize, PROT_NONE);
fprintf(stderr, "mem = %p\n", mem);
char *X = mem + kPageSize - 3;
fprintf(stderr, "X = %p\n", X);
// We can access X[0], X[1], X[2], but not X[3].
char res = foo(X);
fprintf(stderr, "PASSED %d\n", res);
}
% clang++ t.cc -O2 ; ./a.out
mem = 0x7f1313ca0000
X = 0x7f1313ca0ffd
Segmentation fault
00000000004006b0 <_Z3fooPc>:
4006b0: 8b 07 mov (%rdi),%eax <<<<<<<<<<<<<<<
4006b2: 89 c1 mov %eax,%ecx
4006b4: c1 e9 08 shr $0x8,%ecx
4006b7: 09 c1 or %eax,%ecx
4006b9: c1 e8 10 shr $0x10,%eax
4006bc: 08 c8 or %cl,%al
4006be: 0f 95 c0 setne %al
4006c1: 0f b6 c0 movzbl %al,%eax
4006c4: c3 retq
4006c5: 66 66 2e 0f 1f 84 00 nopw %cs:0x0(%rax,%rax,1)
4006cc: 00 00 00 00
The same test passes at O1.