Skip to content

Commit dd0b3c2

Browse files
authored
[clang][analyzer] Support fprintf in the SecuritySyntaxChecker (llvm#73247)
1 parent 579e721 commit dd0b3c2

File tree

2 files changed

+51
-40
lines changed

2 files changed

+51
-40
lines changed

clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -144,38 +144,39 @@ void WalkAST::VisitCallExpr(CallExpr *CE) {
144144
Name = Name.substr(10);
145145

146146
// Set the evaluation function by switching on the callee name.
147-
FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name)
148-
.Case("bcmp", &WalkAST::checkCall_bcmp)
149-
.Case("bcopy", &WalkAST::checkCall_bcopy)
150-
.Case("bzero", &WalkAST::checkCall_bzero)
151-
.Case("gets", &WalkAST::checkCall_gets)
152-
.Case("getpw", &WalkAST::checkCall_getpw)
153-
.Case("mktemp", &WalkAST::checkCall_mktemp)
154-
.Case("mkstemp", &WalkAST::checkCall_mkstemp)
155-
.Case("mkdtemp", &WalkAST::checkCall_mkstemp)
156-
.Case("mkstemps", &WalkAST::checkCall_mkstemp)
157-
.Cases("strcpy", "__strcpy_chk", &WalkAST::checkCall_strcpy)
158-
.Cases("strcat", "__strcat_chk", &WalkAST::checkCall_strcat)
159-
.Cases("sprintf", "vsprintf", "scanf", "wscanf", "fscanf", "fwscanf",
160-
"vscanf", "vwscanf", "vfscanf", "vfwscanf",
161-
&WalkAST::checkDeprecatedOrUnsafeBufferHandling)
162-
.Cases("sscanf", "swscanf", "vsscanf", "vswscanf", "swprintf",
163-
"snprintf", "vswprintf", "vsnprintf", "memcpy", "memmove",
164-
&WalkAST::checkDeprecatedOrUnsafeBufferHandling)
165-
.Cases("strncpy", "strncat", "memset",
166-
&WalkAST::checkDeprecatedOrUnsafeBufferHandling)
167-
.Case("drand48", &WalkAST::checkCall_rand)
168-
.Case("erand48", &WalkAST::checkCall_rand)
169-
.Case("jrand48", &WalkAST::checkCall_rand)
170-
.Case("lrand48", &WalkAST::checkCall_rand)
171-
.Case("mrand48", &WalkAST::checkCall_rand)
172-
.Case("nrand48", &WalkAST::checkCall_rand)
173-
.Case("lcong48", &WalkAST::checkCall_rand)
174-
.Case("rand", &WalkAST::checkCall_rand)
175-
.Case("rand_r", &WalkAST::checkCall_rand)
176-
.Case("random", &WalkAST::checkCall_random)
177-
.Case("vfork", &WalkAST::checkCall_vfork)
178-
.Default(nullptr);
147+
FnCheck evalFunction =
148+
llvm::StringSwitch<FnCheck>(Name)
149+
.Case("bcmp", &WalkAST::checkCall_bcmp)
150+
.Case("bcopy", &WalkAST::checkCall_bcopy)
151+
.Case("bzero", &WalkAST::checkCall_bzero)
152+
.Case("gets", &WalkAST::checkCall_gets)
153+
.Case("getpw", &WalkAST::checkCall_getpw)
154+
.Case("mktemp", &WalkAST::checkCall_mktemp)
155+
.Case("mkstemp", &WalkAST::checkCall_mkstemp)
156+
.Case("mkdtemp", &WalkAST::checkCall_mkstemp)
157+
.Case("mkstemps", &WalkAST::checkCall_mkstemp)
158+
.Cases("strcpy", "__strcpy_chk", &WalkAST::checkCall_strcpy)
159+
.Cases("strcat", "__strcat_chk", &WalkAST::checkCall_strcat)
160+
.Cases("sprintf", "vsprintf", "scanf", "wscanf", "fscanf", "fwscanf",
161+
"vscanf", "vwscanf", "vfscanf", "vfwscanf",
162+
&WalkAST::checkDeprecatedOrUnsafeBufferHandling)
163+
.Cases("sscanf", "swscanf", "vsscanf", "vswscanf", "swprintf",
164+
"snprintf", "vswprintf", "vsnprintf", "memcpy", "memmove",
165+
&WalkAST::checkDeprecatedOrUnsafeBufferHandling)
166+
.Cases("strncpy", "strncat", "memset", "fprintf",
167+
&WalkAST::checkDeprecatedOrUnsafeBufferHandling)
168+
.Case("drand48", &WalkAST::checkCall_rand)
169+
.Case("erand48", &WalkAST::checkCall_rand)
170+
.Case("jrand48", &WalkAST::checkCall_rand)
171+
.Case("lrand48", &WalkAST::checkCall_rand)
172+
.Case("mrand48", &WalkAST::checkCall_rand)
173+
.Case("nrand48", &WalkAST::checkCall_rand)
174+
.Case("lcong48", &WalkAST::checkCall_rand)
175+
.Case("rand", &WalkAST::checkCall_rand)
176+
.Case("rand_r", &WalkAST::checkCall_rand)
177+
.Case("random", &WalkAST::checkCall_random)
178+
.Case("vfork", &WalkAST::checkCall_vfork)
179+
.Default(nullptr);
179180

180181
// If the callee isn't defined, it is not of security concern.
181182
// Check and evaluate the call.
@@ -737,10 +738,10 @@ void WalkAST::checkCall_strcat(const CallExpr *CE, const FunctionDecl *FD) {
737738
// Check: Any use of 'sprintf', 'vsprintf', 'scanf', 'wscanf', 'fscanf',
738739
// 'fwscanf', 'vscanf', 'vwscanf', 'vfscanf', 'vfwscanf', 'sscanf',
739740
// 'swscanf', 'vsscanf', 'vswscanf', 'swprintf', 'snprintf', 'vswprintf',
740-
// 'vsnprintf', 'memcpy', 'memmove', 'strncpy', 'strncat', 'memset'
741-
// is deprecated since C11.
741+
// 'vsnprintf', 'memcpy', 'memmove', 'strncpy', 'strncat', 'memset',
742+
// 'fprintf' is deprecated since C11.
742743
//
743-
// Use of 'sprintf', 'vsprintf', 'scanf', 'wscanf','fscanf',
744+
// Use of 'sprintf', 'fprintf', 'vsprintf', 'scanf', 'wscanf', 'fscanf',
744745
// 'fwscanf', 'vscanf', 'vwscanf', 'vfscanf', 'vfwscanf', 'sscanf',
745746
// 'swscanf', 'vsscanf', 'vswscanf' without buffer limitations
746747
// is insecure.
@@ -768,8 +769,9 @@ void WalkAST::checkDeprecatedOrUnsafeBufferHandling(const CallExpr *CE,
768769
int ArgIndex =
769770
llvm::StringSwitch<int>(Name)
770771
.Cases("scanf", "wscanf", "vscanf", "vwscanf", 0)
771-
.Cases("sprintf", "vsprintf", "fscanf", "fwscanf", "vfscanf",
772-
"vfwscanf", "sscanf", "swscanf", "vsscanf", "vswscanf", 1)
772+
.Cases("fscanf", "fwscanf", "vfscanf", "vfwscanf", "sscanf",
773+
"swscanf", "vsscanf", "vswscanf", 1)
774+
.Cases("sprintf", "vsprintf", "fprintf", 1)
773775
.Cases("swprintf", "snprintf", "vswprintf", "vsnprintf", "memcpy",
774776
"memmove", "memset", "strncpy", "strncat", DEPR_ONLY)
775777
.Default(UNKNOWN_CALL);

clang/test/Analysis/security-syntax-checks.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,24 @@
55
// RUN: %clang_analyze_cc1 %s -verify -std=gnu99 \
66
// RUN: -analyzer-checker=security.insecureAPI
77

8+
#include "Inputs/system-header-simulator.h"
9+
10+
extern FILE *fp;
11+
extern char buf[128];
12+
813
void builtin_function_call_crash_fixes(char *c) {
914
__builtin_strncpy(c, "", 6);
1015
__builtin_memset(c, '\0', (0));
1116
__builtin_memcpy(c, c, 0);
17+
__builtin_sprintf(buf, "%s", c);
18+
__builtin_fprintf(fp, "%s", c);
1219

1320
#if __STDC_VERSION__ > 199901
14-
// expected-warning@-5{{Call to function 'strncpy' is insecure as it does not provide security checks introduced in the C11 standard.}}
15-
// expected-warning@-5{{Call to function 'memset' is insecure as it does not provide security checks introduced in the C11 standard.}}
16-
// expected-warning@-5{{Call to function 'memcpy' is insecure as it does not provide security checks introduced in the C11 standard.}}
21+
// expected-warning@-7{{Call to function 'strncpy' is insecure as it does not provide security checks introduced in the C11 standard.}}
22+
// expected-warning@-7{{Call to function 'memset' is insecure as it does not provide security checks introduced in the C11 standard.}}
23+
// expected-warning@-7{{Call to function 'memcpy' is insecure as it does not provide security checks introduced in the C11 standard.}}
24+
// expected-warning@-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.}}
25+
// expected-warning@-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.}}
1726
#else
1827
// expected-no-diagnostics
1928
#endif

0 commit comments

Comments
 (0)