diff options
Diffstat (limited to 'clang/test/Sema')
| -rw-r--r-- | clang/test/Sema/format-strings-no-fixit.c | 65 | ||||
| -rw-r--r-- | clang/test/Sema/format-strings-scanf.c | 12 | ||||
| -rw-r--r-- | clang/test/Sema/format-strings.c | 76 |
3 files changed, 153 insertions, 0 deletions
diff --git a/clang/test/Sema/format-strings-no-fixit.c b/clang/test/Sema/format-strings-no-fixit.c new file mode 100644 index 00000000000..701e945f690 --- /dev/null +++ b/clang/test/Sema/format-strings-no-fixit.c @@ -0,0 +1,65 @@ +// RUN: cp %s %t +// RUN: %clang_cc1 -fsyntax-only -fixit %t +// RUN: %clang_cc1 -E -o - %t | FileCheck %s + +/* This is a test of the various code modification hints that are + provided as part of warning or extension diagnostics. Only + warnings for format strings within the function call will be + fixed by -fixit. Other format strings will be left alone. */ + +int printf(char const *, ...); +int scanf(char const *, ...); + +void pr9751() { + const char kFormat1[] = "%s"; + printf(kFormat1, 5); + printf("%s", 5); + + const char kFormat2[] = "%.3p"; + void *p; + printf(kFormat2, p); + printf("%.3p", p); + + const char kFormat3[] = "%0s"; + printf(kFormat3, "a"); + printf("%0s", "a"); + + const char kFormat4[] = "%hhs"; + printf(kFormat4, "a"); + printf("%hhs", "a"); + + const char kFormat5[] = "%-0d"; + printf(kFormat5, 5); + printf("%-0d", 5); + + const char kFormat6[] = "%00d"; + int *i; + scanf(kFormat6, i); + scanf("%00d", i); +} + +// CHECK: const char kFormat1[] = "%s"; +// CHECK: printf(kFormat1, 5); +// CHECK: printf("%d", 5); + +// CHECK: const char kFormat2[] = "%.3p"; +// CHECK: void *p; +// CHECK: printf(kFormat2, p); +// CHECK: printf("%p", p); + +// CHECK: const char kFormat3[] = "%0s"; +// CHECK: printf(kFormat3, "a"); +// CHECK: printf("%s", "a"); + +// CHECK: const char kFormat4[] = "%hhs"; +// CHECK: printf(kFormat4, "a"); +// CHECK: printf("%s", "a"); + +// CHECK: const char kFormat5[] = "%-0d"; +// CHECK: printf(kFormat5, 5); +// CHECK: printf("%-d", 5); + +// CHECK: const char kFormat6[] = "%00d"; +// CHECK: int *i; +// CHECK: scanf(kFormat6, i); +// CHECK: scanf("%d", i); diff --git a/clang/test/Sema/format-strings-scanf.c b/clang/test/Sema/format-strings-scanf.c index 42b6c03ffbf..ee559daef61 100644 --- a/clang/test/Sema/format-strings-scanf.c +++ b/clang/test/Sema/format-strings-scanf.c @@ -32,3 +32,15 @@ void bad_length_modifiers(char *s, void *p, wchar_t *ws, long double *ld) { scanf("%ls", ws); // no-warning scanf("%#.2Lf", ld); // expected-warning{{invalid conversion specifier '#'}} } + +// Test that the scanf call site is where the warning is attached. If the +// format string is somewhere else, point to it in a note. +void pr9751() { + int *i; + const char kFormat1[] = "%00d"; // expected-note{{format string is defined here}}} + scanf(kFormat1, i); // expected-warning{{zero field width in scanf format string is unused}} + scanf("%00d", i); // expected-warning{{zero field width in scanf format string is unused}} + const char kFormat2[] = "%["; // expected-note{{format string is defined here}}} + scanf(kFormat2, &i); // expected-warning{{no closing ']' for '%[' in scanf format string}} + scanf("%[", &i); // expected-warning{{no closing ']' for '%[' in scanf format string}} +} diff --git a/clang/test/Sema/format-strings.c b/clang/test/Sema/format-strings.c index 4f2ad99a572..c4bbc836d45 100644 --- a/clang/test/Sema/format-strings.c +++ b/clang/test/Sema/format-strings.c @@ -393,3 +393,79 @@ void test_suppress_invalid_specifier() { #pragma clang diagnostic pop } +// Make sure warnings are on for next test. +#pragma GCC diagnostic warning "-Wformat" +#pragma GCC diagnostic warning "-Wformat-security" + +// Test that the printf call site is where the warning is attached. If the +// format string is somewhere else, point to it in a note. +void pr9751() { + const char kFormat1[] = "%d %d \n"; // expected-note{{format string is defined here}}} + printf(kFormat1, 0); // expected-warning{{more '%' conversions than data arguments}} + printf("%d %s\n", 0); // expected-warning{{more '%' conversions than data arguments}} + + const char kFormat2[] = "%18$s\n"; // expected-note{{format string is defined here}} + printf(kFormat2, 1, "foo"); // expected-warning{{data argument position '18' exceeds the number of data arguments (2)}} + printf("%18$s\n", 1, "foo"); // expected-warning{{data argument position '18' exceeds the number of data arguments (2)}} + + const char kFormat3[] = "%n"; // expected-note{{format string is defined here}} + printf(kFormat3, "as"); // expected-warning{{use of '%n' in format string discouraged}} + printf("%n", "as"); // expected-warning{{use of '%n' in format string discouraged}} + + const char kFormat4[] = "%y"; // expected-note{{format string is defined here}} + printf(kFormat4, 5); // expected-warning{{invalid conversion specifier 'y'}} + printf("%y", 5); // expected-warning{{invalid conversion specifier 'y'}} + + const char kFormat5[] = "%."; // expected-note{{format string is defined here}} + printf(kFormat5, 5); // expected-warning{{incomplete format specifier}} + printf("%.", 5); // expected-warning{{incomplete format specifier}} + + const char kFormat6[] = "%s"; // expected-note{{format string is defined here}} + printf(kFormat6, 5); // expected-warning{{conversion specifies type 'char *' but the argument has type 'int'}} + printf("%s", 5); // expected-warning{{conversion specifies type 'char *' but the argument has type 'int'}} + + const char kFormat7[] = "%0$"; // expected-note{{format string is defined here}} + printf(kFormat7, 5); // expected-warning{{position arguments in format strings start counting at 1 (not 0)}} + printf("%0$", 5); // expected-warning{{position arguments in format strings start counting at 1 (not 0)}} + + const char kFormat8[] = "%1$d %d"; // expected-note{{format string is defined here}} + printf(kFormat8, 4, 4); // expected-warning{{cannot mix positional and non-positional arguments in format string}} + printf("%1$d %d", 4, 4); // expected-warning{{cannot mix positional and non-positional arguments in format string}} + + const char kFormat9[] = ""; // expected-note{{format string is defined here}} + printf(kFormat9, 4, 4); // expected-warning{{format string is empty}} + printf("", 4, 4); // expected-warning{{format string is empty}} + + const char kFormat10[] = "\0%d"; // expected-note{{format string is defined here}} + printf(kFormat10, 4); // expected-warning{{format string contains '\0' within the string body}} + printf("\0%d", 4); // expected-warning{{format string contains '\0' within the string body}} + + const char kFormat11[] = "%*d"; // expected-note{{format string is defined here}} + printf(kFormat11); // expected-warning{{'*' specified field width is missing a matching 'int' argument}} + printf("%*d"); // expected-warning{{'*' specified field width is missing a matching 'int' argument}} + + const char kFormat12[] = "%*d"; // expected-note{{format string is defined here}} + printf(kFormat12, 4.4); // expected-warning{{field width should have type 'int', but argument has type 'double'}} + printf("%*d", 4.4); // expected-warning{{field width should have type 'int', but argument has type 'double'}} + + const char kFormat13[] = "%.3p"; // expected-note{{format string is defined here}} + void *p; + printf(kFormat13, p); // expected-warning{{precision used with 'p' conversion specifier, resulting in undefined behavior}} + printf("%.3p", p); // expected-warning{{precision used with 'p' conversion specifier, resulting in undefined behavior}} + + const char kFormat14[] = "%0s"; // expected-note{{format string is defined here}} + printf(kFormat14, "a"); // expected-warning{{flag '0' results in undefined behavior with 's' conversion specifier}} + printf("%0s", "a"); // expected-warning{{flag '0' results in undefined behavior with 's' conversion specifier}} + + const char kFormat15[] = "%hhs"; // expected-note{{format string is defined here}} + printf(kFormat15, "a"); // expected-warning{{length modifier 'hh' results in undefined behavior or no effect with 's' conversion specifier}} + printf("%hhs", "a"); // expected-warning{{length modifier 'hh' results in undefined behavior or no effect with 's' conversion specifier}} + + const char kFormat16[] = "%-0d"; // expected-note{{format string is defined here}} + printf(kFormat16, 5); // expected-warning{{flag '0' is ignored when flag '-' is present}} + printf("%-0d", 5); // expected-warning{{flag '0' is ignored when flag '-' is present}} + + // Make sure that the "format string is defined here" note is not emitted + // when the original string is within the argument expression. + printf(1 ? "yes %d" : "no %d"); // expected-warning 2{{more '%' conversions than data arguments}} +} |

