Check that arguments to a scanf call match the format specifier,
and offer fixits when there is a mismatch.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146326 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/Analysis/taint-generic.c b/test/Analysis/taint-generic.c
index eeec886..9c99f90 100644
--- a/test/Analysis/taint-generic.c
+++ b/test/Analysis/taint-generic.c
@@ -39,7 +39,8 @@
void scanfArg() {
int t;
- scanf("%d", t); // expected-warning {{Pointer argument is expected}}
+ scanf("%d", t); // expected-warning {{Pointer argument is expected}} \
+ // expected-warning {{conversion specifies type 'int *' but the argument has type 'int'}}
}
void bufferGetchar(int x) {
diff --git a/test/Analysis/taint-tester.c b/test/Analysis/taint-tester.c
index 8a82cd3..da1ff02 100644
--- a/test/Analysis/taint-tester.c
+++ b/test/Analysis/taint-tester.c
@@ -49,8 +49,8 @@
// Taint on fields of a struct.
struct XYStruct xy = {2, 3, 11};
- scanf("%f", &xy.y);
- scanf("%f", &xy.x);
+ scanf("%d", &xy.y);
+ scanf("%d", &xy.x);
int tx = xy.x; // expected-warning {{tainted}}
int ty = xy.y; // FIXME: This should be tainted as well.
char ntz = xy.z;// no warning
diff --git a/test/Sema/format-strings-fixit.c b/test/Sema/format-strings-fixit.c
index bfb5432..4fb6d75 100644
--- a/test/Sema/format-strings-fixit.c
+++ b/test/Sema/format-strings-fixit.c
@@ -10,6 +10,11 @@
int printf(char const *, ...);
+typedef __SIZE_TYPE__ size_t;
+typedef __INTMAX_TYPE__ intmax_t;
+typedef __UINTMAX_TYPE__ uintmax_t;
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+
void test() {
// Basic types
printf("%s", (int) 123);
@@ -47,11 +52,6 @@
unsigned long val = 42;
printf("%X", val);
- typedef __SIZE_TYPE__ size_t;
- typedef __INTMAX_TYPE__ intmax_t;
- typedef __UINTMAX_TYPE__ uintmax_t;
- typedef __PTRDIFF_TYPE__ ptrdiff_t;
-
// size_t, etc.
printf("%f", (size_t) 42);
printf("%f", (intmax_t) 42);
@@ -62,6 +62,51 @@
printf("%ld", "foo");
}
+int scanf(char const *, ...);
+
+void test2() {
+ char str[100];
+ short shortVar;
+ unsigned short uShortVar;
+ int intVar;
+ unsigned uIntVar;
+ float floatVar;
+ double doubleVar;
+ long double longDoubleVar;
+ long longVar;
+ unsigned long uLongVar;
+ long long longLongVar;
+ unsigned long long uLongLongVar;
+ size_t sizeVar;
+ intmax_t intmaxVar;
+ uintmax_t uIntmaxVar;
+ ptrdiff_t ptrdiffVar;
+
+ scanf("%lf", str);
+ scanf("%f", &shortVar);
+ scanf("%f", &uShortVar);
+ scanf("%p", &intVar);
+ scanf("%Lf", &uIntVar);
+ scanf("%ld", &floatVar);
+ scanf("%f", &doubleVar);
+ scanf("%d", &longDoubleVar);
+ scanf("%f", &longVar);
+ scanf("%f", &uLongVar);
+ scanf("%f", &longLongVar);
+ scanf("%f", &uLongLongVar);
+
+ // Some named ints.
+ scanf("%f", &sizeVar);
+ scanf("%f", &intmaxVar);
+ scanf("%f", &uIntmaxVar);
+ scanf("%f", &ptrdiffVar);
+
+ // Perserve the original formatting for unsigned integers.
+ scanf("%o", &uLongVar);
+ scanf("%x", &uLongVar);
+ scanf("%X", &uLongVar);
+}
+
// Validate the fixes...
// CHECK: printf("%d", (int) 123);
// CHECK: printf("abc%s", "testing testing 123");
@@ -87,3 +132,23 @@
// CHECK: printf("%ju", (uintmax_t) 42);
// CHECK: printf("%td", (ptrdiff_t) 42);
// CHECK: printf("%s", "foo");
+
+// CHECK: scanf("%s", str);
+// CHECK: scanf("%hd", &shortVar);
+// CHECK: scanf("%hu", &uShortVar);
+// CHECK: scanf("%d", &intVar);
+// CHECK: scanf("%u", &uIntVar);
+// CHECK: scanf("%f", &floatVar);
+// CHECK: scanf("%lf", &doubleVar);
+// CHECK: scanf("%Lf", &longDoubleVar);
+// CHECK: scanf("%ld", &longVar);
+// CHECK: scanf("%lu", &uLongVar);
+// CHECK: scanf("%lld", &longLongVar);
+// CHECK: scanf("%llu", &uLongLongVar);
+// CHECK: scanf("%zu", &sizeVar);
+// CHECK: scanf("%jd", &intmaxVar);
+// CHECK: scanf("%ju", &uIntmaxVar);
+// CHECK: scanf("%td", &ptrdiffVar);
+// CHECK: scanf("%lo", &uLongVar);
+// CHECK: scanf("%lx", &uLongVar);
+// CHECK: scanf("%lX", &uLongVar);
diff --git a/test/Sema/format-strings-int-typedefs.c b/test/Sema/format-strings-int-typedefs.c
index 2568b8d..8d5dff1 100644
--- a/test/Sema/format-strings-int-typedefs.c
+++ b/test/Sema/format-strings-int-typedefs.c
@@ -1,6 +1,7 @@
// RUN: %clang_cc1 -triple i386-apple-darwin9 -fsyntax-only -verify %s
int printf(char const *, ...);
+int scanf(char const *, ...);
void test(void) {
printf("%jd", 42.0); // expected-warning {{conversion specifies type 'intmax_t' (aka 'long long')}}
@@ -12,6 +13,15 @@
printf("%S", 42.0); // expected-warning {{conversion specifies type 'wchar_t *' (aka 'int *')}}
printf("%C", 42.0); // expected-warning {{conversion specifies type 'wchar_t' (aka 'int')}}
+ scanf("%jd", 0); // expected-warning {{conversion specifies type 'intmax_t *' (aka 'long long *')}}
+ scanf("%ju", 0); // expected-warning {{conversion specifies type 'uintmax_t *' (aka 'unsigned long long *')}}
+ scanf("%zu", 0); // expected-warning {{conversion specifies type 'size_t *' (aka 'unsigned long *')}}
+ scanf("%td", 0); // expected-warning {{conversion specifies type 'ptrdiff_t *' (aka 'int *')}}
+ scanf("%lc", 0); // expected-warning {{conversion specifies type 'wchar_t *' (aka 'int *')}}
+ scanf("%ls", 0); // expected-warning {{conversion specifies type 'wchar_t *' (aka 'int *')}}
+ scanf("%S", 0); // expected-warning {{conversion specifies type 'wchar_t *' (aka 'int *')}}
+ scanf("%C", 0); // expected-warning {{conversion specifies type 'wchar_t *' (aka 'int *')}}
+
// typedef size_t et al. to something crazy.
typedef void *size_t;
diff --git a/test/Sema/format-strings-scanf.c b/test/Sema/format-strings-scanf.c
index ee559da..4675862 100644
--- a/test/Sema/format-strings-scanf.c
+++ b/test/Sema/format-strings-scanf.c
@@ -28,7 +28,7 @@
void bad_length_modifiers(char *s, void *p, wchar_t *ws, long double *ld) {
scanf("%hhs", "foo"); // expected-warning{{length modifier 'hh' results in undefined behavior or no effect with 's' conversion specifier}}
- scanf("%1$zp", p); // expected-warning{{length modifier 'z' results in undefined behavior or no effect with 'p' conversion specifier}}
+ scanf("%1$zp", &p); // expected-warning{{length modifier 'z' results in undefined behavior or no effect with 'p' conversion specifier}}
scanf("%ls", ws); // no-warning
scanf("%#.2Lf", ld); // expected-warning{{invalid conversion specifier '#'}}
}
@@ -37,10 +37,11 @@
// format string is somewhere else, point to it in a note.
void pr9751() {
int *i;
+ char str[100];
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}}
+ scanf(kFormat2, str); // expected-warning{{no closing ']' for '%[' in scanf format string}}
+ scanf("%[", str); // expected-warning{{no closing ']' for '%[' in scanf format string}}
}