[clang] [analyzer][clangsa] Add new option to alpha.security.cert.InvalidPtrChecker (PR #67663)

via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 9 04:40:03 PDT 2023


Endre =?utf-8?q?Fülöp?= <endre.fulop at sigmatechnology.se>,
Endre =?utf-8?q?Fülöp?= <endre.fulop at sigmatechnology.se>,
Endre =?utf-8?q?Fülöp?= <endre.fulop at sigmatechnology.se>,
Endre =?utf-8?q?Fülöp?= <endre.fulop at sigmatechnology.se>,
Endre =?utf-8?q?Fülöp?= <endre.fulop at sigmatechnology.se>,
Endre =?utf-8?q?Fülöp?= <endre.fulop at sigmatechnology.se>,
Endre =?utf-8?q?Fülöp?= <endre.fulop at sigmatechnology.se>,
Endre =?utf-8?q?Fülöp?= <endre.fulop at sigmatechnology.se>,
Endre =?utf-8?q?Fülöp?= <endre.fulop at sigmatechnology.se>
Message-ID:
In-Reply-To: <llvm/llvm-project/pull/67663/clang at github.com>


================
@@ -84,33 +104,70 @@ class InvalidPtrChecker
 REGISTER_SET_WITH_PROGRAMSTATE(InvalidMemoryRegions, const MemRegion *)
 
 // Stores the region of the environment pointer of 'main' (if present).
-REGISTER_TRAIT_WITH_PROGRAMSTATE(EnvPtrRegion, const MemRegion *)
+REGISTER_TRAIT_WITH_PROGRAMSTATE(MainEnvPtrRegion, const MemRegion *)
+
+// Stores the regions of environments returned by getenv calls.
+REGISTER_SET_WITH_PROGRAMSTATE(GetenvEnvPtrRegions, const MemRegion *)
 
 // Stores key-value pairs, where key is function declaration and value is
 // pointer to memory region returned by previous call of this function
 REGISTER_MAP_WITH_PROGRAMSTATE(PreviousCallResultMap, const FunctionDecl *,
                                const MemRegion *)
 
+const NoteTag *InvalidPtrChecker::createEnvInvalidationNote(
+    CheckerContext &C, ProgramStateRef State, StringRef FunctionName) const {
+
+  const MemRegion *MainRegion = State->get<MainEnvPtrRegion>();
+  const auto GetenvRegions = State->get<GetenvEnvPtrRegions>();
+
+  return C.getNoteTag([this, MainRegion, GetenvRegions,
+                       FunctionName = std::string{FunctionName}](
+                          PathSensitiveBugReport &BR, llvm::raw_ostream &Out) {
+    auto IsInterestingForInvalidation = [this, &BR](const MemRegion *R) {
+      return R && &BR.getBugType() == &InvalidPtrBugType && BR.isInteresting(R);
+    };
+
+    // Craft the note tag message.
+    llvm::SmallVector<std::string, 2> InvalidLocationNames;
+    if (IsInterestingForInvalidation(MainRegion)) {
+      InvalidLocationNames.push_back("the environment parameter of 'main'");
+    }
+    if (llvm::any_of(GetenvRegions, IsInterestingForInvalidation))
+      InvalidLocationNames.push_back("the environment returned by 'getenv'");
+
+    if (InvalidLocationNames.size() >= 1)
+      Out << '\'' << FunctionName << "' call may invalidate "
+          << InvalidLocationNames[0];
+    if (InvalidLocationNames.size() == 2)
+      Out << ", and " << InvalidLocationNames[1];
+
+    // Mark all regions that were interesting before as NOT interesting now
+    // to avoid extra notes coming from invalidation points higher up the
+    // bugpath. This ensures, that only the last invalidation point is marked
+    // with a note tag.
+    if (IsInterestingForInvalidation(MainRegion))
+      BR.markNotInteresting(MainRegion);
+    for (const MemRegion *GetenvRegion : GetenvRegions)
+      if (IsInterestingForInvalidation(GetenvRegion))
+        BR.markNotInteresting(GetenvRegion);
----------------
DonatNagyE wrote:

You can merge this check-and-loop with the check-and-loop (more precisely check-and-`any_of`) that constructs `InvalidLocationNames` to avoid unnecessary repeated calls to `IsInterestingForInvalidation`.

https://github.com/llvm/llvm-project/pull/67663


More information about the cfe-commits mailing list