diff options
author | Ted Kremenek <kremenek@apple.com> | 2010-03-25 03:59:12 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2010-03-25 03:59:12 +0000 |
commit | 6ee765348b2855c702fa593fb030ef6abe0d01f6 (patch) | |
tree | 050fc89d24e82d40bed63ee34005f57580699d31 /lib/Sema/SemaChecking.cpp | |
parent | fdb703ab3a3c28aeb53b3db4c54e14a30d78dc4e (diff) |
Fix two bugs in format-string checking:
(1) Do not assume the data arguments start after the format string
(2) Do not use the fact that a function is variadic to treat it like a va_list printf function
Fixes PR 6697.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@99480 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaChecking.cpp')
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 36 |
1 files changed, 17 insertions, 19 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 0a33485dd7..ff364fce75 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -222,11 +222,6 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) { if (const FormatAttr *Format = FDecl->getAttr<FormatAttr>()) { if (CheckablePrintfAttr(Format, TheCall)) { bool HasVAListArg = Format->getFirstArg() == 0; - if (!HasVAListArg) { - if (const FunctionProtoType *Proto - = FDecl->getType()->getAs<FunctionProtoType>()) - HasVAListArg = !Proto->isVariadic(); - } CheckPrintfArguments(TheCall, HasVAListArg, Format->getFormatIdx() - 1, HasVAListArg ? 0 : Format->getFirstArg() - 1); } @@ -257,12 +252,6 @@ bool Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall) { return false; bool HasVAListArg = Format->getFirstArg() == 0; - if (!HasVAListArg) { - const FunctionType *FT = - Ty->getAs<BlockPointerType>()->getPointeeType()->getAs<FunctionType>(); - if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT)) - HasVAListArg = !Proto->isVariadic(); - } CheckPrintfArguments(TheCall, HasVAListArg, Format->getFormatIdx() - 1, HasVAListArg ? 0 : Format->getFirstArg() - 1); @@ -1045,6 +1034,7 @@ class CheckPrintfHandler : public analyze_printf::FormatStringHandler { Sema &S; const StringLiteral *FExpr; const Expr *OrigFormatExpr; + const unsigned FirstDataArg; const unsigned NumDataArgs; const bool IsObjCLiteral; const char *Beg; // Start of format string. @@ -1056,11 +1046,12 @@ class CheckPrintfHandler : public analyze_printf::FormatStringHandler { bool atFirstArg; public: CheckPrintfHandler(Sema &s, const StringLiteral *fexpr, - const Expr *origFormatExpr, + const Expr *origFormatExpr, unsigned firstDataArg, unsigned numDataArgs, bool isObjCLiteral, const char *beg, bool hasVAListArg, const CallExpr *theCall, unsigned formatIdx) : S(s), FExpr(fexpr), OrigFormatExpr(origFormatExpr), + FirstDataArg(firstDataArg), NumDataArgs(numDataArgs), IsObjCLiteral(isObjCLiteral), Beg(beg), HasVAListArg(hasVAListArg), @@ -1183,11 +1174,9 @@ void CheckPrintfHandler::HandleNullChar(const char *nullCharacter) { } const Expr *CheckPrintfHandler::getDataArg(unsigned i) const { - return TheCall->getArg(FormatIdx + i + 1); + return TheCall->getArg(FirstDataArg + i); } - - void CheckPrintfHandler::HandleFlags(const analyze_printf::FormatSpecifier &FS, llvm::StringRef flag, llvm::StringRef cspec, @@ -1329,9 +1318,18 @@ CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier return true; if (argIndex >= NumDataArgs) { - S.Diag(getLocationOfByte(CS.getStart()), - diag::warn_printf_insufficient_data_args) - << getFormatSpecifierRange(startSpecifier, specifierLen); + if (FS.usesPositionalArg()) { + S.Diag(getLocationOfByte(CS.getStart()), + diag::warn_printf_positional_arg_exceeds_data_args) + << (argIndex+1) << NumDataArgs + << getFormatSpecifierRange(startSpecifier, specifierLen); + } + else { + S.Diag(getLocationOfByte(CS.getStart()), + diag::warn_printf_insufficient_data_args) + << getFormatSpecifierRange(startSpecifier, specifierLen); + } + // Don't do any more checking. return false; } @@ -1400,7 +1398,7 @@ void Sema::CheckPrintfString(const StringLiteral *FExpr, return; } - CheckPrintfHandler H(*this, FExpr, OrigFormatExpr, + CheckPrintfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg, TheCall->getNumArgs() - firstDataArg, isa<ObjCStringLiteral>(OrigFormatExpr), Str, HasVAListArg, TheCall, format_idx); |