[cfe-commits] r94761 - in /cfe/trunk/lib/Sema: Sema.h SemaChecking.cpp
Ted Kremenek
kremenek at apple.com
Thu Jan 28 15:39:18 PST 2010
Author: kremenek
Date: Thu Jan 28 17:39:18 2010
New Revision: 94761
URL: http://llvm.org/viewvc/llvm-project?rev=94761&view=rev
Log:
Start fleshing out Sema::AlternateCheckPrintfString():
- Add an anonymous class 'CheckPrintfHandler' which will do the
checking of specific format specifiers
- Add checking for using the '@' conversion specifier outside
an ObjC string literal
- Add checking for null characters within the string
Modified:
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaChecking.cpp
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=94761&r1=94760&r2=94761&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Thu Jan 28 17:39:18 2010
@@ -4020,12 +4020,15 @@
//===--------------------------------------------------------------------===//
// Extra semantic analysis beyond the C type system
+
+public:
+ SourceLocation getLocationOfStringLiteralByte(const StringLiteral *SL,
+ unsigned ByteNo) const;
+
private:
bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall);
bool CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall);
- SourceLocation getLocationOfStringLiteralByte(const StringLiteral *SL,
- unsigned ByteNo) const;
bool CheckablePrintfAttr(const FormatAttr *Format, CallExpr *TheCall);
bool CheckObjCString(Expr *Arg);
Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=94761&r1=94760&r2=94761&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Thu Jan 28 17:39:18 2010
@@ -15,6 +15,7 @@
#include "Sema.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/Analyses/PrintfFormatString.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclObjC.h"
@@ -1279,13 +1280,106 @@
}
}
+
+namespace {
+class CheckPrintfHandler : public analyze_printf::FormatStringHandler {
+ Sema &S;
+ const StringLiteral *FExpr;
+ const Expr *OrigFormatExpr;
+ unsigned NumConversions;
+ const unsigned NumDataArgs;
+ const bool IsObjCLiteral;
+ const char *Beg; // Start of format string.
+public:
+ CheckPrintfHandler(Sema &s, const StringLiteral *fexpr,
+ const Expr *origFormatExpr,
+ unsigned numDataArgs, bool isObjCLiteral,
+ const char *beg)
+ : S(s), FExpr(fexpr), OrigFormatExpr(origFormatExpr),
+ NumConversions(0), NumDataArgs(numDataArgs),
+ IsObjCLiteral(isObjCLiteral), Beg(beg) {}
+
+ void HandleNullChar(const char *nullCharacter);
+
+ bool HandleFormatSpecifier(const analyze_printf::FormatSpecifier &FS,
+ const char *startSpecifier,
+ unsigned specifierLen);
+private:
+ SourceRange getFormatRange();
+ SourceLocation getLocationOfByte(const char *x);
+};
+}
+
+SourceRange CheckPrintfHandler::getFormatRange() {
+ return OrigFormatExpr->getSourceRange();
+}
+
+SourceLocation CheckPrintfHandler::getLocationOfByte(const char *x) {
+ return S.getLocationOfStringLiteralByte(FExpr, x - Beg);
+}
+
+void CheckPrintfHandler::HandleNullChar(const char *nullCharacter) {
+ // The presence of a null character is likely an error.
+ S.Diag(getLocationOfByte(nullCharacter),
+ diag::warn_printf_format_string_contains_null_char)
+ << getFormatRange();
+}
+
+bool
+CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier &FS,
+ const char *startSpecifier,
+ unsigned specifierLen) {
+
+ using namespace analyze_printf;
+ const ConversionSpecifier &CS = FS.getConversionSpecifier();
+
+ // Check for using an Objective-C specific conversion specifier
+ // in a non-ObjC literal.
+ if (!IsObjCLiteral && CS.isObjCArg()) {
+ SourceLocation Loc = getLocationOfByte(CS.getConversionStart());
+ S.Diag(Loc, diag::warn_printf_invalid_conversion)
+ << llvm::StringRef(startSpecifier, specifierLen)
+ << getFormatRange();
+
+ // Continue checking the other format specifiers.
+ return true;
+ }
+
+ return true;
+}
+
+
void
Sema::AlternateCheckPrintfString(const StringLiteral *FExpr,
const Expr *OrigFormatExpr,
const CallExpr *TheCall, bool HasVAListArg,
unsigned format_idx, unsigned firstDataArg) {
+ // CHECK: is the format string a wide literal?
+ if (FExpr->isWide()) {
+ Diag(FExpr->getLocStart(),
+ diag::warn_printf_format_string_is_wide_literal)
+ << OrigFormatExpr->getSourceRange();
+ return;
+ }
+
+ // Str - The format string. NOTE: this is NOT null-terminated!
+ const char *Str = FExpr->getStrData();
+
+ // CHECK: empty format string?
+ unsigned StrLen = FExpr->getByteLength();
+
+ if (StrLen == 0) {
+ Diag(FExpr->getLocStart(), diag::warn_printf_empty_format_string)
+ << OrigFormatExpr->getSourceRange();
+ return;
+ }
+ CheckPrintfHandler H(*this, FExpr, OrigFormatExpr,
+ TheCall->getNumArgs() - firstDataArg,
+ isa<ObjCStringLiteral>(OrigFormatExpr), Str);
+
+ analyze_printf::ParseFormatString(H, Str, Str + StrLen);
}
//===--- CHECK: Return Address of Stack Variable --------------------------===//
More information about the cfe-commits
mailing list