[clang] [clang][analyzer] Fix false positive in StdLibraryFunctionsChecker for mmap with MAP_ANON (PR #219568)
Daniel M. Zimmerman via cfe-commits
cfe-commits at lists.llvm.org
Mon Aug 31 08:56:33 PDT 2026
https://github.com/dmzimmerman updated https://github.com/llvm/llvm-project/pull/219568
>From 1ddc39c9b90563ebd3ce221357d5b421dcfe3257 Mon Sep 17 00:00:00 2001
From: "Daniel M. Zimmerman" <dmzimmerman at apple.com>
Date: Fri, 28 Aug 2026 12:49:17 -0700
Subject: [PATCH 1/4] [clang][analyzer] Fix false positive in mmap fd
constraint on Darwin
On Darwin, mmap acccepts a Mach VM tag encoded in the fd argument when
MAP_ANON is set, using VM_MAKE_TAG(tag). For some tags, VM_MAKE_TAG
produces a large negative signed integer, which causes a false positive
with the current Range(-1, IntMax) constraint for fd.
Fixed by omitting the fd constraint on Darwin targets, where the set
of valid fd values can't be expressed as a simple range.
Assisted-by: Claude:claude-4.6-sonnet
Signed-off-by: Daniel M. Zimmerman <dmzimmerman at apple.com>
rdar://185124909
---
.../Checkers/StdLibraryFunctionsChecker.cpp | 33 ++++++++++++++-----
clang/test/Analysis/mmap-vm-make-tag.c | 30 +++++++++++++++++
2 files changed, 54 insertions(+), 9 deletions(-)
create mode 100644 clang/test/Analysis/mmap-vm-make-tag.c
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
index 3f027025fd25e..556a92911e96c 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -41,6 +41,7 @@
//===----------------------------------------------------------------------===//
#include "ErrnoModeling.h"
+#include "clang/Basic/TargetInfo.h"
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
@@ -2950,15 +2951,29 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
// void *mmap(void *addr, size_t length, int prot, int flags, int fd,
// off_t offset);
// FIXME: Improve for errno modeling.
- addToFunctionSummaryMap(
- "mmap",
- Signature(
- ArgTypes{VoidPtrTy, SizeTyCanonTy, IntTy, IntTy, IntTy, Off_tTy},
- RetType{VoidPtrTy}),
- Summary(NoEvalCall)
- .ArgConstraint(ArgumentCondition(1, WithinRange, Range(1, SizeMax)))
- .ArgConstraint(
- ArgumentCondition(4, WithinRange, Range(-1, IntMax))));
+ if (ACtx.getTargetInfo().getTriple().isOSDarwin()) {
+ // On Darwin, MAP_ANON + VM_MAKE_TAG(tag) uses argument 4 (len) for
+ // the tag, which looks like a large negative signed integer. The
+ // valid range for fd is not expressible as a simple union of ranges
+ // so omit the constraint.
+ addToFunctionSummaryMap("mmap",
+ Signature(ArgTypes{VoidPtrTy, SizeTyCanonTy,
+ IntTy, IntTy, IntTy, Off_tTy},
+ RetType{VoidPtrTy}),
+ Summary(NoEvalCall)
+ .ArgConstraint(ArgumentCondition(
+ 1, WithinRange, Range(1, SizeMax))));
+ } else {
+ addToFunctionSummaryMap("mmap",
+ Signature(ArgTypes{VoidPtrTy, SizeTyCanonTy,
+ IntTy, IntTy, IntTy, Off_tTy},
+ RetType{VoidPtrTy}),
+ Summary(NoEvalCall)
+ .ArgConstraint(ArgumentCondition(
+ 1, WithinRange, Range(1, SizeMax)))
+ .ArgConstraint(ArgumentCondition(
+ 4, WithinRange, Range(-1, IntMax))));
+ }
std::optional<QualType> Off64_tTy = lookupTy("off64_t");
// void *mmap64(void *addr, size_t length, int prot, int flags, int fd,
diff --git a/clang/test/Analysis/mmap-vm-make-tag.c b/clang/test/Analysis/mmap-vm-make-tag.c
new file mode 100644
index 0000000000000..cef5cf0e0b9c9
--- /dev/null
+++ b/clang/test/Analysis/mmap-vm-make-tag.c
@@ -0,0 +1,30 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=unix.StdCLibraryFunctions \
+// RUN: -analyzer-config unix.StdCLibraryFunctions:ModelPOSIX=true \
+// RUN: -triple arm64-apple-darwin -verify=darwin %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=unix.StdCLibraryFunctions \
+// RUN: -analyzer-config unix.StdCLibraryFunctions:ModelPOSIX=true \
+// RUN: -triple x86_64-unknown-linux-gnu -verify=linux %s
+
+typedef unsigned long size_t;
+typedef long off_t;
+void *mmap(void *, size_t, int, int, int, off_t);
+
+#define MAP_PRIVATE 0x0002
+#define MAP_ANON 0x1000
+
+// VM_MAKE_TAG on Darwin encodes a Mach VM memory tag in the top 8 bits.
+// For tags >= 128 the result is a large negative signed integer.
+#define VM_MAKE_TAG(tag) ((int)((unsigned)(tag) << 24))
+#define VM_MEMORY_APPLICATION_SPECIFIC_1 240
+
+void test_mmap_vm_make_tag_no_false_positive(void) {
+ void *p = mmap(0, 4096, 0, MAP_ANON | MAP_PRIVATE,
+ VM_MAKE_TAG(VM_MEMORY_APPLICATION_SPECIFIC_1), 0);
+ // linux-warning at -2 {{should be >= -1}}
+}
+
+void test_size_constraint_still_enforced(void) {
+ void *p = mmap(0, 0, 0, MAP_ANON | MAP_PRIVATE, -1, 0);
+ // darwin-warning at -1 {{should be > 0}}
+ // linux-warning at -2 {{should be > 0}}
+}
>From 32cb5576265416c0605165b3eaa79b4be1123d5f Mon Sep 17 00:00:00 2001
From: "Daniel M. Zimmerman" <dmzimmerman at apple.com>
Date: Fri, 28 Aug 2026 16:12:26 -0700
Subject: [PATCH 2/4] fix: address review comments
---
.../Checkers/StdLibraryFunctionsChecker.cpp | 39 +++++++++----------
clang/test/Analysis/mmap-vm-make-tag.c | 30 --------------
.../test/Analysis/stdlibraryfunction-darwin.c | 31 +++++++++++++++
3 files changed, 50 insertions(+), 50 deletions(-)
delete mode 100644 clang/test/Analysis/mmap-vm-make-tag.c
create mode 100644 clang/test/Analysis/stdlibraryfunction-darwin.c
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
index 556a92911e96c..34df77c82a102 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -2950,29 +2950,28 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
// void *mmap(void *addr, size_t length, int prot, int flags, int fd,
// off_t offset);
- // FIXME: Improve for errno modeling.
+ // FIXME: Improve for errno modeling
+ auto MmapSignature = Signature(
+ ArgTypes{VoidPtrTy, SizeTyCanonTy, IntTy, IntTy, IntTy, Off_tTy},
+ RetType{VoidPtrTy});
+ auto MmapSummaryWithLengthConstraint =
+ Summary(NoEvalCall)
+ .ArgConstraint(
+ ArgumentCondition(1, WithinRange, Range(1, SizeMax)));
+
if (ACtx.getTargetInfo().getTriple().isOSDarwin()) {
// On Darwin, MAP_ANON + VM_MAKE_TAG(tag) uses argument 4 (len) for
- // the tag, which looks like a large negative signed integer. The
- // valid range for fd is not expressible as a simple union of ranges
- // so omit the constraint.
- addToFunctionSummaryMap("mmap",
- Signature(ArgTypes{VoidPtrTy, SizeTyCanonTy,
- IntTy, IntTy, IntTy, Off_tTy},
- RetType{VoidPtrTy}),
- Summary(NoEvalCall)
- .ArgConstraint(ArgumentCondition(
- 1, WithinRange, Range(1, SizeMax))));
+ // the tag, which looks like a large negative signed integer.
+ // The valid range for fd is not expressible as a simple union of
+ // ranges so we only constrain the length parameter.
+ addToFunctionSummaryMap("mmap", MmapSignature,
+ MmapSummaryWithLengthConstraint);
} else {
- addToFunctionSummaryMap("mmap",
- Signature(ArgTypes{VoidPtrTy, SizeTyCanonTy,
- IntTy, IntTy, IntTy, Off_tTy},
- RetType{VoidPtrTy}),
- Summary(NoEvalCall)
- .ArgConstraint(ArgumentCondition(
- 1, WithinRange, Range(1, SizeMax)))
- .ArgConstraint(ArgumentCondition(
- 4, WithinRange, Range(-1, IntMax))));
+ // On other platforms, we also constrain the fd parameter (-1 <= fd).
+ addToFunctionSummaryMap(
+ "mmap", MmapSignature,
+ MmapSummaryWithLengthConstraint.ArgConstraint(
+ ArgumentCondition(4, WithinRange, Range(-1, IntMax))));
}
std::optional<QualType> Off64_tTy = lookupTy("off64_t");
diff --git a/clang/test/Analysis/mmap-vm-make-tag.c b/clang/test/Analysis/mmap-vm-make-tag.c
deleted file mode 100644
index cef5cf0e0b9c9..0000000000000
--- a/clang/test/Analysis/mmap-vm-make-tag.c
+++ /dev/null
@@ -1,30 +0,0 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=unix.StdCLibraryFunctions \
-// RUN: -analyzer-config unix.StdCLibraryFunctions:ModelPOSIX=true \
-// RUN: -triple arm64-apple-darwin -verify=darwin %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=unix.StdCLibraryFunctions \
-// RUN: -analyzer-config unix.StdCLibraryFunctions:ModelPOSIX=true \
-// RUN: -triple x86_64-unknown-linux-gnu -verify=linux %s
-
-typedef unsigned long size_t;
-typedef long off_t;
-void *mmap(void *, size_t, int, int, int, off_t);
-
-#define MAP_PRIVATE 0x0002
-#define MAP_ANON 0x1000
-
-// VM_MAKE_TAG on Darwin encodes a Mach VM memory tag in the top 8 bits.
-// For tags >= 128 the result is a large negative signed integer.
-#define VM_MAKE_TAG(tag) ((int)((unsigned)(tag) << 24))
-#define VM_MEMORY_APPLICATION_SPECIFIC_1 240
-
-void test_mmap_vm_make_tag_no_false_positive(void) {
- void *p = mmap(0, 4096, 0, MAP_ANON | MAP_PRIVATE,
- VM_MAKE_TAG(VM_MEMORY_APPLICATION_SPECIFIC_1), 0);
- // linux-warning at -2 {{should be >= -1}}
-}
-
-void test_size_constraint_still_enforced(void) {
- void *p = mmap(0, 0, 0, MAP_ANON | MAP_PRIVATE, -1, 0);
- // darwin-warning at -1 {{should be > 0}}
- // linux-warning at -2 {{should be > 0}}
-}
diff --git a/clang/test/Analysis/stdlibraryfunction-darwin.c b/clang/test/Analysis/stdlibraryfunction-darwin.c
new file mode 100644
index 0000000000000..55d8c15d72978
--- /dev/null
+++ b/clang/test/Analysis/stdlibraryfunction-darwin.c
@@ -0,0 +1,31 @@
+// DEFINE: %{analyze} = %clang_analyze_cc1 \
+// DEFINE: -analyzer-checker=core,unix.StdCLibraryFunctions \
+// DEFINE: -analyzer-config unix.StdCLibraryFunctions:ModelPOSIX=true
+
+// RUN: %{analyze} -triple arm64-apple-darwin -verify=darwin %s
+// RUN: %{analyze} -triple x86_64-unknown-linux-gnu -verify=linux %s
+
+typedef unsigned long size_t;
+typedef long off_t;
+void *mmap(void *, size_t, int, int, int, off_t);
+
+#define MAP_PRIVATE 0x0002
+#define MAP_ANON 0x1000
+
+// VM_MAKE_TAG on Darwin encodes a Mach VM memory tag in the top 8 bits.
+// For tags >= 128 the result is a large negative signed integer.
+#define VM_MAKE_TAG(tag) ((int)((unsigned)(tag) << 24))
+#define VM_MEMORY_APPLICATION_SPECIFIC_1 240
+
+void test_mmap_vm_make_tag(void) {
+ void *p = mmap(0, 4096, 0, MAP_ANON | MAP_PRIVATE,
+ VM_MAKE_TAG(VM_MEMORY_APPLICATION_SPECIFIC_1), 0);
+ // darwin-no-warning: no bound restriction on fd parameter on Darwin
+ // linux-warning at -3 {{The 5th argument to 'mmap' is -268435456 but should be >= -1}}
+}
+
+void test_mmap_size_constraint(void) {
+ void *p = mmap(0, 0, 0, MAP_ANON | MAP_PRIVATE, -1, 0);
+ // darwin-warning at -1 {{The 2nd argument to 'mmap' is 0 but should be > 0}}
+ // linux-warning at -2 {{The 2nd argument to 'mmap' is 0 but should be > 0}}
+}
>From 133687a112f28b61a586caa2495bb98487c6bbe7 Mon Sep 17 00:00:00 2001
From: "Daniel M. Zimmerman" <dmz at acm.org>
Date: Mon, 31 Aug 2026 08:56:09 -0700
Subject: [PATCH 3/4] Update
clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: Balázs Benics <benicsbalazs at gmail.com>
---
.../lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
index 34df77c82a102..f6a6e535f7638 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -2950,7 +2950,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
// void *mmap(void *addr, size_t length, int prot, int flags, int fd,
// off_t offset);
- // FIXME: Improve for errno modeling
+ // FIXME: Improve for errno modeling.
auto MmapSignature = Signature(
ArgTypes{VoidPtrTy, SizeTyCanonTy, IntTy, IntTy, IntTy, Off_tTy},
RetType{VoidPtrTy});
>From 7bf2c0b273fe8fd95ac4a780234386bc1152f246 Mon Sep 17 00:00:00 2001
From: "Daniel M. Zimmerman" <dmz at acm.org>
Date: Mon, 31 Aug 2026 08:56:23 -0700
Subject: [PATCH 4/4] Update clang/test/Analysis/stdlibraryfunction-darwin.c
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: Balázs Benics <benicsbalazs at gmail.com>
---
clang/test/Analysis/stdlibraryfunction-darwin.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/test/Analysis/stdlibraryfunction-darwin.c b/clang/test/Analysis/stdlibraryfunction-darwin.c
index 55d8c15d72978..be14236eef0b6 100644
--- a/clang/test/Analysis/stdlibraryfunction-darwin.c
+++ b/clang/test/Analysis/stdlibraryfunction-darwin.c
@@ -18,10 +18,10 @@ void *mmap(void *, size_t, int, int, int, off_t);
#define VM_MEMORY_APPLICATION_SPECIFIC_1 240
void test_mmap_vm_make_tag(void) {
+ // darwin-no-warning: no bound restriction on fd parameter on Darwin
+ // linux-warning at +1 {{The 5th argument to 'mmap' is -268435456 but should be >= -1}}
void *p = mmap(0, 4096, 0, MAP_ANON | MAP_PRIVATE,
VM_MAKE_TAG(VM_MEMORY_APPLICATION_SPECIFIC_1), 0);
- // darwin-no-warning: no bound restriction on fd parameter on Darwin
- // linux-warning at -3 {{The 5th argument to 'mmap' is -268435456 but should be >= -1}}
}
void test_mmap_size_constraint(void) {
More information about the cfe-commits
mailing list