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).

Reply via email to