Skip to content

illegal load widening at O2 #11748

@kcc

Description

@kcc
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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugzillaIssues migrated from bugzilla

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions