diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2014-09-18 17:58:27 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2014-09-18 17:58:27 +0000 |
commit | 03b182422aec68f1567433aa3ae4eb9c0dd7e21a (patch) | |
tree | 12f2b9d9be1d65cfb93823ae4a07b2abcd35bfd5 /lib/Sema/SemaChecking.cpp | |
parent | 5032e400cdd5ba066a00d0d1391d2649bbce920e (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.cpp | 49 |
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 |