]> granicus.if.org Git - clang/commitdiff
Hook up 'invalid conversion' warning for scanf format strings.
authorTed Kremenek <kremenek@apple.com>
Mon, 19 Jul 2010 21:25:57 +0000 (21:25 +0000)
committerTed Kremenek <kremenek@apple.com>
Mon, 19 Jul 2010 21:25:57 +0000 (21:25 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@108750 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaChecking.cpp
test/Sema/format-strings-scanf.c

index 78a754ad609835679b8c076d23e985940aaf0bbf..d3c33e62f1f8eab559c2607e099092bbcd3bf610 100644 (file)
@@ -2936,7 +2936,7 @@ def warn_printf_insufficient_data_args : Warning<
   "more '%%' conversions than data arguments">, InGroup<Format>;
 def warn_printf_data_arg_not_used : Warning<
   "data argument not used by format string">, InGroup<FormatExtraArgs>;
-def warn_printf_invalid_conversion : Warning<
+def warn_format_invalid_conversion : Warning<
   "invalid conversion specifier '%0'">, InGroup<Format>;
 def warn_printf_incomplete_specifier : Warning<
   "incomplete format specifier">, InGroup<Format>;
index f1e501651e2a657ee949786d49641a0bd90bca54..f36a9ed938677c1d2effb6ea9293df4284d2ec88 100644 (file)
@@ -1160,6 +1160,11 @@ public:
   void HandleNullChar(const char *nullCharacter);
 
 protected:
+  bool HandleInvalidConversionSpecifier(unsigned argIndex, SourceLocation Loc,
+                                        const char *startSpec,
+                                        unsigned specifierLen,
+                                        const char *csStart, unsigned csLen);
+  
   SourceRange getFormatStringRange();
   CharSourceRange getSpecifierRange(const char *startSpecifier,
                                     unsigned specifierLen);
@@ -1237,6 +1242,36 @@ void CheckFormatHandler::DoneProcessing() {
   }
 }
 
+bool
+CheckFormatHandler::HandleInvalidConversionSpecifier(unsigned argIndex,
+                                                     SourceLocation Loc,
+                                                     const char *startSpec,
+                                                     unsigned specifierLen,
+                                                     const char *csStart,
+                                                     unsigned csLen) {
+  
+  bool keepGoing = true;
+  if (argIndex < NumDataArgs) {
+    // Consider the argument coverered, even though the specifier doesn't
+    // make sense.
+    CoveredArgs.set(argIndex);
+  }
+  else {
+    // If argIndex exceeds the number of data arguments we
+    // don't issue a warning because that is just a cascade of warnings (and
+    // they may have intended '%%' anyway). We don't want to continue processing
+    // the format string after this point, however, as we will like just get
+    // gibberish when trying to match arguments.
+    keepGoing = false;
+  }
+  
+  S.Diag(Loc, diag::warn_format_invalid_conversion)
+    << llvm::StringRef(csStart, csLen)
+    << getSpecifierRange(startSpec, specifierLen);
+  
+  return keepGoing;
+}
+
 //===--- CHECK: Printf format string checking ------------------------------===//
 
 namespace {
@@ -1281,31 +1316,13 @@ bool CheckPrintfHandler::HandleInvalidPrintfConversionSpecifier(
                                       const analyze_printf::PrintfSpecifier &FS,
                                       const char *startSpecifier,
                                       unsigned specifierLen) {
-  
-  unsigned argIndex = FS.getArgIndex();
-  bool keepGoing = true;
-  if (argIndex < NumDataArgs) {
-      // Consider the argument coverered, even though the specifier doesn't
-      // make sense.
-    CoveredArgs.set(argIndex);
-  }
-  else {
-    // If argIndex exceeds the number of data arguments we
-    // don't issue a warning because that is just a cascade of warnings (and
-    // they may have intended '%%' anyway). We don't want to continue processing
-    // the format string after this point, however, as we will like just get
-    // gibberish when trying to match arguments.
-    keepGoing = false;
-  }
-  
   const analyze_printf::ConversionSpecifier &CS =
-  FS.getConversionSpecifier();
-  SourceLocation Loc = getLocationOfByte(CS.getStart());
-  S.Diag(Loc, diag::warn_printf_invalid_conversion)
-  << llvm::StringRef(CS.getStart(), CS.getLength())
-  << getSpecifierRange(startSpecifier, specifierLen);
+    FS.getConversionSpecifier();
   
-  return keepGoing;
+  return HandleInvalidConversionSpecifier(FS.getArgIndex(),
+                                          getLocationOfByte(CS.getStart()),
+                                          startSpecifier, specifierLen,
+                                          CS.getStart(), CS.getLength());
 }
 
 bool CheckPrintfHandler::HandleAmount(
@@ -1596,6 +1613,11 @@ public:
   bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS,
                             const char *startSpecifier,
                             unsigned specifierLen);
+  
+  bool HandleInvalidScanfConversionSpecifier(
+          const analyze_scanf::ScanfSpecifier &FS,
+          const char *startSpecifier,
+          unsigned specifierLen);
 
   void HandleIncompleteScanList(const char *start, const char *end);
 };
@@ -1607,6 +1629,20 @@ void CheckScanfHandler::HandleIncompleteScanList(const char *start,
     << getSpecifierRange(start, end - start);
 }
 
+bool CheckScanfHandler::HandleInvalidScanfConversionSpecifier(
+                                        const analyze_scanf::ScanfSpecifier &FS,
+                                        const char *startSpecifier,
+                                        unsigned specifierLen) {
+
+  const analyze_scanf::ConversionSpecifier &CS =
+    FS.getConversionSpecifier();
+
+  return HandleInvalidConversionSpecifier(FS.getArgIndex(),
+                                          getLocationOfByte(CS.getStart()),
+                                          startSpecifier, specifierLen,
+                                          CS.getStart(), CS.getLength());
+}
+
 bool CheckScanfHandler::HandleScanfSpecifier(
                                        const analyze_scanf::ScanfSpecifier &FS,
                                        const char *startSpecifier,
index ac53d66bf63e6de7b8a98b46e136e66c731fc30a..5d2a7a7a9b21e62544049c0c874023c95b9b0fd4 100644 (file)
@@ -15,4 +15,5 @@ void test(const char *s, int *i) {
 
   unsigned short s_x;
   scanf ("%" "hu" "\n", &s_x); // no-warning
+  scanf("%y", i); // expected-warning{{invalid conversion specifier 'y'}}
 }