]> granicus.if.org Git - clang/commitdiff
Add fix-it for format-security warnings.
authorBob Wilson <bob.wilson@apple.com>
Fri, 11 Mar 2016 21:55:37 +0000 (21:55 +0000)
committerBob Wilson <bob.wilson@apple.com>
Fri, 11 Mar 2016 21:55:37 +0000 (21:55 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@263299 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaChecking.cpp
test/Sema/format-strings-fixit.c
test/SemaObjC/format-strings-objc-fixit.m [new file with mode: 0644]

index eb5b5890495711128113800916f39d7b60211253..966d34939260fc7600dd71d90baa6cc1ecef2be4 100644 (file)
@@ -3621,20 +3621,32 @@ bool Sema::CheckFormatArguments(ArrayRef<const Expr *> Args,
   // format is either NSString or CFString. This is a hack to prevent
   // diag when using the NSLocalizedString and CFCopyLocalizedString macros
   // which are usually used in place of NS and CF string literals.
-  if (Type == FST_NSString &&
-      SourceMgr.isInSystemMacro(Args[format_idx]->getLocStart()))
+  SourceLocation FormatLoc = Args[format_idx]->getLocStart();
+  if (Type == FST_NSString && SourceMgr.isInSystemMacro(FormatLoc))
     return false;
 
   // If there are no arguments specified, warn with -Wformat-security, otherwise
   // warn only with -Wformat-nonliteral.
-  if (Args.size() == firstDataArg)
-    Diag(Args[format_idx]->getLocStart(),
-         diag::warn_format_nonliteral_noargs)
+  if (Args.size() == firstDataArg) {
+    const SemaDiagnosticBuilder &D =
+      Diag(FormatLoc, diag::warn_format_nonliteral_noargs);
+    switch (Type) {
+    default:
+      D << OrigFormatExpr->getSourceRange();
+      break;
+    case FST_Kprintf:
+    case FST_FreeBSDKPrintf:
+    case FST_Printf:
+      D << FixItHint::CreateInsertion(FormatLoc, "\"%s\", ");
+      break;
+    case FST_NSString:
+      D << FixItHint::CreateInsertion(FormatLoc, "@\"%@\", ");
+      break;
+    }
+  } else {
+    Diag(FormatLoc, diag::warn_format_nonliteral)
       << OrigFormatExpr->getSourceRange();
-  else
-    Diag(Args[format_idx]->getLocStart(),
-         diag::warn_format_nonliteral)
-           << OrigFormatExpr->getSourceRange();
+  }
   return false;
 }
 
index b982eb45e5f930aea025d598fbdbc39a594dd2af..fb617dd500fddff64c0d6c4c3474ffe413bbfbc1 100644 (file)
@@ -16,6 +16,8 @@ typedef __UINTMAX_TYPE__ uintmax_t;
 typedef __PTRDIFF_TYPE__ ptrdiff_t;
 typedef __WCHAR_TYPE__ wchar_t;
 
+extern const char *NonliteralString;
+
 void test() {
   // Basic types
   printf("%s", (int) 123);
@@ -94,6 +96,9 @@ void test() {
   printf("%G", (long double) 42);
   printf("%a", (long double) 42);
   printf("%A", (long double) 42);
+
+  // nonliteral format
+  printf(NonliteralString);
 }
 
 int scanf(char const *, ...);
@@ -218,6 +223,7 @@ void test2(int intSAParm[static 2]) {
 // CHECK: printf("%LG", (long double) 42);
 // CHECK: printf("%La", (long double) 42);
 // CHECK: printf("%LA", (long double) 42);
+// CHECK: printf("%s", NonliteralString);
 
 // CHECK: scanf("%99s", str);
 // CHECK: scanf("%s", vstr);
diff --git a/test/SemaObjC/format-strings-objc-fixit.m b/test/SemaObjC/format-strings-objc-fixit.m
new file mode 100644 (file)
index 0000000..feaebee
--- /dev/null
@@ -0,0 +1,31 @@
+// RUN: cp %s %t
+// RUN: %clang_cc1 -x objective-c -triple x86_64-apple-darwin -Wno-objc-root-class -pedantic -Wall -fixit %t
+// RUN: %clang_cc1 -x objective-c -triple x86_64-apple-darwin -Wno-objc-root-class -fsyntax-only -pedantic -Wall -Werror %t
+// RUN: %clang_cc1 -x objective-c -triple x86_64-apple-darwin -Wno-objc-root-class -E -o - %t | FileCheck %s
+
+typedef signed char BOOL;
+typedef unsigned int NSUInteger;
+typedef struct _NSZone NSZone;
+@class NSCoder, NSString, NSEnumerator;
+@protocol NSObject  - (BOOL)isEqual:(id)object; @end
+@protocol NSCopying  - (id)copyWithZone:(NSZone *)zone; @end
+@protocol NSMutableCopying  - (id)mutableCopyWithZone:(NSZone *)zone; @end
+@protocol NSCoding  - (void)encodeWithCoder:(NSCoder *)aCoder; @end
+@interface NSObject <NSObject> {} @end
+@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding>  - (NSUInteger)length; @end
+extern void NSLog(NSString *format, ...);
+
+/* This is a test of the various code modification hints that are
+   provided as part of warning or extension diagnostics. All of the
+   warnings will be fixed by -fixit, and the resulting file should
+   compile cleanly with -Werror -pedantic. */
+
+extern NSString *NonliteralString;
+
+void test() {
+  // nonliteral format
+  NSLog(NonliteralString);
+}
+
+// Validate the fixes.
+// CHECK: NSLog(@"%@", NonliteralString);