Model the effects of strcpy() and stpcpy() in CStringChecker. Other changes:
- Fix memcpy() and friends to actually invalidate the destination buffer.
- Emit a different message for out-of-bounds buffer accesses if the buffer is being written to.
- When conjuring symbols, let ValueManager figure out the type.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111120 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/Analysis/string.c b/test/Analysis/string.c
index af43c4b..35ed710 100644
--- a/test/Analysis/string.c
+++ b/test/Analysis/string.c
@@ -24,6 +24,7 @@
# define BUILTIN(f) f
#endif /* USE_BUILTINS */
+#define NULL 0
typedef typeof(sizeof(int)) size_t;
//===----------------------------------------------------------------------===
@@ -137,3 +138,103 @@
if (strlen(x) < 5)
(void)*(char*)0; // no-warning
}
+
+//===----------------------------------------------------------------------===
+// strcpy()
+//===----------------------------------------------------------------------===
+
+#ifdef VARIANT
+
+#define __strcpy_chk BUILTIN(__strcpy_chk)
+char *__strcpy_chk(char *restrict s1, const char *restrict s2, size_t destlen);
+
+#define strcpy(a,b) __strcpy_chk(a,b,(size_t)-1)
+
+#else /* VARIANT */
+
+#define strcpy BUILTIN(strcpy)
+char *strcpy(char *restrict s1, const char *restrict s2);
+
+#endif /* VARIANT */
+
+
+void strcpy_null_dst(char *x) {
+ strcpy(NULL, x); // expected-warning{{Null pointer argument in call to byte string function}}
+}
+
+void strcpy_null_src(char *x) {
+ strcpy(x, NULL); // expected-warning{{Null pointer argument in call to byte string function}}
+}
+
+void strcpy_fn(char *x) {
+ strcpy(x, (char*)&strcpy_fn); // expected-warning{{Argument to byte string function is the address of the function 'strcpy_fn', which is not a null-terminated string}}
+}
+
+void strcpy_effects(char *x, char *y) {
+ char a = x[0];
+
+ if (strcpy(x, y) != x)
+ (void)*(char*)0; // no-warning
+
+ if (strlen(x) != strlen(y))
+ (void)*(char*)0; // no-warning
+
+ if (a != x[0])
+ (void)*(char*)0; // expected-warning{{null}}
+}
+
+void strcpy_overflow(char *y) {
+ char x[4];
+ if (strlen(y) == 4)
+ strcpy(x, y); // expected-warning{{Byte string function overflows destination buffer}}
+}
+
+void strcpy_no_overflow(char *y) {
+ char x[4];
+ if (strlen(y) == 3)
+ strcpy(x, y); // no-warning
+}
+
+//===----------------------------------------------------------------------===
+// stpcpy()
+//===----------------------------------------------------------------------===
+
+#ifdef VARIANT
+
+#define __stpcpy_chk BUILTIN(__stpcpy_chk)
+char *__stpcpy_chk(char *restrict s1, const char *restrict s2, size_t destlen);
+
+#define stpcpy(a,b) __stpcpy_chk(a,b,(size_t)-1)
+
+#else /* VARIANT */
+
+#define stpcpy BUILTIN(stpcpy)
+char *stpcpy(char *restrict s1, const char *restrict s2);
+
+#endif /* VARIANT */
+
+
+void stpcpy_effect(char *x, char *y) {
+ char a = x[0];
+
+ if (stpcpy(x, y) != &x[strlen(y)])
+ (void)*(char*)0; // no-warning
+
+ if (strlen(x) != strlen(y))
+ (void)*(char*)0; // no-warning
+
+ if (a != x[0])
+ (void)*(char*)0; // expected-warning{{null}}
+}
+
+void stpcpy_overflow(char *y) {
+ char x[4];
+ if (strlen(y) == 4)
+ stpcpy(x, y); // expected-warning{{Byte string function overflows destination buffer}}
+}
+
+void stpcpy_no_overflow(char *y) {
+ char x[4];
+ if (strlen(y) == 3)
+ stpcpy(x, y); // no-warning
+}