strcat() and strncat() model additions to CStringChecker.
Validates inputs are not NULL, checks for overlapping strings, concatenates the strings checking for buffer overflow, sets the length of the destination string to the sum of the s1 length and the s2 length, binds the return value to the s1 value.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@129215 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/Analysis/string.c b/test/Analysis/string.c
index 430145f..d9e0cf8 100644
--- a/test/Analysis/string.c
+++ b/test/Analysis/string.c
@@ -438,3 +438,161 @@
if (strlen(y) == 3)
stpcpy(x, y); // no-warning
}
+
+//===----------------------------------------------------------------------===
+// strcat()
+//===----------------------------------------------------------------------===
+
+#ifdef VARIANT
+
+#define __strcat_chk BUILTIN(__strcat_chk)
+char *__strcat_chk(char *restrict s1, const char *restrict s2, size_t destlen);
+
+#define strcat(a,b) __strcat_chk(a,b,(size_t)-1)
+
+#else /* VARIANT */
+
+#define strcat BUILTIN(strcat)
+char *strcat(char *restrict s1, const char *restrict s2);
+
+#endif /* VARIANT */
+
+
+void strcat_null_dst(char *x) {
+ strcat(NULL, x); // expected-warning{{Null pointer argument in call to byte string function}}
+}
+
+void strcat_null_src(char *x) {
+ strcat(x, NULL); // expected-warning{{Null pointer argument in call to byte string function}}
+}
+
+void strcat_fn(char *x) {
+ strcat(x, (char*)&strcat_fn); // expected-warning{{Argument to byte string function is the address of the function 'strcat_fn', which is not a null-terminated string}}
+}
+
+void strcat_effects(char *y) {
+ char x[8] = "123";
+ size_t orig_len = strlen(x);
+ char a = x[0];
+
+ if (strlen(y) != 4)
+ return;
+
+ if (strcat(x, y) != x)
+ (void)*(char*)0; // no-warning
+
+ if ((int)strlen(x) != (orig_len + strlen(y)))
+ (void)*(char*)0; // no-warning
+
+ if (a != x[0])
+ (void)*(char*)0; // expected-warning{{null}}
+}
+
+void strcat_overflow_0(char *y) {
+ char x[4] = "12";
+ if (strlen(y) == 4)
+ strcat(x, y); // expected-warning{{Byte string function overflows destination buffer}}
+}
+
+void strcat_overflow_1(char *y) {
+ char x[4] = "12";
+ if (strlen(y) == 3)
+ strcat(x, y); // expected-warning{{Byte string function overflows destination buffer}}
+}
+
+void strcat_overflow_2(char *y) {
+ char x[4] = "12";
+ if (strlen(y) == 2)
+ strcat(x, y); // expected-warning{{Byte string function overflows destination buffer}}
+}
+
+void strcat_no_overflow(char *y) {
+ char x[5] = "12";
+ if (strlen(y) == 2)
+ strcat(x, y); // no-warning
+}
+
+
+//===----------------------------------------------------------------------===
+// strncat()
+//===----------------------------------------------------------------------===
+
+#ifdef VARIANT
+
+#define __strncat_chk BUILTIN(__strncat_chk)
+char *__strncat_chk(char *restrict s1, const char *restrict s2, size_t n, size_t destlen);
+
+#define strncat(a,b,c) __strncat_chk(a,b,c, (size_t)-1)
+
+#else /* VARIANT */
+
+#define strncat BUILTIN(strncat)
+char *strncat(char *restrict s1, const char *restrict s2, size_t n);
+
+#endif /* VARIANT */
+
+
+void strncat_null_dst(char *x) {
+ strncat(NULL, x, 4); // expected-warning{{Null pointer argument in call to byte string function}}
+}
+
+void strncat_null_src(char *x) {
+ strncat(x, NULL, 4); // expected-warning{{Null pointer argument in call to byte string function}}
+}
+
+void strncat_fn(char *x) {
+ strncat(x, (char*)&strncat_fn, 4); // expected-warning{{Argument to byte string function is the address of the function 'strncat_fn', which is not a null-terminated string}}
+}
+
+void strncat_effects(char *y) {
+ char x[8] = "123";
+ size_t orig_len = strlen(x);
+ char a = x[0];
+
+ if (strlen(y) != 4)
+ return;
+
+ if (strncat(x, y, strlen(y)) != x)
+ (void)*(char*)0; // no-warning
+
+ if (strlen(x) != orig_len + strlen(y))
+ (void)*(char*)0; // no-warning
+
+ if (a != x[0])
+ (void)*(char*)0; // expected-warning{{null}}
+}
+
+void strncat_overflow_0(char *y) {
+ char x[4] = "12";
+ if (strlen(y) == 4)
+ strncat(x, y, strlen(y)); // expected-warning{{Byte string function overflows destination buffer}}
+}
+
+void strncat_overflow_1(char *y) {
+ char x[4] = "12";
+ if (strlen(y) == 3)
+ strncat(x, y, strlen(y)); // expected-warning{{Byte string function overflows destination buffer}}
+}
+
+void strncat_overflow_2(char *y) {
+ char x[4] = "12";
+ if (strlen(y) == 2)
+ strncat(x, y, strlen(y)); // expected-warning{{Byte string function overflows destination buffer}}
+}
+
+void strncat_overflow_3(char *y) {
+ char x[4] = "12";
+ if (strlen(y) == 4)
+ strncat(x, y, 2); // expected-warning{{Byte string function overflows destination buffer}}
+}
+void strncat_no_overflow_1(char *y) {
+ char x[5] = "12";
+ if (strlen(y) == 2)
+ strncat(x, y, strlen(y)); // no-warning
+}
+
+void strncat_no_overflow_2(char *y) {
+ char x[4] = "12";
+ if (strlen(y) == 4)
+ strncat(x, y, 1); // no-warning
+}