[clang] [clang][analyzer] Support `fprintf` in the SecuritySyntaxChecker (PR #73247)

Ben Shi via cfe-commits cfe-commits at lists.llvm.org
Thu Nov 23 07:07:36 PST 2023


https://github.com/benshi001 updated https://github.com/llvm/llvm-project/pull/73247

>From 34603a920d5b3ce462c85980c4abff912c1bb22a Mon Sep 17 00:00:00 2001
From: Ben Shi <bennshi at tencent.com>
Date: Thu, 23 Nov 2023 18:22:14 +0800
Subject: [PATCH] [clang][analyzer] Support `fprintf` in the
 SecuritySyntaxChecker

---
 .../Checkers/CheckSecuritySyntaxOnly.cpp      | 76 ++++++++++---------
 clang/test/Analysis/security-syntax-checks.c  | 15 +++-
 2 files changed, 51 insertions(+), 40 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp b/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
index 1a88615f01697cb..dbba12bb4355c3a 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
@@ -144,38 +144,39 @@ void WalkAST::VisitCallExpr(CallExpr *CE) {
     Name = Name.substr(10);
 
   // Set the evaluation function by switching on the callee name.
-  FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name)
-    .Case("bcmp", &WalkAST::checkCall_bcmp)
-    .Case("bcopy", &WalkAST::checkCall_bcopy)
-    .Case("bzero", &WalkAST::checkCall_bzero)
-    .Case("gets", &WalkAST::checkCall_gets)
-    .Case("getpw", &WalkAST::checkCall_getpw)
-    .Case("mktemp", &WalkAST::checkCall_mktemp)
-    .Case("mkstemp", &WalkAST::checkCall_mkstemp)
-    .Case("mkdtemp", &WalkAST::checkCall_mkstemp)
-    .Case("mkstemps", &WalkAST::checkCall_mkstemp)
-    .Cases("strcpy", "__strcpy_chk", &WalkAST::checkCall_strcpy)
-    .Cases("strcat", "__strcat_chk", &WalkAST::checkCall_strcat)
-    .Cases("sprintf", "vsprintf", "scanf", "wscanf", "fscanf", "fwscanf",
-           "vscanf", "vwscanf", "vfscanf", "vfwscanf",
-           &WalkAST::checkDeprecatedOrUnsafeBufferHandling)
-    .Cases("sscanf", "swscanf", "vsscanf", "vswscanf", "swprintf",
-           "snprintf", "vswprintf", "vsnprintf", "memcpy", "memmove",
-           &WalkAST::checkDeprecatedOrUnsafeBufferHandling)
-    .Cases("strncpy", "strncat", "memset",
-           &WalkAST::checkDeprecatedOrUnsafeBufferHandling)
-    .Case("drand48", &WalkAST::checkCall_rand)
-    .Case("erand48", &WalkAST::checkCall_rand)
-    .Case("jrand48", &WalkAST::checkCall_rand)
-    .Case("lrand48", &WalkAST::checkCall_rand)
-    .Case("mrand48", &WalkAST::checkCall_rand)
-    .Case("nrand48", &WalkAST::checkCall_rand)
-    .Case("lcong48", &WalkAST::checkCall_rand)
-    .Case("rand", &WalkAST::checkCall_rand)
-    .Case("rand_r", &WalkAST::checkCall_rand)
-    .Case("random", &WalkAST::checkCall_random)
-    .Case("vfork", &WalkAST::checkCall_vfork)
-    .Default(nullptr);
+  FnCheck evalFunction =
+      llvm::StringSwitch<FnCheck>(Name)
+          .Case("bcmp", &WalkAST::checkCall_bcmp)
+          .Case("bcopy", &WalkAST::checkCall_bcopy)
+          .Case("bzero", &WalkAST::checkCall_bzero)
+          .Case("gets", &WalkAST::checkCall_gets)
+          .Case("getpw", &WalkAST::checkCall_getpw)
+          .Case("mktemp", &WalkAST::checkCall_mktemp)
+          .Case("mkstemp", &WalkAST::checkCall_mkstemp)
+          .Case("mkdtemp", &WalkAST::checkCall_mkstemp)
+          .Case("mkstemps", &WalkAST::checkCall_mkstemp)
+          .Cases("strcpy", "__strcpy_chk", &WalkAST::checkCall_strcpy)
+          .Cases("strcat", "__strcat_chk", &WalkAST::checkCall_strcat)
+          .Cases("sprintf", "vsprintf", "scanf", "wscanf", "fscanf", "fwscanf",
+                 "vscanf", "vwscanf", "vfscanf", "vfwscanf",
+                 &WalkAST::checkDeprecatedOrUnsafeBufferHandling)
+          .Cases("sscanf", "swscanf", "vsscanf", "vswscanf", "swprintf",
+                 "snprintf", "vswprintf", "vsnprintf", "memcpy", "memmove",
+                 &WalkAST::checkDeprecatedOrUnsafeBufferHandling)
+          .Cases("strncpy", "strncat", "memset", "fprintf",
+                 &WalkAST::checkDeprecatedOrUnsafeBufferHandling)
+          .Case("drand48", &WalkAST::checkCall_rand)
+          .Case("erand48", &WalkAST::checkCall_rand)
+          .Case("jrand48", &WalkAST::checkCall_rand)
+          .Case("lrand48", &WalkAST::checkCall_rand)
+          .Case("mrand48", &WalkAST::checkCall_rand)
+          .Case("nrand48", &WalkAST::checkCall_rand)
+          .Case("lcong48", &WalkAST::checkCall_rand)
+          .Case("rand", &WalkAST::checkCall_rand)
+          .Case("rand_r", &WalkAST::checkCall_rand)
+          .Case("random", &WalkAST::checkCall_random)
+          .Case("vfork", &WalkAST::checkCall_vfork)
+          .Default(nullptr);
 
   // If the callee isn't defined, it is not of security concern.
   // Check and evaluate the call.
@@ -737,10 +738,10 @@ void WalkAST::checkCall_strcat(const CallExpr *CE, const FunctionDecl *FD) {
 // Check: Any use of 'sprintf', 'vsprintf', 'scanf', 'wscanf', 'fscanf',
 //        'fwscanf', 'vscanf', 'vwscanf', 'vfscanf', 'vfwscanf', 'sscanf',
 //        'swscanf', 'vsscanf', 'vswscanf', 'swprintf', 'snprintf', 'vswprintf',
-//        'vsnprintf', 'memcpy', 'memmove', 'strncpy', 'strncat', 'memset'
-//        is deprecated since C11.
+//        'vsnprintf', 'memcpy', 'memmove', 'strncpy', 'strncat', 'memset',
+//        'fprintf' is deprecated since C11.
 //
-//        Use of 'sprintf', 'vsprintf', 'scanf', 'wscanf','fscanf',
+//        Use of 'sprintf', 'fprintf', 'vsprintf', 'scanf', 'wscanf', 'fscanf',
 //        'fwscanf', 'vscanf', 'vwscanf', 'vfscanf', 'vfwscanf', 'sscanf',
 //        'swscanf', 'vsscanf', 'vswscanf' without buffer limitations
 //        is insecure.
@@ -768,8 +769,9 @@ void WalkAST::checkDeprecatedOrUnsafeBufferHandling(const CallExpr *CE,
   int ArgIndex =
       llvm::StringSwitch<int>(Name)
           .Cases("scanf", "wscanf", "vscanf", "vwscanf", 0)
-          .Cases("sprintf", "vsprintf", "fscanf", "fwscanf", "vfscanf",
-                 "vfwscanf", "sscanf", "swscanf", "vsscanf", "vswscanf", 1)
+          .Cases("fscanf", "fwscanf", "vfscanf", "vfwscanf", "sscanf",
+                 "swscanf", "vsscanf", "vswscanf", 1)
+          .Cases("sprintf", "vsprintf", "fprintf", 1)
           .Cases("swprintf", "snprintf", "vswprintf", "vsnprintf", "memcpy",
                  "memmove", "memset", "strncpy", "strncat", DEPR_ONLY)
           .Default(UNKNOWN_CALL);
diff --git a/clang/test/Analysis/security-syntax-checks.c b/clang/test/Analysis/security-syntax-checks.c
index 392a65ff5f167ce..2c904f41623fcd1 100644
--- a/clang/test/Analysis/security-syntax-checks.c
+++ b/clang/test/Analysis/security-syntax-checks.c
@@ -5,15 +5,24 @@
 // RUN: %clang_analyze_cc1 %s -verify -std=gnu99 \
 // RUN:   -analyzer-checker=security.insecureAPI
 
+#include "Inputs/system-header-simulator.h"
+
+extern FILE *fp;
+extern char buf[128];
+
 void builtin_function_call_crash_fixes(char *c) {
   __builtin_strncpy(c, "", 6);
   __builtin_memset(c, '\0', (0));
   __builtin_memcpy(c, c, 0);
+  __builtin_sprintf(buf, "%s", c);
+  __builtin_fprintf(fp, "%s", c);
 
 #if __STDC_VERSION__ > 199901
-  // expected-warning at -5{{Call to function 'strncpy' is insecure as it does not provide security checks introduced in the C11 standard.}}
-  // expected-warning at -5{{Call to function 'memset' is insecure as it does not provide security checks introduced in the C11 standard.}}
-  // expected-warning at -5{{Call to function 'memcpy' is insecure as it does not provide security checks introduced in the C11 standard.}}
+  // expected-warning at -7{{Call to function 'strncpy' is insecure as it does not provide security checks introduced in the C11 standard.}}
+  // expected-warning at -7{{Call to function 'memset' is insecure as it does not provide security checks introduced in the C11 standard.}}
+  // expected-warning at -7{{Call to function 'memcpy' is insecure as it does not provide security checks introduced in the C11 standard.}}
+  // expected-warning at -7{{Call to function 'sprintf' is insecure as it does not provide bounding of the memory buffer or security checks introduced in the C11 standard.}}
+  // expected-warning at -7{{Call to function 'fprintf' is insecure as it does not provide bounding of the memory buffer or security checks introduced in the C11 standard.}}
 #else
   // expected-no-diagnostics
 #endif



More information about the cfe-commits mailing list