summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaChecking.cpp
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2014-09-18 17:58:27 +0000
committerFariborz Jahanian <fjahanian@apple.com>2014-09-18 17:58:27 +0000
commit03b182422aec68f1567433aa3ae4eb9c0dd7e21a (patch)
tree12f2b9d9be1d65cfb93823ae4a07b2abcd35bfd5 /lib/Sema/SemaChecking.cpp
parent5032e400cdd5ba066a00d0d1391d2649bbce920e (diff)
Patch to check at compile time for overflow when
__builtin___memcpy_chk and similar builtins are being used. Patch by Jacques Fortier (with added clang tests). rdar://11076881 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@218063 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaChecking.cpp')
-rw-r--r--lib/Sema/SemaChecking.cpp49
1 files changed, 48 insertions, 1 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 953b3f67d2..7462869306 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -111,8 +111,37 @@ static bool SemaBuiltinAddressof(Sema &S, CallExpr *TheCall) {
return false;
}
+static void SemaBuiltinMemChkCall(Sema &S, FunctionDecl *FDecl,
+ CallExpr *TheCall, unsigned SizeIdx,
+ unsigned DstSizeIdx) {
+ if (TheCall->getNumArgs() <= SizeIdx ||
+ TheCall->getNumArgs() <= DstSizeIdx)
+ return;
+
+ const Expr *SizeArg = TheCall->getArg(SizeIdx);
+ const Expr *DstSizeArg = TheCall->getArg(DstSizeIdx);
+
+ llvm::APSInt Size, DstSize;
+
+ // find out if both sizes are known at compile time
+ if (!SizeArg->EvaluateAsInt(Size, S.Context) ||
+ !DstSizeArg->EvaluateAsInt(DstSize, S.Context))
+ return;
+
+ if (Size.ule(DstSize))
+ return;
+
+ // confirmed overflow so generate the diagnostic.
+ IdentifierInfo *FnName = FDecl->getIdentifier();
+ SourceLocation SL = TheCall->getLocStart();
+ SourceRange SR = TheCall->getSourceRange();
+
+ S.Diag(SL, diag::warn_memcpy_chk_overflow) << SR << FnName;
+}
+
ExprResult
-Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
+Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
+ CallExpr *TheCall) {
ExprResult TheCallResult(TheCall);
// Find out if any arguments are required to be integer constant expressions.
@@ -332,6 +361,24 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
// so ensure that they are declared.
DeclareGlobalNewDelete();
break;
+
+ // check secure string manipulation functions where overflows
+ // are detectable at compile time
+ case Builtin::BI__builtin___memcpy_chk:
+ case Builtin::BI__builtin___memccpy_chk:
+ case Builtin::BI__builtin___memmove_chk:
+ case Builtin::BI__builtin___memset_chk:
+ case Builtin::BI__builtin___strlcat_chk:
+ case Builtin::BI__builtin___strlcpy_chk:
+ case Builtin::BI__builtin___strncat_chk:
+ case Builtin::BI__builtin___strncpy_chk:
+ case Builtin::BI__builtin___stpncpy_chk:
+ SemaBuiltinMemChkCall(*this, FDecl, TheCall, 2, 3);
+ break;
+ case Builtin::BI__builtin___snprintf_chk:
+ case Builtin::BI__builtin___vsnprintf_chk:
+ SemaBuiltinMemChkCall(*this, FDecl, TheCall, 1, 3);
+ break;
}
// Since the target specific builtins for each arch overlap, only check those