https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67513
Bug ID: 67513
Summary: ASAN: Not optimal shadow value check (unlikely
condition checked in fast path)
Product: gcc
Version: 5.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: sanitizer
Assignee: unassigned at gcc dot gnu.org
Reporter: ryabinin.a.a at gmail dot com
CC: dodji at gcc dot gnu.org, dvyukov at gcc dot gnu.org,
jakub at gcc dot gnu.org, kcc at gcc dot gnu.org
Target Milestone: ---
Created attachment 36311
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=36311&action=edit
repro case
Consider following simple case:
void foo(unsigned int *a) {
*a = 0;
}
Compiling this with 'gcc -O2 -fsanitize=address asan_test.c -S -o -'
gave me the following code:
foo:
.LASANPC0:
.LFB0:
.cfi_startproc
movq %rdi, %rax
shrq $3, %rax
movzbl 2147450880(%rax), %edx
movq %rdi, %rax
andl $7, %eax
addl $3, %eax
cmpb %dl, %al
jl .L2
testb %dl, %dl
jne .L11
.L2:
movl $0, (%rdi)
ret
.L11:
pushq %rax
.cfi_def_cfa_offset 16
call __asan_report_store4
.cfi_endproc
if I read this assembly correctly, GCC did something like this:
foo(addr):
{
if (((addr & 7) + 3) < *shadow)
goto access;
if (*shadow)
report_error(addr);
access:
*a = 0
return;
}
So the problem here is that check '((addr & 7) + 3) < *shadow)' is in the
fast-path, while it should be in a slow-path (shadow value is usually zero).