Author: Daniel M. Zimmerman Date: 2026-09-01T05:52:11-04:00 New Revision: af6ae639c296e3ab141b0ee755eb669945411810
URL: https://github.com/llvm/llvm-project/commit/af6ae639c296e3ab141b0ee755eb669945411810 DIFF: https://github.com/llvm/llvm-project/commit/af6ae639c296e3ab141b0ee755eb669945411810.diff LOG: [clang][analyzer] Fix false positive in StdLibraryFunctionsChecker for mmap with MAP_ANON (#219568) On Darwin,`mmap(2)` acccepts a Mach VM tag encoded in the fd argument when `MAP_ANON` is set; the encoding is done using `VM_MAKE_TAG(tag)`, which expands to `(tag << 24)` and is therefore a large negative signed value for tags >= 128. This causes a false positive with the existing constraint, which restricts `fd` to be >= 1, when code uses a `VM_MAKE_TAG` value as the `fd` argument. The fix here is to eliminate the false positive by omitting the `fd` constraint on Darwin targets, because it can't be expressed as a simple range. This does give rise to false negatives (any `fd` < -1 on Darwin when `MAP_ANON` is not set), but any code with such a false negative would crash immediately when trying to use the invalid file descriptor, rather than exhibiting some more subtle dangerous behavior. AI disclosure: I used Claude Sonnet 4.6 to help diagnose the original false positive and suggest possible fixes. rdar://185124909 Added: clang/test/Analysis/stdlibraryfunction-darwin.c Modified: clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp Removed: ################################################################################ diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp index 3f027025fd25e..f6a6e535f7638 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,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. - addToFunctionSummaryMap( - "mmap", - Signature( - ArgTypes{VoidPtrTy, SizeTyCanonTy, IntTy, IntTy, IntTy, Off_tTy}, - RetType{VoidPtrTy}), + auto MmapSignature = Signature( + ArgTypes{VoidPtrTy, SizeTyCanonTy, IntTy, IntTy, IntTy, Off_tTy}, + RetType{VoidPtrTy}); + auto MmapSummaryWithLengthConstraint = Summary(NoEvalCall) - .ArgConstraint(ArgumentCondition(1, WithinRange, Range(1, SizeMax))) .ArgConstraint( - ArgumentCondition(4, WithinRange, Range(-1, IntMax)))); + 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 we only constrain the length parameter. + addToFunctionSummaryMap("mmap", MmapSignature, + MmapSummaryWithLengthConstraint); + } else { + // 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"); // void *mmap64(void *addr, size_t length, int prot, int flags, int fd, diff --git a/clang/test/Analysis/stdlibraryfunction-darwin.c b/clang/test/Analysis/stdlibraryfunction-darwin.c new file mode 100644 index 0000000000000..50ed68e6325de --- /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) { + // darwin-no-warning: no bound restriction on fd parameter on Darwin + // linux-warning@+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); +} + +void test_mmap_size_constraint(void) { + void *p = mmap(0, 0, 0, MAP_ANON | MAP_PRIVATE, -1, 0); + // darwin-warning@-1 {{The 2nd argument to 'mmap' is 0 but should be > 0}} + // linux-warning@-2 {{The 2nd argument to 'mmap' is 0 but should be > 0}} +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
