[analyzer] Revise CStringChecker's modelling of strcpy() and strcat():
- (bounded copies) Be more conservative about how much is being copied.
- (str(n)cat) If we can't compute the exact final length of an append operation, we can still lower-bound it.
- (stpcpy) Fix the conjured return value at the end to actually be returned.
This requires these supporting changes:
- C string metadata symbols are still live even when buried in a SymExpr.
- "Hypothetical" C string lengths, to represent a value that /will/ be passed to setCStringLength() if all goes well. (The idea is to allow for temporary constrainable symbols that may end up becoming permanent.)
- The 'checkAdditionOverflow' helper makes sure that the two strings being appended in a strcat don't overflow size_t. This should never *actually* happen; the real effect is to keep the final string length from "wrapping around" in the constraint manager.
This doesn't actually test the "bounded" operations (strncpy and strncat) because they can leave strings unterminated. Next on the list!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133046 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/Analysis/string.c b/test/Analysis/string.c
index 20b7126..98fd8c0 100644
--- a/test/Analysis/string.c
+++ b/test/Analysis/string.c
@@ -398,9 +398,6 @@
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) {
@@ -427,6 +424,37 @@
strcat(x, y); // no-warning
}
+void strcat_symbolic_dst_length(char *dst) {
+ strcat(dst, "1234");
+ if (strlen(dst) < 4)
+ (void)*(char*)0; // no-warning
+}
+
+void strcat_symbolic_src_length(char *src) {
+ char dst[8] = "1234";
+ strcat(dst, src);
+ if (strlen(dst) < 4)
+ (void)*(char*)0; // no-warning
+}
+
+void strcat_unknown_src_length(char *src, int offset) {
+ char dst[8] = "1234";
+ strcat(dst, &src[offset]);
+ if (strlen(dst) < 4)
+ (void)*(char*)0; // no-warning
+}
+
+// There is no strcat_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 strcat_too_big(char *dst, char *src) {
+ if (strlen(dst) != (((size_t)0) - 2))
+ return;
+ if (strlen(src) != 2)
+ return;
+ strcat(dst, src); // expected-warning{{This expression will create a string whose length is too big to be represented as a size_t}}
+}
+
//===----------------------------------------------------------------------===
// strncat()
@@ -472,9 +500,6 @@
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) {