Jaysonyan created this revision.
Jaysonyan added reviewers: leonardchan, phosek.
Jaysonyan requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This warning is to dissuade developers from using the potentially unsafe %n
format specifier. Currently this warning is surfaced under the flag 
-Wformat-n-specifier
which is enabled under the group -Wformat. The way this information is surfaced 
is pending
discussion from this RFC: 
https://lists.llvm.org/pipermail/cfe-dev/2021-September/068986.html.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D110436

Files:
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaChecking.cpp
  clang/test/FixIt/format.m
  clang/test/Misc/warning-wall.c
  clang/test/Sema/format-string-percentn.c
  clang/test/Sema/format-strings-size_t.c
  clang/test/Sema/format-strings.c

Index: clang/test/Sema/format-strings.c
===================================================================
--- clang/test/Sema/format-strings.c
+++ clang/test/Sema/format-strings.c
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -isystem %S/Inputs %s
-// RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -isystem %S/Inputs -fno-signed-char %s
+// RUN: %clang_cc1 -fsyntax-only -verify -Wno-format-n-specifier -Wformat-nonliteral -isystem %S/Inputs %s
+// RUN: %clang_cc1 -fsyntax-only -verify -Wno-format-n-specifier -Wformat-nonliteral -isystem %S/Inputs -fno-signed-char %s
 
 #include <stdarg.h>
 #include <stddef.h>
@@ -644,6 +644,7 @@
   test14_bar("%", "%d", p); // expected-warning{{incomplete format specifier}}
 }
 
+#pragma GCC diagnostic ignored "-Wformat-n-specifier"
 void test_qualifiers(volatile int *vip, const int *cip,
                      const volatile int *cvip) {
   printf("%n", cip); // expected-warning{{format specifies type 'int *' but the argument has type 'const int *'}}
Index: clang/test/Sema/format-strings-size_t.c
===================================================================
--- clang/test/Sema/format-strings-size_t.c
+++ clang/test/Sema/format-strings-size_t.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -Wno-format-n-specifier -fsyntax-only -verify %s
 
 int printf(char const *, ...);
 
Index: clang/test/Sema/format-string-percentn.c
===================================================================
--- /dev/null
+++ clang/test/Sema/format-string-percentn.c
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+int printf(const char *restrict, ...);
+void percentn(volatile int *n) {
+  printf("%n", n); //expected-warning{{usage of '%n' is unsafe}}
+}
Index: clang/test/Misc/warning-wall.c
===================================================================
--- clang/test/Misc/warning-wall.c
+++ clang/test/Misc/warning-wall.c
@@ -17,6 +17,7 @@
 CHECK-NEXT:      -Wformat-y2k
 CHECK-NEXT:      -Wformat-invalid-specifier
 CHECK-NEXT:      -Wformat-insufficient-args
+CHECK-NEXT:      -Wformat-n-specifier
 CHECK-NEXT:    -Wfor-loop-analysis
 CHECK-NEXT:    -Wframe-address
 CHECK-NEXT:    -Wimplicit
Index: clang/test/FixIt/format.m
===================================================================
--- clang/test/FixIt/format.m
+++ clang/test/FixIt/format.m
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -triple %itanium_abi_triple -fsyntax-only -fblocks -verify %s
-// RUN: %clang_cc1 -triple %itanium_abi_triple -fdiagnostics-parseable-fixits -fblocks %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -triple %itanium_abi_triple -Wno-format-n-specifier -fsyntax-only -fblocks -verify %s
+// RUN: %clang_cc1 -triple %itanium_abi_triple -Wno-format-n-specifier -fdiagnostics-parseable-fixits -fblocks %s 2>&1 | FileCheck %s
 
 @class NSString;
 extern void NSLog(NSString *, ...);
Index: clang/lib/Sema/SemaChecking.cpp
===================================================================
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -8965,6 +8965,13 @@
     return true;
   }
 
+  // %n is unsafe
+  if (CS.getKind() == ConversionSpecifier::nArg) {
+    EmitFormatDiagnostic(
+      S.PDiag(diag::warn_printf_n_specifier), getLocationOfByte(CS.getStart()), /*IsStringLocation*/true,
+      getSpecifierRange(startSpecifier, specifierLen));
+  }
+
   // Only scalars are allowed for os_trace.
   if (FSType == Sema::FST_OSTrace &&
       (CS.getKind() == ConversionSpecifier::PArg ||
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9226,6 +9226,8 @@
 
 def warn_printf_insufficient_data_args : Warning<
   "more '%%' conversions than data arguments">, InGroup<FormatInsufficientArgs>;
+def warn_printf_n_specifier : Warning<
+  "usage of '%%n' is unsafe">, InGroup<FormatNSpecifier>;
 def warn_printf_data_arg_not_used : Warning<
   "data argument not used by format string">, InGroup<FormatExtraArgs>;
 def warn_format_invalid_conversion : Warning<
Index: clang/include/clang/Basic/DiagnosticGroups.td
===================================================================
--- clang/include/clang/Basic/DiagnosticGroups.td
+++ clang/include/clang/Basic/DiagnosticGroups.td
@@ -250,6 +250,7 @@
 def GNUFlexibleArrayUnionMember : DiagGroup<"gnu-flexible-array-union-member">;
 def GNUFoldingConstant : DiagGroup<"gnu-folding-constant">;
 def FormatInsufficientArgs : DiagGroup<"format-insufficient-args">;
+def FormatNSpecifier : DiagGroup<"format-n-specifier">;
 def FormatExtraArgs : DiagGroup<"format-extra-args">;
 def FormatZeroLength : DiagGroup<"format-zero-length">;
 
@@ -900,7 +901,7 @@
 def Format : DiagGroup<"format",
                        [FormatExtraArgs, FormatZeroLength, NonNull,
                         FormatSecurity, FormatY2K, FormatInvalidSpecifier,
-                        FormatInsufficientArgs]>,
+                        FormatInsufficientArgs, FormatNSpecifier]>,
              DiagCategory<"Format String Issue">;
 def FormatNonLiteral : DiagGroup<"format-nonliteral">;
 def Format2 : DiagGroup<"format=2",
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to