[cfe-commits] r94774 - in /cfe/trunk: include/clang/Analysis/Analyses/PrintfFormatString.h lib/Analysis/PrintfFormatString.cpp lib/Sema/SemaChecking.cpp
Ted Kremenek
kremenek at apple.com
Thu Jan 28 17:06:55 PST 2010
Author: kremenek
Date: Thu Jan 28 19:06:55 2010
New Revision: 94774
URL: http://llvm.org/viewvc/llvm-project?rev=94774&view=rev
Log:
Add precision/field width checking to AlternateCheckPrintfString().
Modified:
cfe/trunk/include/clang/Analysis/Analyses/PrintfFormatString.h
cfe/trunk/lib/Analysis/PrintfFormatString.cpp
cfe/trunk/lib/Sema/SemaChecking.cpp
Modified: cfe/trunk/include/clang/Analysis/Analyses/PrintfFormatString.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/PrintfFormatString.h?rev=94774&r1=94773&r2=94774&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/Analyses/PrintfFormatString.h (original)
+++ cfe/trunk/include/clang/Analysis/Analyses/PrintfFormatString.h Thu Jan 28 19:06:55 2010
@@ -104,21 +104,29 @@
public:
enum HowSpecified { NotSpecified, Constant, Arg };
- OptionalAmount(HowSpecified h = NotSpecified) : hs(h), amt(0) {}
- OptionalAmount(unsigned i) : hs(Constant), amt(i) {}
+ OptionalAmount(HowSpecified h, const char *st)
+ : start(st), hs(h), amt(0) {}
+
+ OptionalAmount()
+ : start(0), hs(NotSpecified), amt(0) {}
+
+ OptionalAmount(unsigned i, const char *st)
+ : start(start), hs(Constant), amt(i) {}
HowSpecified getHowSpecified() const { return hs; }
+ bool hasDataArgument() const { return hs == Arg; }
unsigned getConstantAmount() const {
assert(hs == Constant);
return amt;
}
- unsigned getArgumentsConsumed() {
- return hs == Arg ? 1 : 0;
+ const char *getStart() const {
+ return start;
}
private:
+ const char *start;
HowSpecified hs;
unsigned amt;
};
@@ -176,7 +184,7 @@
bool isLeftJustified() const { return flags & LeftJustified; }
bool hasPlusPrefix() const { return flags & PlusPrefix; }
bool hasAlternativeForm() const { return flags & AlternativeForm; }
- bool hasLeadingZeros() const { return flags & LeadingZeroes; }
+ bool hasLeadingZeros() const { return flags & LeadingZeroes; }
};
Modified: cfe/trunk/lib/Analysis/PrintfFormatString.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/PrintfFormatString.cpp?rev=94774&r1=94773&r2=94774&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/PrintfFormatString.cpp (original)
+++ cfe/trunk/lib/Analysis/PrintfFormatString.cpp Thu Jan 28 19:06:55 2010
@@ -15,7 +15,7 @@
#include "clang/Analysis/Analyses/PrintfFormatString.h"
using namespace clang;
-using namespace analyze_printf;
+using namespace clang::analyze_printf;
namespace {
class FormatSpecifierResult {
@@ -70,10 +70,12 @@
}
if (foundDigits)
- return OptionalAmount(accumulator);
+ return OptionalAmount(accumulator, Beg);
- if (c == '*')
- return OptionalAmount(OptionalAmount::Arg);
+ if (c == '*') {
+ ++I;
+ return OptionalAmount(OptionalAmount::Arg, Beg);
+ }
break;
}
Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=94774&r1=94773&r2=94774&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Thu Jan 28 19:06:55 2010
@@ -1290,14 +1290,20 @@
const unsigned NumDataArgs;
const bool IsObjCLiteral;
const char *Beg; // Start of format string.
+ const bool HasVAListArg;
+ const CallExpr *TheCall;
+ unsigned FormatIdx;
public:
CheckPrintfHandler(Sema &s, const StringLiteral *fexpr,
const Expr *origFormatExpr,
unsigned numDataArgs, bool isObjCLiteral,
- const char *beg)
+ const char *beg, bool hasVAListArg,
+ const CallExpr *theCall, unsigned formatIdx)
: S(s), FExpr(fexpr), OrigFormatExpr(origFormatExpr),
NumConversions(0), NumDataArgs(numDataArgs),
- IsObjCLiteral(isObjCLiteral), Beg(beg) {}
+ IsObjCLiteral(isObjCLiteral), Beg(beg),
+ HasVAListArg(hasVAListArg),
+ TheCall(theCall), FormatIdx(formatIdx) {}
void HandleNullChar(const char *nullCharacter);
@@ -1307,6 +1313,11 @@
private:
SourceRange getFormatRange();
SourceLocation getLocationOfByte(const char *x);
+
+ bool HandleAmount(const analyze_printf::OptionalAmount &Amt,
+ unsigned MissingArgDiag, unsigned BadTypeDiag);
+
+ const Expr *getDataArg(unsigned i) const;
};
}
@@ -1325,6 +1336,43 @@
<< getFormatRange();
}
+const Expr *CheckPrintfHandler::getDataArg(unsigned i) const {
+ return TheCall->getArg(FormatIdx + i);
+}
+
+bool
+CheckPrintfHandler::HandleAmount(const analyze_printf::OptionalAmount &Amt,
+ unsigned MissingArgDiag,
+ unsigned BadTypeDiag) {
+
+ if (Amt.hasDataArgument()) {
+ ++NumConversions;
+ if (!HasVAListArg) {
+ if (NumConversions > NumDataArgs) {
+ S.Diag(getLocationOfByte(Amt.getStart()), MissingArgDiag)
+ << getFormatRange();
+ // Don't do any more checking. We will just emit
+ // spurious errors.
+ return false;
+ }
+
+ // Type check the data argument. It should be an 'int'.
+ const Expr *Arg = getDataArg(NumConversions);
+ QualType T = Arg->getType();
+ const BuiltinType *BT = T->getAs<BuiltinType>();
+ if (!BT || BT->getKind() != BuiltinType::Int) {
+ S.Diag(getLocationOfByte(Amt.getStart()), BadTypeDiag)
+ << T << getFormatRange() << Arg->getSourceRange();
+ // Don't do any more checking. We will just emit
+ // spurious errors.
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+
bool
CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier &FS,
const char *startSpecifier,
@@ -1333,6 +1381,22 @@
using namespace analyze_printf;
const ConversionSpecifier &CS = FS.getConversionSpecifier();
+ // First check if the field width, precision, and conversion specifier
+ // have matching data arguments.
+ if (!HandleAmount(FS.getFieldWidth(),
+ diag::warn_printf_asterisk_width_missing_arg,
+ diag::warn_printf_asterisk_width_wrong_type)) {
+ return false;
+ }
+
+ if (!HandleAmount(FS.getPrecision(),
+ diag::warn_printf_asterisk_precision_missing_arg,
+ diag::warn_printf_asterisk_precision_wrong_type)) {
+ return false;
+ }
+
+ ++NumConversions;
+
// Check for using an Objective-C specific conversion specifier
// in a non-ObjC literal.
if (!IsObjCLiteral && CS.isObjCArg()) {
@@ -1377,7 +1441,8 @@
CheckPrintfHandler H(*this, FExpr, OrigFormatExpr,
TheCall->getNumArgs() - firstDataArg,
- isa<ObjCStringLiteral>(OrigFormatExpr), Str);
+ isa<ObjCStringLiteral>(OrigFormatExpr), Str,
+ HasVAListArg, TheCall, format_idx);
analyze_printf::ParseFormatString(H, Str, Str + StrLen);
}
More information about the cfe-commits
mailing list