https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123248
Bug ID: 123248
Summary: ASan diagnostic gap at -O1 due to optimization removal
Product: gcc
Version: 13.1.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: sanitizer
Assignee: unassigned at gcc dot gnu.org
Reporter: 220246428 at seu dot edu.cn
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: ---
I am reporting a diagnostic inconsistency where AddressSanitizer fails to
surface a heap-use-after-free at -O1. While GCC reliably flags the error at
-O0, the same source exits silently with status 0 at -O1. This indicates an
interaction where optimization passes remove the buggy access before the
sanitizer instrumentation can observe it, reducing the effectiveness of ASan
coverage under typical testing configurations.
Reproducer (uaf.c):
#include <stdlib.h>
#include <stdio.h>
int main(void) {
int *a = (int*)malloc(4);
free(a);
*a = 4; // heap-use-after-free
puts("done");
return 0;
}
When compiled with -std=c11 -g -O0 -fsanitize=address -fno-omit-frame-pointer,
the binary aborts with a non-zero exit code (134) and a full ASan report.
However, at -O1, the program prints "done" and exits with status 0.
Inspecting the generated assembly (-S) reveals the root of this behavior. At
-O0, the compiler preserves the logic and emits the instrumentation:
# -O0 snippet (simplified)
call __asan_report_store4@PLT
movl $4, (%rax)
In contrast, the -O1 assembly reveals that the entire sequence—including the
malloc, free, and the subsequent movl $4, (%rax) store—is completely excised
from the main function. The resulting binary proceeds directly to the puts
call.