https://github.com/steakhal updated https://github.com/llvm/llvm-project/pull/152462
>From 909f0bce1aec9939eeecdaa8c3f0a028f89d96f4 Mon Sep 17 00:00:00 2001 From: LoboQ1ng <xp...@qq.com> Date: Thu, 7 Aug 2025 16:52:39 +0800 Subject: [PATCH 1/5] [StaticAnalyzer] [MallocChecker] Detect use-after-free for field address (e.g., &ptr->field) --- clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 369d6194dbb65..ad1d20779f384 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -3156,8 +3156,14 @@ 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(); - if (!Sym) + const MemRegion *MR = ArgSVal.getAsRegion(); + if (!MR) + continue; + const MemRegion *BaseRegion = MR->getBaseRegion(); + SymbolRef Sym = nullptr; + if (const auto *SR = dyn_cast<SymbolicRegion>(BaseRegion)) + Sym = SR->getSymbol(); + if (!Sym) continue; if (checkUseAfterFree(Sym, C, Call.getArgExpr(I))) return; >From a19a454b4940b0bc12c765a358eb09088f9f9e46 Mon Sep 17 00:00:00 2001 From: LoboQ1ng <xp...@qq.com> Date: Thu, 7 Aug 2025 19:19:15 +0800 Subject: [PATCH 2/5] add test case --- clang/test/Analysis/malloc-checker-arg-uaf.c | 44 ++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 clang/test/Analysis/malloc-checker-arg-uaf.c 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 0000000000000..54cfe6633910c --- /dev/null +++ b/clang/test/Analysis/malloc-checker-arg-uaf.c @@ -0,0 +1,44 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=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 freed}} +} + +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 freed}} +} + +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 freed}} +} + +void test_nested_field() { + struct Obj *o = malloc(sizeof(struct Obj)); + int *f = &o->field; + free(o); + use(f); // expected-warning{{Use of memory after it is freed}} +} \ No newline at end of file >From dbcf8b4d84a9fad6a2b865cf20751339ff96c2c7 Mon Sep 17 00:00:00 2001 From: LoboQ1ng <xp...@qq.com> Date: Fri, 8 Aug 2025 10:14:58 +0800 Subject: [PATCH 3/5] Update clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: DonĂ¡t Nagy <donat.n...@ericsson.com> --- clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index ad1d20779f384..fb7e80f06385d 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -3156,13 +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)) { - const MemRegion *MR = ArgSVal.getAsRegion(); - if (!MR) - continue; - const MemRegion *BaseRegion = MR->getBaseRegion(); - SymbolRef Sym = nullptr; - if (const auto *SR = dyn_cast<SymbolicRegion>(BaseRegion)) - Sym = SR->getSymbol(); + SymbolRef Sym = ArgSVal.getAsSymbol(/*IncludeBaseRegions=*/true); if (!Sym) continue; if (checkUseAfterFree(Sym, C, Call.getArgExpr(I))) >From 11715c0a6e8cb982320a9d102fda24ae0553e571 Mon Sep 17 00:00:00 2001 From: Balazs Benics <benicsbal...@gmail.com> Date: Fri, 8 Aug 2025 19:21:33 +0200 Subject: [PATCH 4/5] Apply suggestions from code review --- clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 2 +- clang/test/Analysis/malloc-checker-arg-uaf.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index fb7e80f06385d..efb980962e811 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -3157,7 +3157,7 @@ void MallocChecker::checkPreCall(const CallEvent &Call, SVal ArgSVal = Call.getArgSVal(I); if (isa<Loc>(ArgSVal)) { SymbolRef Sym = ArgSVal.getAsSymbol(/*IncludeBaseRegions=*/true); - if (!Sym) + if (!Sym) continue; if (checkUseAfterFree(Sym, C, Call.getArgExpr(I))) return; diff --git a/clang/test/Analysis/malloc-checker-arg-uaf.c b/clang/test/Analysis/malloc-checker-arg-uaf.c index 54cfe6633910c..d48178ebf09bd 100644 --- a/clang/test/Analysis/malloc-checker-arg-uaf.c +++ b/clang/test/Analysis/malloc-checker-arg-uaf.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=unix.Malloc -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc -verify %s #include "Inputs/system-header-simulator-for-malloc.h" @@ -37,8 +37,8 @@ void test_nested_alloc() { } void test_nested_field() { - struct Obj *o = malloc(sizeof(struct Obj)); + 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 freed}} -} \ No newline at end of file +} >From 57736541a29007703afbe106c78ed92ac15ec18c Mon Sep 17 00:00:00 2001 From: Balazs Benics <benicsbal...@gmail.com> Date: Fri, 8 Aug 2025 20:15:46 +0200 Subject: [PATCH 5/5] Apply suggestions from code review --- clang/test/Analysis/malloc-checker-arg-uaf.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clang/test/Analysis/malloc-checker-arg-uaf.c b/clang/test/Analysis/malloc-checker-arg-uaf.c index d48178ebf09bd..d6aa85657fd46 100644 --- a/clang/test/Analysis/malloc-checker-arg-uaf.c +++ b/clang/test/Analysis/malloc-checker-arg-uaf.c @@ -11,13 +11,13 @@ 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 freed}} + 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 freed}} + use(&o->field); // expected-warning{{Use of memory after it is released}} } void test_no_warning_const_int() { @@ -33,12 +33,12 @@ 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 freed}} + 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 freed}} + use(f); // expected-warning{{Use of memory after it is released}} } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits