diff options
author | LoboQ1ng <xpess@qq.com> | 2025-08-09 02:48:50 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-08-08 20:48:50 +0200 |
commit | 5bb7ba6222f7bdee30835c40f2c2bc9c98157c70 (patch) | |
tree | 86130f22ec39c4707d1192a3f5bf00299014b13c | |
parent | f35e9fa478e25266f7a72aed5cd34437c6aa7c39 (diff) | |
download | llvm-5bb7ba6222f7bdee30835c40f2c2bc9c98157c70.zip llvm-5bb7ba6222f7bdee30835c40f2c2bc9c98157c70.tar.gz llvm-5bb7ba6222f7bdee30835c40f2c2bc9c98157c70.tar.bz2 |
[analyzer] Detect use-after-free for field address (e.g., &ptr->field) (#152462)
This patch improves MallocChecker to detect use-after-free bugs when
a freed structure's field is passed by address (e.g., `&ptr->field`).
Previously, MallocChecker would miss such cases, as it only checked the
top-level symbol of argument values.
This patch analyzes the base region of arguments and extracts the
symbolic region (if any), allowing UAF detection even for field address
expressions.
Fixes #152446
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 2 | ||||
-rw-r--r-- | clang/test/Analysis/malloc-checker-arg-uaf.c | 44 |
2 files changed, 45 insertions, 1 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 369d619..efb9809 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -3156,7 +3156,7 @@ void MallocChecker::checkPreCall(const CallEvent &Call, for (unsigned I = 0, E = Call.getNumArgs(); I != E; ++I) { SVal ArgSVal = Call.getArgSVal(I); if (isa<Loc>(ArgSVal)) { - SymbolRef Sym = ArgSVal.getAsSymbol(); + SymbolRef Sym = ArgSVal.getAsSymbol(/*IncludeBaseRegions=*/true); if (!Sym) continue; if (checkUseAfterFree(Sym, C, Call.getArgExpr(I))) diff --git a/clang/test/Analysis/malloc-checker-arg-uaf.c b/clang/test/Analysis/malloc-checker-arg-uaf.c new file mode 100644 index 0000000..d6aa856 --- /dev/null +++ b/clang/test/Analysis/malloc-checker-arg-uaf.c @@ -0,0 +1,44 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc -verify %s + +#include "Inputs/system-header-simulator-for-malloc.h" + +struct Obj { + int field; +}; + +void use(void *ptr); + +void test_direct_param_uaf() { + int *p = (int *)malloc(sizeof(int)); + free(p); + use(p); // expected-warning{{Use of memory after it is released}} +} + +void test_struct_field_uaf() { + struct Obj *o = (struct Obj *)malloc(sizeof(struct Obj)); + free(o); + use(&o->field); // expected-warning{{Use of memory after it is released}} +} + +void test_no_warning_const_int() { + use((void *)0x1234); // no-warning +} + +void test_no_warning_stack() { + int x = 42; + use(&x); // no-warning +} + +void test_nested_alloc() { + struct Obj *o = (struct Obj *)malloc(sizeof(struct Obj)); + use(o); // no-warning + free(o); + use(o); // expected-warning{{Use of memory after it is released}} +} + +void test_nested_field() { + struct Obj *o = (struct Obj *)malloc(sizeof(struct Obj)); + int *f = &o->field; + free(o); + use(f); // expected-warning{{Use of memory after it is released}} +} |