Skip to content

Commit fe09888

Browse files
committed
[clang][analyzer] Add AllowWithoutC11 option to DeprecatedOrUnsafeBufferHandling checker
The checker may report warnings for deprecated buffer handling functions (memcpy, memset, memmove, etc.) even when not compiling with C11 standard if the new option "AllowWithoutC11" is set to true. These functions are deprecated in C11, but may still be problematic in earlier C standards.
1 parent c946418 commit fe09888

File tree

6 files changed

+92
-8
lines changed

6 files changed

+92
-8
lines changed

clang/docs/analyzer/checkers.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1768,6 +1768,13 @@ security.insecureAPI.DeprecatedOrUnsafeBufferHandling (C)
17681768
strncpy(buf, "a", 1); // warn
17691769
}
17701770
1771+
The ``AllowWithoutC11`` option allows reporting warnings for these functions even when not compiling with C11 standard. These functions are deprecated in C11, but may still be problematic in earlier C standards.
1772+
1773+
To enable this option, use:
1774+
``-analyzer-config security.insecureAPI.DeprecatedOrUnsafeBufferHandling:AllowWithoutC11=true``.
1775+
1776+
By default, this option is set to *false*.
1777+
17711778
.. _security-MmapWriteExec:
17721779
17731780
security.MmapWriteExec (C)

clang/include/clang/StaticAnalyzer/Checkers/Checkers.td

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -901,12 +901,21 @@ def UncheckedReturn : Checker<"UncheckedReturn">,
901901
Dependencies<[SecuritySyntaxChecker]>,
902902
Documentation<HasDocumentation>;
903903

904-
def DeprecatedOrUnsafeBufferHandling :
905-
Checker<"DeprecatedOrUnsafeBufferHandling">,
906-
HelpText<"Warn on uses of unsecure or deprecated buffer manipulating "
907-
"functions">,
908-
Dependencies<[SecuritySyntaxChecker]>,
909-
Documentation<HasDocumentation>;
904+
def DeprecatedOrUnsafeBufferHandling
905+
: Checker<"DeprecatedOrUnsafeBufferHandling">,
906+
HelpText<"Warn on uses of unsecure or deprecated buffer manipulating "
907+
"functions">,
908+
Dependencies<[SecuritySyntaxChecker]>,
909+
CheckerOptions<
910+
[CmdLineOption<
911+
Boolean, "AllowWithoutC11",
912+
"Allow reporting deprecated or unsafe buffer handling "
913+
"functions even when not compiling with C11 standard. "
914+
"These functions are deprecated in C11, but may still be "
915+
"problematic in earlier C standards.",
916+
"false", Released>,
917+
]>,
918+
Documentation<HasDocumentation>;
910919

911920
def decodeValueOfObjCType : Checker<"decodeValueOfObjCType">,
912921
HelpText<"Warn on uses of the '-decodeValueOfObjCType:at:' method">,

clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ struct ChecksFilter {
5050
bool check_UncheckedReturn = false;
5151
bool check_decodeValueOfObjCType = false;
5252

53+
bool allowDeprecatedOrUnsafeBufferHandlingWithoutC11 = false;
54+
5355
CheckerNameRef checkName_bcmp;
5456
CheckerNameRef checkName_bcopy;
5557
CheckerNameRef checkName_bzero;
@@ -754,7 +756,8 @@ void WalkAST::checkDeprecatedOrUnsafeBufferHandling(const CallExpr *CE,
754756
if (!filter.check_DeprecatedOrUnsafeBufferHandling)
755757
return;
756758

757-
if (!BR.getContext().getLangOpts().C11)
759+
if (!(BR.getContext().getLangOpts().C11 ||
760+
filter.allowDeprecatedOrUnsafeBufferHandlingWithoutC11))
758761
return;
759762

760763
// Issue a warning. ArgIndex == -1: Deprecated but not unsafe (has size
@@ -1113,5 +1116,20 @@ REGISTER_CHECKER(rand)
11131116
REGISTER_CHECKER(vfork)
11141117
REGISTER_CHECKER(FloatLoopCounter)
11151118
REGISTER_CHECKER(UncheckedReturn)
1116-
REGISTER_CHECKER(DeprecatedOrUnsafeBufferHandling)
1119+
1120+
void ento::registerDeprecatedOrUnsafeBufferHandling(CheckerManager &mgr) {
1121+
SecuritySyntaxChecker *checker = mgr.getChecker<SecuritySyntaxChecker>();
1122+
checker->filter.check_DeprecatedOrUnsafeBufferHandling = true;
1123+
checker->filter.checkName_DeprecatedOrUnsafeBufferHandling =
1124+
mgr.getCurrentCheckerName();
1125+
checker->filter.allowDeprecatedOrUnsafeBufferHandlingWithoutC11 =
1126+
mgr.getAnalyzerOptions().getCheckerBooleanOption(
1127+
mgr.getCurrentCheckerName(), "AllowWithoutC11");
1128+
}
1129+
1130+
bool ento::shouldRegisterDeprecatedOrUnsafeBufferHandling(
1131+
const CheckerManager &mgr) {
1132+
return true;
1133+
}
1134+
11171135
REGISTER_CHECKER(decodeValueOfObjCType)

clang/test/Analysis/Inputs/system-header-simulator.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ char *strcpy(char *restrict, const char *restrict);
8282
char *strncpy(char *restrict dst, const char *restrict src, size_t n);
8383
char *strsep(char **restrict stringp, const char *restrict delim);
8484
void *memcpy(void *restrict dst, const void *restrict src, size_t n);
85+
void *memmove(void *dst, const void *src, size_t n);
8586
void *memset(void *s, int c, size_t n);
8687

8788
typedef unsigned long __darwin_pthread_key_t;

clang/test/Analysis/analyzer-config.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@
121121
// CHECK-NEXT: region-store-small-struct-limit = 2
122122
// CHECK-NEXT: report-in-main-source-file = false
123123
// CHECK-NEXT: security.cert.env.InvalidPtr:InvalidatingGetEnv = false
124+
// CHECK-NEXT: security.insecureAPI.DeprecatedOrUnsafeBufferHandling:AllowWithoutC11 = false
124125
// CHECK-NEXT: serialize-stats = false
125126
// CHECK-NEXT: silence-checkers = ""
126127
// CHECK-NEXT: stable-report-filename = false
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Test 1: Without C11 and without flag - should NOT warn
2+
// RUN: %clang_analyze_cc1 %s -verify -std=gnu99 \
3+
// RUN: -analyzer-checker=security.insecureAPI.DeprecatedOrUnsafeBufferHandling \
4+
// RUN: -DEXPECT_NO_WARNINGS
5+
6+
// Test 2: Without C11 but with flag enabled - should warn
7+
// RUN: %clang_analyze_cc1 %s -verify -std=gnu99 \
8+
// RUN: -analyzer-checker=security.insecureAPI.DeprecatedOrUnsafeBufferHandling \
9+
// RUN: -analyzer-config security.insecureAPI.DeprecatedOrUnsafeBufferHandling:AllowWithoutC11=true \
10+
// RUN: -DEXPECT_WARNINGS
11+
12+
// Test 3: With C11 - should warn (existing behavior)
13+
// RUN: %clang_analyze_cc1 %s -verify -std=gnu11 \
14+
// RUN: -analyzer-checker=security.insecureAPI.DeprecatedOrUnsafeBufferHandling \
15+
// RUN: -DEXPECT_WARNINGS
16+
17+
#include "Inputs/system-header-simulator.h"
18+
19+
extern char buf[128];
20+
extern char src[128];
21+
22+
void test_memcpy(void) {
23+
memcpy(buf, src, 10);
24+
#ifdef EXPECT_WARNINGS
25+
// expected-warning@-2{{Call to function 'memcpy' is insecure as it does not provide security checks introduced in the C11 standard}}
26+
#else
27+
// expected-no-diagnostics
28+
#endif
29+
}
30+
31+
void test_memset(void) {
32+
memset(buf, 0, 10);
33+
#ifdef EXPECT_WARNINGS
34+
// expected-warning@-2{{Call to function 'memset' is insecure as it does not provide security checks introduced in the C11 standard}}
35+
#else
36+
// expected-no-diagnostics
37+
#endif
38+
}
39+
40+
void test_memmove(void) {
41+
memmove(buf, src, 10);
42+
#ifdef EXPECT_WARNINGS
43+
// expected-warning@-2{{Call to function 'memmove' is insecure as it does not provide security checks introduced in the C11 standard}}
44+
#else
45+
// expected-no-diagnostics
46+
#endif
47+
}
48+

0 commit comments

Comments
 (0)