https://github.com/NagyDonat updated https://github.com/llvm/llvm-project/pull/237447
From 0f0c9c0af0256813b2ef9ab78f15a68085f468f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <[email protected]> Date: Sat, 31 Oct 2026 01:14:07 +0100 Subject: [PATCH 1/2] [analyzer] MallocChecker: don't crash on funny funopen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The method mayFreeAnyEscapedMemoryOrIsModeledExplicitly implemented a heuristic for handling "funopen", but only checked that the call has at least 4 arguments before accessing the fifth (index 4) one. This off-by-one error could cause a crash in the theoretical case when a system header had a nonstandard 4-argument function named "funopen". I'm pretty sure that nobody encountered this in the wild since 2012 when it was added. The bug was noticed by a Claude review of a PR that touched nearby code; but this change is written by hand. Reported-by: Balázs Benics <[email protected]> --- clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 2 +- .../Inputs/system-header-simulator-funny-funopen.h | 11 +++++++++++ clang/test/Analysis/malloc-funny-funopen.c | 11 +++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 clang/test/Analysis/Inputs/system-header-simulator-funny-funopen.h create mode 100644 clang/test/Analysis/malloc-funny-funopen.c diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index ccd8e4efabcce2..ee83afb8ab5457 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -3830,7 +3830,7 @@ bool MallocChecker::mayFreeAnyEscapedMemoryOrIsModeledExplicitly( // but it will not if closefn is not specified. // Currently, we do not inspect the 'closefn' function (PR12101). if (FName == "funopen") - if (Call->getNumArgs() >= 4 && Call->getArgSVal(4).isConstant(0)) + if (Call->getNumArgs() >= 5 && Call->getArgSVal(4).isConstant(0)) return false; // Do not warn on pointers passed to 'setbuf' when used with std streams, diff --git a/clang/test/Analysis/Inputs/system-header-simulator-funny-funopen.h b/clang/test/Analysis/Inputs/system-header-simulator-funny-funopen.h new file mode 100644 index 00000000000000..efbaa28b159928 --- /dev/null +++ b/clang/test/Analysis/Inputs/system-header-simulator-funny-funopen.h @@ -0,0 +1,11 @@ +#pragma clang system_header + +// A non-standard function named "funopen" with four parameters: +void funopen(int *, int *, int *, int *); + +// Note that standard funopen() has five parameters: +//FILE *funopen(const void *cookie, +// int (*readfn)(void *, char *, int), +// int (*writefn)(void *, const char *, int), +// off_t (*seekfn)(void *, off_t, int), +// int (*closefn)(void *)); diff --git a/clang/test/Analysis/malloc-funny-funopen.c b/clang/test/Analysis/malloc-funny-funopen.c new file mode 100644 index 00000000000000..8e9dd0060712e8 --- /dev/null +++ b/clang/test/Analysis/malloc-funny-funopen.c @@ -0,0 +1,11 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=unix.Malloc -verify %s +#include "Inputs/system-header-simulator-funny-funopen.h" + +// expected-no-diagnostics + +// Standard funopen() has 5 parameters; but if a system header contained a +// nonstandard declaration with only 4 parameters, then calling that used to +// trigger an assertion failure through MallocChecker. +void use_funny_funopen(int *a, int *b, int *c, int *d) { + funopen(a, b, c, d); // no-crash +} From b7fdb11f35003c1f163e5b937e07b91c200d8d83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <[email protected]> Date: Mon, 2 Nov 2026 13:12:30 +0100 Subject: [PATCH 2/2] Use split-file instead of single-use system header simulator --- .../system-header-simulator-funny-funopen.h | 11 ------- clang/test/Analysis/malloc-funny-funopen.c | 29 +++++++++++++++---- 2 files changed, 24 insertions(+), 16 deletions(-) delete mode 100644 clang/test/Analysis/Inputs/system-header-simulator-funny-funopen.h diff --git a/clang/test/Analysis/Inputs/system-header-simulator-funny-funopen.h b/clang/test/Analysis/Inputs/system-header-simulator-funny-funopen.h deleted file mode 100644 index efbaa28b159928..00000000000000 --- a/clang/test/Analysis/Inputs/system-header-simulator-funny-funopen.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma clang system_header - -// A non-standard function named "funopen" with four parameters: -void funopen(int *, int *, int *, int *); - -// Note that standard funopen() has five parameters: -//FILE *funopen(const void *cookie, -// int (*readfn)(void *, char *, int), -// int (*writefn)(void *, const char *, int), -// off_t (*seekfn)(void *, off_t, int), -// int (*closefn)(void *)); diff --git a/clang/test/Analysis/malloc-funny-funopen.c b/clang/test/Analysis/malloc-funny-funopen.c index 8e9dd0060712e8..3d92de9e67aad9 100644 --- a/clang/test/Analysis/malloc-funny-funopen.c +++ b/clang/test/Analysis/malloc-funny-funopen.c @@ -1,11 +1,30 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=unix.Malloc -verify %s -#include "Inputs/system-header-simulator-funny-funopen.h" +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t + +// RUN: %clang_analyze_cc1 -analyzer-checker=unix.Malloc -verify %t/source.c + +//--- header.h + +#pragma clang system_header + +// A non-standard function named "funopen" with four parameters: +void funopen(int *, int *, int *, int *); + +// Note that standard funopen() has five parameters: +//FILE *funopen(const void *cookie, +// int (*readfn)(void *, char *, int), +// int (*writefn)(void *, const char *, int), +// off_t (*seekfn)(void *, off_t, int), +// int (*closefn)(void *)); + +//--- source.c + +#include "header.h" // expected-no-diagnostics -// Standard funopen() has 5 parameters; but if a system header contained a -// nonstandard declaration with only 4 parameters, then calling that used to -// trigger an assertion failure through MallocChecker. +// This used to trigger an assertion failure through MallocChecker. void use_funny_funopen(int *a, int *b, int *c, int *d) { funopen(a, b, c, d); // no-crash } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
