[analyzer] Finish size argument checking for strncat (and strncpy).


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133472 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/Analysis/string.c b/test/Analysis/string.c
index c755d5e..250989f 100644
--- a/test/Analysis/string.c
+++ b/test/Analysis/string.c
@@ -604,25 +604,25 @@
 void strncat_overflow_0(char *y) {
   char x[4] = "12";
   if (strlen(y) == 4)
-    strncat(x, y, strlen(y)); // expected-warning{{String copy function overflows destination buffer}}
+    strncat(x, y, strlen(y)); // expected-warning{{Size argument is greater than the free space in the destination buffer}}
 }
 
 void strncat_overflow_1(char *y) {
   char x[4] = "12";
   if (strlen(y) == 3)
-    strncat(x, y, strlen(y)); // expected-warning{{String copy function overflows destination buffer}}
+    strncat(x, y, strlen(y)); // expected-warning{{Size argument is greater than the free space in the destination buffer}}
 }
 
 void strncat_overflow_2(char *y) {
   char x[4] = "12";
   if (strlen(y) == 2)
-    strncat(x, y, strlen(y)); // expected-warning{{String copy function overflows destination buffer}}
+    strncat(x, y, strlen(y)); // expected-warning{{Size argument is greater than the free space in the destination buffer}}
 }
 
 void strncat_overflow_3(char *y) {
   char x[4] = "12";
   if (strlen(y) == 4)
-    strncat(x, y, 2); // expected-warning{{String copy function overflows destination buffer}}
+    strncat(x, y, 2); // expected-warning{{Size argument is greater than the free space in the destination buffer}}
 }
 void strncat_no_overflow_1(char *y) {
   char x[5] = "12";
@@ -636,6 +636,63 @@
     strncat(x, y, 1); // no-warning
 }
 
+void strncat_symbolic_dst_length(char *dst) {
+  strncat(dst, "1234", 5);
+  if (strlen(dst) < 4)
+    (void)*(char*)0; // no-warning
+}
+
+void strncat_symbolic_src_length(char *src) {
+  char dst[8] = "1234";
+  strncat(dst, src, 3);
+  if (strlen(dst) < 4)
+    (void)*(char*)0; // no-warning
+
+  char dst2[8] = "1234";
+  strncat(dst2, src, 4); // expected-warning{{Size argument is greater than the free space in the destination buffer}}
+}
+
+void strncat_unknown_src_length(char *src, int offset) {
+  char dst[8] = "1234";
+  strncat(dst, &src[offset], 3);
+  if (strlen(dst) < 4)
+    (void)*(char*)0; // no-warning
+
+  char dst2[8] = "1234";
+  strncat(dst2, &src[offset], 4); // expected-warning{{Size argument is greater than the free space in the destination buffer}}
+}
+
+// There is no strncat_unknown_dst_length because if we can't get a symbolic
+// length for the "before" strlen, we won't be able to set one for "after".
+
+void strncat_symbolic_limit(unsigned limit) {
+  char dst[6] = "1234";
+  char src[] = "567";
+  strncat(dst, src, limit); // no-warning
+  if (strlen(dst) < 4)
+    (void)*(char*)0; // no-warning
+  if (strlen(dst) == 4)
+    (void)*(char*)0; // expected-warning{{null}}
+}
+
+void strncat_unknown_limit(float limit) {
+  char dst[6] = "1234";
+  char src[] = "567";
+  strncat(dst, src, (size_t)limit); // no-warning
+  if (strlen(dst) < 4)
+    (void)*(char*)0; // no-warning
+  if (strlen(dst) == 4)
+    (void)*(char*)0; // expected-warning{{null}}
+}
+
+void strncat_too_big(char *dst, char *src) {
+  if (strlen(dst) != (((size_t)0) - 2))
+    return;
+  if (strlen(src) != 2)
+    return;
+  strncat(dst, src, 2); // expected-warning{{This expression will create a string whose length is too big to be represented as a size_t}}
+}
+
 //===----------------------------------------------------------------------===
 // strcmp()
 //===----------------------------------------------------------------------===