Skip to content

Commit dc34e57

Browse files
authored
Merge pull request #512 from haoNoQ/static-analyzer-cherrypicks-7
Static analyzer cherrypicks 7
2 parents 82e1d79 + 5ddd656 commit dc34e57

15 files changed

+544
-67
lines changed

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

+5
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,11 @@ def DeprecatedOrUnsafeBufferHandling :
773773
Dependencies<[SecuritySyntaxChecker]>,
774774
Documentation<HasDocumentation>;
775775

776+
def decodeValueOfObjCType : Checker<"decodeValueOfObjCType">,
777+
HelpText<"Warn on uses of the '-decodeValueOfObjCType:at:' method">,
778+
Dependencies<[SecuritySyntaxChecker]>,
779+
Documentation<HasDocumentation>;
780+
776781
} // end "security.insecureAPI"
777782

778783
let ParentPackage = Security in {

clang/lib/Driver/ToolChains/Clang.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -2611,8 +2611,11 @@ static void RenderAnalyzerOptions(const ArgList &Args, ArgStringList &CmdArgs,
26112611
CmdArgs.push_back("-analyzer-disable-checker=unix.Vfork");
26122612
}
26132613

2614-
if (Triple.isOSDarwin())
2614+
if (Triple.isOSDarwin()) {
26152615
CmdArgs.push_back("-analyzer-checker=osx");
2616+
CmdArgs.push_back(
2617+
"-analyzer-checker=security.insecureAPI.decodeValueOfObjCType");
2618+
}
26162619

26172620
CmdArgs.push_back("-analyzer-checker=deadcode");
26182621

clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp

+68
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ struct ChecksFilter {
4949
DefaultBool check_vfork;
5050
DefaultBool check_FloatLoopCounter;
5151
DefaultBool check_UncheckedReturn;
52+
DefaultBool check_decodeValueOfObjCType;
5253

5354
CheckerNameRef checkName_bcmp;
5455
CheckerNameRef checkName_bcopy;
@@ -63,6 +64,7 @@ struct ChecksFilter {
6364
CheckerNameRef checkName_vfork;
6465
CheckerNameRef checkName_FloatLoopCounter;
6566
CheckerNameRef checkName_UncheckedReturn;
67+
CheckerNameRef checkName_decodeValueOfObjCType;
6668
};
6769

6870
class WalkAST : public StmtVisitor<WalkAST> {
@@ -83,6 +85,7 @@ class WalkAST : public StmtVisitor<WalkAST> {
8385

8486
// Statement visitor methods.
8587
void VisitCallExpr(CallExpr *CE);
88+
void VisitObjCMessageExpr(ObjCMessageExpr *CE);
8689
void VisitForStmt(ForStmt *S);
8790
void VisitCompoundStmt (CompoundStmt *S);
8891
void VisitStmt(Stmt *S) { VisitChildren(S); }
@@ -93,6 +96,7 @@ class WalkAST : public StmtVisitor<WalkAST> {
9396
bool checkCall_strCommon(const CallExpr *CE, const FunctionDecl *FD);
9497

9598
typedef void (WalkAST::*FnCheck)(const CallExpr *, const FunctionDecl *);
99+
typedef void (WalkAST::*MsgCheck)(const ObjCMessageExpr *);
96100

97101
// Checker-specific methods.
98102
void checkLoopConditionForFloat(const ForStmt *FS);
@@ -110,6 +114,7 @@ class WalkAST : public StmtVisitor<WalkAST> {
110114
void checkCall_rand(const CallExpr *CE, const FunctionDecl *FD);
111115
void checkCall_random(const CallExpr *CE, const FunctionDecl *FD);
112116
void checkCall_vfork(const CallExpr *CE, const FunctionDecl *FD);
117+
void checkMsg_decodeValueOfObjCType(const ObjCMessageExpr *ME);
113118
void checkUncheckedReturnValue(CallExpr *CE);
114119
};
115120
} // end anonymous namespace
@@ -182,6 +187,20 @@ void WalkAST::VisitCallExpr(CallExpr *CE) {
182187
VisitChildren(CE);
183188
}
184189

190+
void WalkAST::VisitObjCMessageExpr(ObjCMessageExpr *ME) {
191+
MsgCheck evalFunction =
192+
llvm::StringSwitch<MsgCheck>(ME->getSelector().getAsString())
193+
.Case("decodeValueOfObjCType:at:",
194+
&WalkAST::checkMsg_decodeValueOfObjCType)
195+
.Default(nullptr);
196+
197+
if (evalFunction)
198+
(this->*evalFunction)(ME);
199+
200+
// Recurse and check children.
201+
VisitChildren(ME);
202+
}
203+
185204
void WalkAST::VisitCompoundStmt(CompoundStmt *S) {
186205
for (Stmt *Child : S->children())
187206
if (Child) {
@@ -923,6 +942,54 @@ void WalkAST::checkCall_vfork(const CallExpr *CE, const FunctionDecl *FD) {
923942
CELoc, CE->getCallee()->getSourceRange());
924943
}
925944

945+
//===----------------------------------------------------------------------===//
946+
// Check: '-decodeValueOfObjCType:at:' should not be used.
947+
// It is deprecated in favor of '-decodeValueOfObjCType:at:size:' due to
948+
// likelihood of buffer overflows.
949+
//===----------------------------------------------------------------------===//
950+
951+
void WalkAST::checkMsg_decodeValueOfObjCType(const ObjCMessageExpr *ME) {
952+
if (!filter.check_decodeValueOfObjCType)
953+
return;
954+
955+
// Check availability of the secure alternative:
956+
// iOS 11+, macOS 10.13+, tvOS 11+, and watchOS 4.0+
957+
// FIXME: We probably shouldn't register the check if it's not available.
958+
const TargetInfo &TI = AC->getASTContext().getTargetInfo();
959+
const llvm::Triple &T = TI.getTriple();
960+
const VersionTuple &VT = TI.getPlatformMinVersion();
961+
switch (T.getOS()) {
962+
case llvm::Triple::IOS:
963+
if (VT < VersionTuple(11, 0))
964+
return;
965+
break;
966+
case llvm::Triple::MacOSX:
967+
if (VT < VersionTuple(10, 13))
968+
return;
969+
break;
970+
case llvm::Triple::WatchOS:
971+
if (VT < VersionTuple(4, 0))
972+
return;
973+
break;
974+
case llvm::Triple::TvOS:
975+
if (VT < VersionTuple(11, 0))
976+
return;
977+
break;
978+
default:
979+
return;
980+
}
981+
982+
PathDiagnosticLocation MELoc =
983+
PathDiagnosticLocation::createBegin(ME, BR.getSourceManager(), AC);
984+
BR.EmitBasicReport(
985+
AC->getDecl(), filter.checkName_decodeValueOfObjCType,
986+
"Potential buffer overflow in '-decodeValueOfObjCType:at:'", "Security",
987+
"Deprecated method '-decodeValueOfObjCType:at:' is insecure "
988+
"as it can lead to potential buffer overflows. Use the safer "
989+
"'-decodeValueOfObjCType:at:size:' method.",
990+
MELoc, ME->getSourceRange());
991+
}
992+
926993
//===----------------------------------------------------------------------===//
927994
// Check: Should check whether privileges are dropped successfully.
928995
// Originally: <rdar://problem/6337132>
@@ -1035,3 +1102,4 @@ REGISTER_CHECKER(vfork)
10351102
REGISTER_CHECKER(FloatLoopCounter)
10361103
REGISTER_CHECKER(UncheckedReturn)
10371104
REGISTER_CHECKER(DeprecatedOrUnsafeBufferHandling)
1105+
REGISTER_CHECKER(decodeValueOfObjCType)

0 commit comments

Comments
 (0)