aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaChecking.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2010-03-25 03:59:12 +0000
committerTed Kremenek <kremenek@apple.com>2010-03-25 03:59:12 +0000
commit6ee765348b2855c702fa593fb030ef6abe0d01f6 (patch)
tree050fc89d24e82d40bed63ee34005f57580699d31 /lib/Sema/SemaChecking.cpp
parentfdb703ab3a3c28aeb53b3db4c54e14a30d78dc4e (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.cpp36
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);