[cfe-commits] r94792 - 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 18:40:24 PST 2010


Author: kremenek
Date: Thu Jan 28 20:40:24 2010
New Revision: 94792

URL: http://llvm.org/viewvc/llvm-project?rev=94792&view=rev
Log:
Alternate format string checking: issue a warning for invalid conversion specifiers.

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=94792&r1=94791&r2=94792&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/Analyses/PrintfFormatString.h (original)
+++ cfe/trunk/include/clang/Analysis/Analyses/PrintfFormatString.h Thu Jan 28 20:40:24 2010
@@ -200,7 +200,9 @@
   
   virtual void HandleIncompletePrecision(const char *periodChar) {}
   
-  virtual void HandleInvalidConversionSpecifier(const char *conversionChar) {}
+  virtual void HandleInvalidConversionSpecifier(const FormatSpecifier &FS,
+                                                const char *startSpecifier,
+                                                unsigned specifierLen) {}
   
   virtual bool HandleFormatSpecifier(const FormatSpecifier &FS,
                                      const char *startSpecifier,

Modified: cfe/trunk/lib/Analysis/PrintfFormatString.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/PrintfFormatString.cpp?rev=94792&r1=94791&r2=94792&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/PrintfFormatString.cpp (original)
+++ cfe/trunk/lib/Analysis/PrintfFormatString.cpp Thu Jan 28 20:40:24 2010
@@ -21,17 +21,17 @@
 class FormatSpecifierResult {
   FormatSpecifier FS;
   const char *Start;
-  bool HasError;
+  bool Stop;
 public:
-  FormatSpecifierResult(bool err = false)
-    : Start(0), HasError(err) {}
+  FormatSpecifierResult(bool stop = false)
+    : Start(0), Stop(stop) {}
   FormatSpecifierResult(const char *start,
                         const FormatSpecifier &fs)
-    : FS(fs), Start(start), HasError(false) {}
+    : FS(fs), Start(start), Stop(false) {}
 
   
   const char *getStart() const { return Start; }
-  bool hasError() const { return HasError; }
+  bool shouldStop() const { return Stop; }
   bool hasValue() const { return Start != 0; }
   const FormatSpecifier &getValue() const {
     assert(hasValue());
@@ -194,11 +194,10 @@
   
   // Finally, look for the conversion specifier.
   const char *conversionPosition = I++;
-  ConversionSpecifier::Kind k;
+  ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier;
   switch (*conversionPosition) {
     default:
-      H.HandleInvalidConversionSpecifier(conversionPosition);
-      return true;      
+      break;
     // C99: 7.19.6.1 (section 8).
     case 'd': k = ConversionSpecifier::dArg; break;
     case 'i': k = ConversionSpecifier::iArg; break;
@@ -223,6 +222,11 @@
     case '@': k = ConversionSpecifier::ObjCObjArg; break;      
   }
   FS.setConversionSpecifier(ConversionSpecifier(conversionPosition, k));
+
+  if (k == ConversionSpecifier::InvalidSpecifier) {
+    H.HandleInvalidConversionSpecifier(FS, Beg, I - Beg);
+    return false; // Keep processing format specifiers.
+  }
   return FormatSpecifierResult(Start, FS);
 }
 
@@ -232,13 +236,14 @@
   // Keep looking for a format specifier until we have exhausted the string.
   while (I != E) {
     const FormatSpecifierResult &FSR = ParseFormatSpecifier(H, I, E);
-    // Did an error of any kind occur when parsing the specifier?  If so,
-    // don't do any more processing.
-    if (FSR.hasError())
+    // Did a fail-stop error of any kind occur when parsing the specifier?
+    // If so, don't do any more processing.
+    if (FSR.shouldStop())
       return true;;
-    // Done processing the string?
+    // Did we exhaust the string or encounter an error that
+    // we can recover from?
     if (!FSR.hasValue())
-      break;    
+      continue;
     // We have a format specifier.  Pass it to the callback.
     if (!H.HandleFormatSpecifier(FSR.getValue(), FSR.getStart(),
                                  I - FSR.getStart()))

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=94792&r1=94791&r2=94792&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Thu Jan 28 20:40:24 2010
@@ -1306,7 +1306,16 @@
       TheCall(theCall), FormatIdx(formatIdx) {}
   
   void DoneProcessing();
-    
+   
+//  void HandleIncompleteFormatSpecifier(const char *startSpecifier,
+//                                       const char *endSpecifier);
+  
+//  void HandleIncompletePrecision(const char *periodChar);
+  
+  void HandleInvalidConversionSpecifier(const analyze_printf::FormatSpecifier &FS,
+                                        const char *startSpecifier,
+                                        unsigned specifierLen);
+  
   void HandleNullChar(const char *nullCharacter);
   
   bool HandleFormatSpecifier(const analyze_printf::FormatSpecifier &FS,
@@ -1331,6 +1340,20 @@
   return S.getLocationOfStringLiteralByte(FExpr, x - Beg);  
 }
 
+void CheckPrintfHandler::
+HandleInvalidConversionSpecifier(const analyze_printf::FormatSpecifier &FS,
+                                 const char *startSpecifier,
+                                 unsigned specifierLen) {
+  
+  ++NumConversions;
+  
+  SourceLocation Loc =
+    getLocationOfByte(FS.getConversionSpecifier().getStart());
+  S.Diag(Loc, diag::warn_printf_invalid_conversion)
+      << llvm::StringRef(startSpecifier, specifierLen)
+      << getFormatRange();  
+}
+
 void CheckPrintfHandler::HandleNullChar(const char *nullCharacter) {
   // The presence of a null character is likely an error.
   S.Diag(getLocationOfByte(nullCharacter),
@@ -1373,7 +1396,6 @@
   }
   return true;
 }
-                                      
 
 bool
 CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier &FS,
@@ -1397,20 +1419,17 @@
     return false;
   }
 
-  ++NumConversions;  
-  
   // Check for using an Objective-C specific conversion specifier
   // in a non-ObjC literal.
   if (!IsObjCLiteral && CS.isObjCArg()) {
-    SourceLocation Loc = getLocationOfByte(CS.getStart());
-    S.Diag(Loc, diag::warn_printf_invalid_conversion)
-      << llvm::StringRef(startSpecifier, specifierLen)
-      << getFormatRange();
+    HandleInvalidConversionSpecifier(FS, startSpecifier, specifierLen);
     
     // Continue checking the other format specifiers.
     return true;
   }
   
+  ++NumConversions;  
+  
   // Are we using '%n'?  Issue a warning about this being
   // a possible security issue.
   if (CS.getKind() == ConversionSpecifier::OutIntPtrArg) {





More information about the cfe-commits mailing list