summaryrefslogtreecommitdiff
path: root/clang/test/Analysis/bstring.c
diff options
context:
space:
mode:
authorZancanaro; Carlo <czan8762@plang3.cs.usyd.edu.au>2012-09-24 09:58:17 +1000
committerZancanaro; Carlo <czan8762@plang3.cs.usyd.edu.au>2012-09-24 09:58:17 +1000
commit222e2a7620e6520ffaf4fc4e69d79c18da31542e (patch)
tree7bfbc05bfa3b41c8f9d2e56d53a0bc3e310df239 /clang/test/Analysis/bstring.c
parent3d206f03985b50beacae843d880bccdc91a9f424 (diff)
Add the clang library to the repo (with some of my changes, too).
Diffstat (limited to 'clang/test/Analysis/bstring.c')
-rw-r--r--clang/test/Analysis/bstring.c430
1 files changed, 430 insertions, 0 deletions
diff --git a/clang/test/Analysis/bstring.c b/clang/test/Analysis/bstring.c
new file mode 100644
index 0000000..833c917
--- /dev/null
+++ b/clang/test/Analysis/bstring.c
@@ -0,0 +1,430 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,experimental.unix.cstring -analyzer-store=region -Wno-null-dereference -verify %s
+// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,experimental.unix.cstring -analyzer-store=region -Wno-null-dereference -verify %s
+// RUN: %clang_cc1 -analyze -DVARIANT -analyzer-checker=core,unix.cstring,experimental.unix.cstring -analyzer-store=region -Wno-null-dereference -verify %s
+// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -DVARIANT -analyzer-checker=core,unix.cstring.NullArg,experimental.unix.cstring.OutOfBounds,experimental.unix.cstring.BufferOverlap,experimental.unix.cstring.NotNullTerminated -analyzer-store=region -Wno-null-dereference -verify %s
+
+//===----------------------------------------------------------------------===
+// Declarations
+//===----------------------------------------------------------------------===
+
+// Some functions are so similar to each other that they follow the same code
+// path, such as memcpy and __memcpy_chk, or memcmp and bcmp. If VARIANT is
+// defined, make sure to use the variants instead to make sure they are still
+// checked by the analyzer.
+
+// Some functions are implemented as builtins. These should be #defined as
+// BUILTIN(f), which will prepend "__builtin_" if USE_BUILTINS is defined.
+
+// Functions that have variants and are also available as builtins should be
+// declared carefully! See memcpy() for an example.
+
+#ifdef USE_BUILTINS
+# define BUILTIN(f) __builtin_ ## f
+#else /* USE_BUILTINS */
+# define BUILTIN(f) f
+#endif /* USE_BUILTINS */
+
+typedef typeof(sizeof(int)) size_t;
+
+//===----------------------------------------------------------------------===
+// memcpy()
+//===----------------------------------------------------------------------===
+
+#ifdef VARIANT
+
+#define __memcpy_chk BUILTIN(__memcpy_chk)
+void *__memcpy_chk(void *restrict s1, const void *restrict s2, size_t n,
+ size_t destlen);
+
+#define memcpy(a,b,c) __memcpy_chk(a,b,c,(size_t)-1)
+
+#else /* VARIANT */
+
+#define memcpy BUILTIN(memcpy)
+void *memcpy(void *restrict s1, const void *restrict s2, size_t n);
+
+#endif /* VARIANT */
+
+
+void memcpy0 () {
+ char src[] = {1, 2, 3, 4};
+ char dst[4] = {0};
+
+ memcpy(dst, src, 4); // no-warning
+
+ if (memcpy(dst, src, 4) != dst) {
+ (void)*(char*)0; // no-warning
+ }
+
+ if (dst[0] != 0)
+ (void)*(char*)0; // expected-warning{{null}}
+}
+
+void memcpy1 () {
+ char src[] = {1, 2, 3, 4};
+ char dst[10];
+
+ memcpy(dst, src, 5); // expected-warning{{Memory copy function accesses out-of-bound array element}}
+}
+
+void memcpy2 () {
+ char src[] = {1, 2, 3, 4};
+ char dst[1];
+
+ memcpy(dst, src, 4); // expected-warning{{Memory copy function overflows destination buffer}}
+}
+
+void memcpy3 () {
+ char src[] = {1, 2, 3, 4};
+ char dst[3];
+
+ memcpy(dst+1, src+2, 2); // no-warning
+}
+
+void memcpy4 () {
+ char src[] = {1, 2, 3, 4};
+ char dst[10];
+
+ memcpy(dst+2, src+2, 3); // expected-warning{{Memory copy function accesses out-of-bound array element}}
+}
+
+void memcpy5() {
+ char src[] = {1, 2, 3, 4};
+ char dst[3];
+
+ memcpy(dst+2, src+2, 2); // expected-warning{{Memory copy function overflows destination buffer}}
+}
+
+void memcpy6() {
+ int a[4] = {0};
+ memcpy(a, a, 8); // expected-warning{{overlapping}}
+}
+
+void memcpy7() {
+ int a[4] = {0};
+ memcpy(a+2, a+1, 8); // expected-warning{{overlapping}}
+}
+
+void memcpy8() {
+ int a[4] = {0};
+ memcpy(a+1, a+2, 8); // expected-warning{{overlapping}}
+}
+
+void memcpy9() {
+ int a[4] = {0};
+ memcpy(a+2, a+1, 4); // no-warning
+ memcpy(a+1, a+2, 4); // no-warning
+}
+
+void memcpy10() {
+ char a[4] = {0};
+ memcpy(0, a, 4); // expected-warning{{Null pointer argument in call to memory copy function}}
+}
+
+void memcpy11() {
+ char a[4] = {0};
+ memcpy(a, 0, 4); // expected-warning{{Null pointer argument in call to memory copy function}}
+}
+
+void memcpy12() {
+ char a[4] = {0};
+ memcpy(0, a, 0); // no-warning
+}
+
+void memcpy13() {
+ char a[4] = {0};
+ memcpy(a, 0, 0); // no-warning
+}
+
+void memcpy_unknown_size (size_t n) {
+ char a[4], b[4] = {1};
+ if (memcpy(a, b, n) != a)
+ (void)*(char*)0; // no-warning
+}
+
+void memcpy_unknown_size_warn (size_t n) {
+ char a[4];
+ if (memcpy(a, 0, n) != a) // expected-warning{{Null pointer argument in call to memory copy function}}
+ (void)*(char*)0; // no-warning
+}
+
+//===----------------------------------------------------------------------===
+// mempcpy()
+//===----------------------------------------------------------------------===
+
+#ifdef VARIANT
+
+#define __mempcpy_chk BUILTIN(__mempcpy_chk)
+void *__mempcpy_chk(void *restrict s1, const void *restrict s2, size_t n,
+ size_t destlen);
+
+#define mempcpy(a,b,c) __mempcpy_chk(a,b,c,(size_t)-1)
+
+#else /* VARIANT */
+
+#define mempcpy BUILTIN(mempcpy)
+void *mempcpy(void *restrict s1, const void *restrict s2, size_t n);
+
+#endif /* VARIANT */
+
+
+void mempcpy0 () {
+ char src[] = {1, 2, 3, 4};
+ char dst[5] = {0};
+
+ mempcpy(dst, src, 4); // no-warning
+
+ if (mempcpy(dst, src, 4) != &dst[4]) {
+ (void)*(char*)0; // no-warning
+ }
+
+ if (dst[0] != 0)
+ (void)*(char*)0; // expected-warning{{null}}
+}
+
+void mempcpy1 () {
+ char src[] = {1, 2, 3, 4};
+ char dst[10];
+
+ mempcpy(dst, src, 5); // expected-warning{{Memory copy function accesses out-of-bound array element}}
+}
+
+void mempcpy2 () {
+ char src[] = {1, 2, 3, 4};
+ char dst[1];
+
+ mempcpy(dst, src, 4); // expected-warning{{Memory copy function overflows destination buffer}}
+}
+
+void mempcpy3 () {
+ char src[] = {1, 2, 3, 4};
+ char dst[3];
+
+ mempcpy(dst+1, src+2, 2); // no-warning
+}
+
+void mempcpy4 () {
+ char src[] = {1, 2, 3, 4};
+ char dst[10];
+
+ mempcpy(dst+2, src+2, 3); // expected-warning{{Memory copy function accesses out-of-bound array element}}
+}
+
+void mempcpy5() {
+ char src[] = {1, 2, 3, 4};
+ char dst[3];
+
+ mempcpy(dst+2, src+2, 2); // expected-warning{{Memory copy function overflows destination buffer}}
+}
+
+void mempcpy6() {
+ int a[4] = {0};
+ mempcpy(a, a, 8); // expected-warning{{overlapping}}
+}
+
+void mempcpy7() {
+ int a[4] = {0};
+ mempcpy(a+2, a+1, 8); // expected-warning{{overlapping}}
+}
+
+void mempcpy8() {
+ int a[4] = {0};
+ mempcpy(a+1, a+2, 8); // expected-warning{{overlapping}}
+}
+
+void mempcpy9() {
+ int a[4] = {0};
+ mempcpy(a+2, a+1, 4); // no-warning
+ mempcpy(a+1, a+2, 4); // no-warning
+}
+
+void mempcpy10() {
+ char a[4] = {0};
+ mempcpy(0, a, 4); // expected-warning{{Null pointer argument in call to memory copy function}}
+}
+
+void mempcpy11() {
+ char a[4] = {0};
+ mempcpy(a, 0, 4); // expected-warning{{Null pointer argument in call to memory copy function}}
+}
+
+void mempcpy12() {
+ char a[4] = {0};
+ mempcpy(0, a, 0); // no-warning
+}
+
+void mempcpy13() {
+ char a[4] = {0};
+ mempcpy(a, 0, 0); // no-warning
+}
+
+void mempcpy_unknown_size_warn (size_t n) {
+ char a[4];
+ if (mempcpy(a, 0, n) != a) // expected-warning{{Null pointer argument in call to memory copy function}}
+ (void)*(char*)0; // no-warning
+}
+
+void mempcpy_unknownable_size (char *src, float n) {
+ char a[4];
+ // This used to crash because we don't model floats.
+ mempcpy(a, src, (size_t)n);
+}
+
+//===----------------------------------------------------------------------===
+// memmove()
+//===----------------------------------------------------------------------===
+
+#ifdef VARIANT
+
+#define __memmove_chk BUILTIN(__memmove_chk)
+void *__memmove_chk(void *s1, const void *s2, size_t n, size_t destlen);
+
+#define memmove(a,b,c) __memmove_chk(a,b,c,(size_t)-1)
+
+#else /* VARIANT */
+
+#define memmove BUILTIN(memmove)
+void *memmove(void *s1, const void *s2, size_t n);
+
+#endif /* VARIANT */
+
+
+void memmove0 () {
+ char src[] = {1, 2, 3, 4};
+ char dst[4] = {0};
+
+ memmove(dst, src, 4); // no-warning
+
+ if (memmove(dst, src, 4) != dst) {
+ (void)*(char*)0; // no-warning
+ }
+
+ if (dst[0] != 0)
+ (void)*(char*)0; // expected-warning{{null}}
+}
+
+void memmove1 () {
+ char src[] = {1, 2, 3, 4};
+ char dst[10];
+
+ memmove(dst, src, 5); // expected-warning{{out-of-bound}}
+}
+
+void memmove2 () {
+ char src[] = {1, 2, 3, 4};
+ char dst[1];
+
+ memmove(dst, src, 4); // expected-warning{{overflow}}
+}
+
+//===----------------------------------------------------------------------===
+// memcmp()
+//===----------------------------------------------------------------------===
+
+#ifdef VARIANT
+
+#define bcmp BUILTIN(bcmp)
+// __builtin_bcmp is not defined with const in Builtins.def.
+int bcmp(/*const*/ void *s1, /*const*/ void *s2, size_t n);
+#define memcmp bcmp
+
+#else /* VARIANT */
+
+#define memcmp BUILTIN(memcmp)
+int memcmp(const void *s1, const void *s2, size_t n);
+
+#endif /* VARIANT */
+
+
+void memcmp0 () {
+ char a[] = {1, 2, 3, 4};
+ char b[4] = { 0 };
+
+ memcmp(a, b, 4); // no-warning
+}
+
+void memcmp1 () {
+ char a[] = {1, 2, 3, 4};
+ char b[10] = { 0 };
+
+ memcmp(a, b, 5); // expected-warning{{out-of-bound}}
+}
+
+void memcmp2 () {
+ char a[] = {1, 2, 3, 4};
+ char b[1] = { 0 };
+
+ memcmp(a, b, 4); // expected-warning{{out-of-bound}}
+}
+
+void memcmp3 () {
+ char a[] = {1, 2, 3, 4};
+
+ if (memcmp(a, a, 4))
+ (void)*(char*)0; // no-warning
+}
+
+void memcmp4 (char *input) {
+ char a[] = {1, 2, 3, 4};
+
+ if (memcmp(a, input, 4))
+ (void)*(char*)0; // expected-warning{{null}}
+}
+
+void memcmp5 (char *input) {
+ char a[] = {1, 2, 3, 4};
+
+ if (memcmp(a, 0, 0)) // no-warning
+ (void)*(char*)0; // no-warning
+ if (memcmp(0, a, 0)) // no-warning
+ (void)*(char*)0; // no-warning
+ if (memcmp(a, input, 0)) // no-warning
+ (void)*(char*)0; // no-warning
+}
+
+void memcmp6 (char *a, char *b, size_t n) {
+ int result = memcmp(a, b, n);
+ if (result != 0)
+ return;
+ if (n == 0)
+ (void)*(char*)0; // expected-warning{{null}}
+}
+
+int memcmp7 (char *a, size_t x, size_t y, size_t n) {
+ // We used to crash when either of the arguments was unknown.
+ return memcmp(a, &a[x*y], n) +
+ memcmp(&a[x*y], a, n);
+}
+
+//===----------------------------------------------------------------------===
+// bcopy()
+//===----------------------------------------------------------------------===
+
+#define bcopy BUILTIN(bcopy)
+// __builtin_bcopy is not defined with const in Builtins.def.
+void bcopy(/*const*/ void *s1, void *s2, size_t n);
+
+
+void bcopy0 () {
+ char src[] = {1, 2, 3, 4};
+ char dst[4] = {0};
+
+ bcopy(src, dst, 4); // no-warning
+
+ if (dst[0] != 0)
+ (void)*(char*)0; // expected-warning{{null}}
+}
+
+void bcopy1 () {
+ char src[] = {1, 2, 3, 4};
+ char dst[10];
+
+ bcopy(src, dst, 5); // expected-warning{{out-of-bound}}
+}
+
+void bcopy2 () {
+ char src[] = {1, 2, 3, 4};
+ char dst[1];
+
+ bcopy(src, dst, 4); // expected-warning{{overflow}}
+}