r204300 - scanf format checking: include the buffer length in the fix-it for %s.

Jordan Rose jordan_rose at apple.com
Wed Mar 19 20:32:40 PDT 2014


Author: jrose
Date: Wed Mar 19 22:32:39 2014
New Revision: 204300

URL: http://llvm.org/viewvc/llvm-project?rev=204300&view=rev
Log:
scanf format checking: include the buffer length in the fix-it for %s.

Patch by Zach Davis!

Modified:
    cfe/trunk/include/clang/Analysis/Analyses/FormatString.h
    cfe/trunk/lib/Analysis/ScanfFormatString.cpp
    cfe/trunk/lib/Sema/SemaChecking.cpp
    cfe/trunk/test/Sema/format-strings-fixit.c

Modified: cfe/trunk/include/clang/Analysis/Analyses/FormatString.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/FormatString.h?rev=204300&r1=204299&r2=204300&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/Analyses/FormatString.h (original)
+++ cfe/trunk/include/clang/Analysis/Analyses/FormatString.h Wed Mar 19 22:32:39 2014
@@ -572,7 +572,8 @@ public:
 
   ArgType getArgType(ASTContext &Ctx) const;
 
-  bool fixType(QualType QT, const LangOptions &LangOpt, ASTContext &Ctx);
+  bool fixType(QualType QT, QualType RawQT, const LangOptions &LangOpt,
+               ASTContext &Ctx);
 
   void toString(raw_ostream &os) const;
 

Modified: cfe/trunk/lib/Analysis/ScanfFormatString.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ScanfFormatString.cpp?rev=204300&r1=204299&r2=204300&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/ScanfFormatString.cpp (original)
+++ cfe/trunk/lib/Analysis/ScanfFormatString.cpp Wed Mar 19 22:32:39 2014
@@ -379,21 +379,23 @@ ArgType ScanfSpecifier::getArgType(ASTCo
   return ArgType();
 }
 
