[clang] [Clang] Optimize -Wunsafe-buffer-usage. (PR #125492)

Ivana Ivanovska via cfe-commits cfe-commits at lists.llvm.org
Fri Mar 7 04:53:45 PST 2025


================
@@ -1561,56 +1821,70 @@ class UnsafeLibcFunctionCallGadget : public WarningGadget {
   } WarnedFunKind = OTHERS;
 
 public:
-  UnsafeLibcFunctionCallGadget(const MatchFinder::MatchResult &Result)
+  UnsafeLibcFunctionCallGadget(const MatchResult &Result)
       : WarningGadget(Kind::UnsafeLibcFunctionCall),
-        Call(Result.Nodes.getNodeAs<CallExpr>(Tag)) {
-    if (Result.Nodes.getNodeAs<Decl>(UnsafeSprintfTag))
+        Call(Result.getNodeAs<CallExpr>(Tag)) {
+    if (Result.getNodeAs<Decl>(UnsafeSprintfTag))
       WarnedFunKind = SPRINTF;
-    else if (auto *E = Result.Nodes.getNodeAs<Expr>(UnsafeStringTag)) {
+    else if (auto *E = Result.getNodeAs<Expr>(UnsafeStringTag)) {
       WarnedFunKind = STRING;
       UnsafeArg = E;
-    } else if (Result.Nodes.getNodeAs<CallExpr>(UnsafeSizedByTag)) {
+    } else if (Result.getNodeAs<CallExpr>(UnsafeSizedByTag)) {
       WarnedFunKind = SIZED_BY;
       UnsafeArg = Call->getArg(0);
-    } else if (Result.Nodes.getNodeAs<Decl>(UnsafeVaListTag))
+    } else if (Result.getNodeAs<Decl>(UnsafeVaListTag))
       WarnedFunKind = VA_LIST;
   }
 
-  static Matcher matcher(const UnsafeBufferUsageHandler *Handler) {
-    return stmt(unless(ignoreUnsafeLibcCall(Handler)),
-      anyOf(
-        callExpr(
-            callee(functionDecl(anyOf(
-                // Match a predefined unsafe libc
-                // function:
-                functionDecl(libc_func_matchers::isPredefinedUnsafeLibcFunc()),
-                // Match a call to one of the `v*printf` functions
-                // taking va-list, which cannot be checked at
-                // compile-time:
-                functionDecl(libc_func_matchers::isUnsafeVaListPrintfFunc())
-                    .bind(UnsafeVaListTag),
-                // Match a call to a `sprintf` function, which is never
-                // safe:
-                functionDecl(libc_func_matchers::isUnsafeSprintfFunc())
-                    .bind(UnsafeSprintfTag)))),
-            //  (unless the call has a sole string literal argument):
-            unless(
-                allOf(hasArgument(0, expr(stringLiteral())), hasNumArgs(1)))),
-
-        // The following two cases require checking against actual
-        // arguments of the call:
-
-        // Match a call to an `snprintf` function. And first two
-        // arguments of the call (that describe a buffer) are not in
-        // safe patterns:
-        callExpr(callee(functionDecl(libc_func_matchers::isNormalPrintfFunc())),
-                 libc_func_matchers::hasUnsafeSnprintfBuffer())
-            .bind(UnsafeSizedByTag),
-        // Match a call to a `printf` function, which can be safe if
-        // all arguments are null-terminated:
-        callExpr(callee(functionDecl(libc_func_matchers::isNormalPrintfFunc())),
-                 libc_func_matchers::hasUnsafePrintfStringArg(
-                     expr().bind(UnsafeStringTag)))));
+  static bool matches(const Stmt *S, ASTContext &Ctx,
+                      const UnsafeBufferUsageHandler *Handler,
+                      MatchResult &Result) {
+    if (ignoreUnsafeLibcCall(Ctx, *S, Handler))
+      return false;
+    auto *CE = dyn_cast<CallExpr>(S);
+    if (!CE || !CE->getDirectCallee())
+      return false;
+    const auto *FD = dyn_cast<FunctionDecl>(CE->getDirectCallee());
+    if (!FD)
+      return false;
+    auto isSingleStringLiteralArg = false;
+    if (CE->getNumArgs() == 1) {
+      const auto *const Arg = CE->getArg(0);
+      if (isa<Expr>(Arg) && !Arg->children().empty()) {
----------------
ivanaivanovska wrote:

Done.

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


More information about the cfe-commits mailing list