[clang] [Thread Modeling]: Resolve function pointers (PR #123357)

Isaac Nudelman via cfe-commits cfe-commits at lists.llvm.org
Fri Jan 17 07:34:45 PST 2025


https://github.com/nuudlman created https://github.com/llvm/llvm-project/pull/123357

None

>From 41ec6ffe545cb7a2b25bda5dbbeed094e478f7df Mon Sep 17 00:00:00 2001
From: Isaac Nudelman <isaac.nudelman at utexas.edu>
Date: Fri, 17 Jan 2025 09:31:04 -0600
Subject: [PATCH 1/2] Declare new thread modeling checker

---
 clang/include/clang/StaticAnalyzer/Checkers/Checkers.td | 4 ++++
 clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt        | 1 +
 2 files changed, 5 insertions(+)

diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index 1361da46c3c81d..b91d6411451f02 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -383,6 +383,10 @@ def TrustReturnsNonnullChecker : Checker<"TrustReturnsNonnull">,
            "are not null">,
   Documentation<NotDocumented>;
 
+def ThreadModeling : Checker<"Thread">,
+  HelpText<"Make threaded code available to other checkers.">,
+  Documentation<NotDocumented>;
+
 } // end "apiModeling"
 
 //===----------------------------------------------------------------------===//
diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
index fcbe8b864b6e41..41df8d9321c034 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -112,6 +112,7 @@ add_clang_library(clangStaticAnalyzerCheckers
   Taint.cpp
   TaintTesterChecker.cpp
   TestAfterDivZeroChecker.cpp
+  ThreadModeling.cpp
   TraversalChecker.cpp
   TrustNonnullChecker.cpp
   TrustReturnsNonnullChecker.cpp

>From 99e07ce2b390d1071cf9cd95655f60da8203ab88 Mon Sep 17 00:00:00 2001
From: Isaac Nudelman <isaac.nudelman at utexas.edu>
Date: Fri, 17 Jan 2025 09:31:23 -0600
Subject: [PATCH 2/2] WIP Impl thread modeling checker

---
 .../Checkers/ThreadModeling.cpp               | 74 +++++++++++++++++++
 1 file changed, 74 insertions(+)
 create mode 100644 clang/lib/StaticAnalyzer/Checkers/ThreadModeling.cpp

diff --git a/clang/lib/StaticAnalyzer/Checkers/ThreadModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/ThreadModeling.cpp
new file mode 100644
index 00000000000000..d5d48a8dde69a6
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/ThreadModeling.cpp
@@ -0,0 +1,74 @@
+
+
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+
+#include <clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h>
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+// Since we are looking to extract the arguments, go with pre call for now
+class ThreadModeling : public Checker<check::PreCall> {
+
+  constexpr static CallDescriptionSet ThreadCreateCalls {
+    { CDM::CLibrary, {"pthread_create"}, 4},
+  };
+
+  const FunctionDecl *GetFunctionDecl(SVal V, CheckerContext &C) const;
+public:
+  void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
+};
+
+} // end anonymous namespace
+
+
+void ThreadModeling::checkPreCall(const CallEvent &Call, CheckerContext &C) const {
+  if (!ThreadCreateCalls.contains(Call)) {
+    return;
+  }
+
+  // 1. Get the `start_routine` argument
+  ProgramStateRef State = C.getState();
+  const FunctionDecl *CreateCall = reinterpret_cast<const FunctionDecl*>(Call.getDecl());
+
+  // 2. Extract the start_routine parameter
+  /* int pthread_create(pthread_t *restrict thread,
+                          const pthread_attr_t *restrict attr,
+                          void *(*start_routine)(void *),
+                          void *restrict arg);
+   */
+  assert(Call.getNumArgs() == 4 && "pthread_create(3) should have 4 arguments");
+  const Expr *StartRoutineExpr = Call.getArgExpr(2);
+  assert(StartRoutineExpr && "start_routine should exist"); // XXX: might fail if in diff TU?
+
+  // 3. Get the function pointer for `start_routine`
+  const SVal SRV = C.getSVal(StartRoutineExpr);
+
+  // 4. Resolve FunctionDecl
+  // 5. Get AST (single TU for now)
+  // 6. Resolve AST to Call
+  // 7. Inline Call
+
+
+}
+
+const FunctionDecl *ThreadModeling::GetFunctionDecl(SVal V, CheckerContext &C) const {
+  if (const FunctionDecl *FD = V.getAsFunctionDecl())
+    return FD;
+  return nullptr;
+}
+
+void clang::ento::registerThreadModeling(CheckerManager &Mgr) {
+  Mgr.registerChecker<ThreadModeling>();
+}
+
+bool clang::ento::shouldRegisterThreadModeling(const CheckerManager &) {
+  return true;
+}
\ No newline at end of file



More information about the cfe-commits mailing list