-bool ScanfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
+bool ScanfSpecifier::fixType(QualType QT, QualType RawQT,
+                             const LangOptions &LangOpt,
                              ASTContext &Ctx) {
-  if (!QT->isPointerType())
-    return false;
 
   // %n is different from other conversion specifiers; don't try to fix it.
   if (CS.getKind() == ConversionSpecifier::nArg)
     return false;
 
+  if (!QT->isPointerType())
+    return false;
+
   QualType PT = QT->getPointeeType();
 
   // If it's an enum, get its underlying type.
-  if (const EnumType *ETy = QT->getAs<EnumType>())
-    QT = ETy->getDecl()->getIntegerType();
-  
+  if (const EnumType *ETy = PT->getAs<EnumType>())
+    PT = ETy->getDecl()->getIntegerType();
+
   const BuiltinType *BT = PT->getAs<BuiltinType>();
   if (!BT)
     return false;
@@ -405,6 +407,15 @@ bool ScanfSpecifier::fixType(QualType QT
       LM.setKind(LengthModifier::AsWideChar);
     else
       LM.setKind(LengthModifier::None);
+
+    // If we know the target array length, we can use it as a field width.
+    if (const ConstantArrayType *CAT = Ctx.getAsConstantArrayType(RawQT)) {
+      if (CAT->getSizeModifier() == ArrayType::Normal)
+        FieldWidth = OptionalAmount(OptionalAmount::Constant,
+                                    CAT->getSize().getZExtValue() - 1,
+                                    "", 0, false);
+
+    }
     return true;
   }
 

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=204300&r1=204299&r2=204300&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Wed Mar 19 22:32:39 2014
@@ -3518,8 +3518,9 @@ bool CheckScanfHandler::HandleScanfSpeci
   const analyze_format_string::ArgType &AT = FS.getArgType(S.Context);
   if (AT.isValid() && !AT.matchesType(S.Context, Ex->getType())) {
     ScanfSpecifier fixedFS = FS;
-    bool success = fixedFS.fixType(Ex->getType(), S.getLangOpts(),
-                                   S.Context);
+    bool success = fixedFS.fixType(Ex->getType(),
+                                   Ex->IgnoreImpCasts()->getType(),
+                                   S.getLangOpts(), S.Context);
 
     if (success) {
       // Get the fix string from the fixed format specifier.

Modified: cfe/trunk/test/Sema/format-strings-fixit.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/format-strings-fixit.c?rev=204300&r1=204299&r2=204300&view=diff
==============================================================================
--- cfe/trunk/test/Sema/format-strings-fixit.c (original)
+++ cfe/trunk/test/Sema/format-strings-fixit.c Wed Mar 19 22:32:39 2014
@@ -14,6 +14,7 @@ typedef __SIZE_TYPE__ size_t;
 typedef __INTMAX_TYPE__ intmax_t;
 typedef __UINTMAX_TYPE__ uintmax_t;
 typedef __PTRDIFF_TYPE__ ptrdiff_t;
+typedef __WCHAR_TYPE__ wchar_t;
 
 void test() {
   // Basic types
@@ -97,11 +98,14 @@ void test() {
 
 int scanf(char const *, ...);
 
-void test2() {
+void test2(int intSAParm[static 2]) {
   char str[100];
+  char *vstr = "abc";
+  wchar_t wstr[100];
   short shortVar;
   unsigned short uShortVar;
   int intVar;
+  int intAVar[2];
   unsigned uIntVar;
   float floatVar;
   double doubleVar;
@@ -114,11 +118,22 @@ void test2() {
   intmax_t intmaxVar;
   uintmax_t uIntmaxVar;
   ptrdiff_t ptrdiffVar;
+  enum {A, B, C} enumVar;
 
+  // Some string types.
   scanf("%lf", str);
+  scanf("%lf", vstr);
+  scanf("%ls", str);
+  scanf("%f", wstr); // FIXME: wchar_t should resolve to %ls, not %d.
+  scanf("%s", wstr); // FIXME: wchar_t should resolve to %ls, not %d.
+  scanf("%ls", str);
+
+  // Some integer types.
   scanf("%f", &shortVar);
   scanf("%f", &uShortVar);
   scanf("%p", &intVar);
+  scanf("%f", intAVar);
+  scanf("%f", intSAParm);
   scanf("%Lf", &uIntVar);
   scanf("%ld", &floatVar);
   scanf("%f", &doubleVar);
@@ -127,6 +142,7 @@ void test2() {
   scanf("%f", &uLongVar);
   scanf("%f", &longLongVar);
   scanf("%f", &uLongLongVar);
+  scanf("%d", &enumVar); // FIXME: We ought to fix specifiers for enums.
 
   // Some named ints.
   scanf("%f", &sizeVar);
@@ -206,10 +222,17 @@ void test2() {
 // CHECK: printf("%La", (long double) 42);
 // CHECK: printf("%LA", (long double) 42);
 
-// CHECK: scanf("%s", str);
+// CHECK: scanf("%99s", str);
+// CHECK: scanf("%s", vstr);
+// CHECK: scanf("%99s", str);
+// CHECK: scanf("%d", wstr);
+// CHECK: scanf("%d", wstr);
+// CHECK: scanf("%99s", str);
 // CHECK: scanf("%hd", &shortVar);
 // CHECK: scanf("%hu", &uShortVar);
 // CHECK: scanf("%d", &intVar);
+// CHECK: scanf("%d", intAVar);
+// CHECK: scanf("%d", intSAParm);
 // CHECK: scanf("%u", &uIntVar);
 // CHECK: scanf("%f", &floatVar);
 // CHECK: scanf("%lf", &doubleVar);
@@ -218,6 +241,7 @@ void test2() {
 // CHECK: scanf("%lu", &uLongVar);
 // CHECK: scanf("%lld", &longLongVar);
 // CHECK: scanf("%llu", &uLongLongVar);
+// CHECK: scanf("%d", &enumVar);
 // CHECK: scanf("%zu", &sizeVar);
 // CHECK: scanf("%jd", &intmaxVar);
 // CHECK: scanf("%ju", &uIntmaxVar);





More information about the cfe-commits mailing list