about summary refs log tree commit diff homepage
diff options
context:
space:
mode:
authorCristian Cadar <c.cadar@imperial.ac.uk>2020-04-05 19:03:45 +0100
committerMartinNowack <2443641+MartinNowack@users.noreply.github.com>2020-06-19 18:19:53 +0100
commitfbd077c1c594ac1cacbd63e40597d0099c426e34 (patch)
treeec6a54adb85688406aa846bccbd1593d9572d64d
parent32b5c245f00bf79ab604fd7473d880fbd3e37890 (diff)
downloadklee-fbd077c1c594ac1cacbd63e40597d0099c426e34.tar.gz
Added test checking that KLEE correctly handles variadic arguments with the byval attribute
-rw-r--r--test/Feature/VarArgByVal.c128
1 files changed, 128 insertions, 0 deletions
diff --git a/test/Feature/VarArgByVal.c b/test/Feature/VarArgByVal.c
new file mode 100644
index 00000000..43c815b5
--- /dev/null
+++ b/test/Feature/VarArgByVal.c
@@ -0,0 +1,128 @@
+/* This test checks that KLEE correctly handles variadic arguments with the 
+   byval attribute */
+
+// RUN: %clang %s -emit-llvm %O0opt -c -g -o %t1.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --exit-on-error --output-dir=%t.klee-out %t1.bc
+// RUN FileCheck %s klee-last/assembly.ll
+// CHECK: @test(i32 -1, %struct.bar* byval
+
+#include <stdarg.h>
+#include <assert.h>
+#include <stdio.h>
+
+struct foo {
+  char f1;
+  long long f2;
+  long long f3;
+  char f4;
+  long f5;
+  int f6;
+  char f7;
+};
+
+struct bar {
+  long long int f1;
+  char f2;
+  long long f3;
+  char f4;
+  long f5;
+};
+
+struct foo test1(int x, ...) {
+  va_list ap;
+  va_start(ap, x);
+  assert(x == -1);
+
+  struct foo f = va_arg(ap, struct foo);
+  assert(f.f1 == 1);
+  assert(f.f2 == 2);
+  assert(f.f3 == 3);
+  assert(f.f4 == 4);
+  assert(f.f5 == 5);
+  assert(f.f6 == 6);
+  assert(f.f7 == 7);
+  
+  struct bar b = va_arg(ap, struct bar);
+  assert(b.f1 == 11);
+  assert(b.f2 == 12);
+  assert(b.f3 == 13);
+  assert(b.f4 == 14);
+  assert(b.f5 == 15);
+  
+  va_end(ap);
+
+  f.f1++;
+  return f;
+}
+
+struct foo test2(int x, long long int l, ...) {
+  va_list ap;
+  va_start(ap, l);
+  assert(x == 10);
+  assert(l == 1000);
+
+  int i = va_arg(ap, int);
+  assert(i == 10);
+
+  struct foo f = va_arg(ap, struct foo);
+  assert(f.f1 == 1);
+  assert(f.f2 == 2);
+  assert(f.f3 == 3);
+  assert(f.f4 == 4);
+  assert(f.f5 == 5);
+  assert(f.f6 == 6);
+  assert(f.f7 == 7);
+
+  l = va_arg(ap, long long int);
+  assert(l == 1000);
+  
+  struct bar b = va_arg(ap, struct bar);
+  assert(b.f1 == 11);
+  assert(b.f2 == 12);
+  assert(b.f3 == 13);
+  assert(b.f4 == 14);
+  assert(b.f5 == 15);
+
+  f = va_arg(ap, struct foo);
+  assert(f.f1 == 10);
+  assert(f.f2 == 20);
+  assert(f.f3 == 30);
+  assert(f.f4 == 40);
+  assert(f.f5 == 50);
+  assert(f.f6 == 60);
+  assert(f.f7 == 70);
+
+  b = va_arg(ap, struct bar);
+  assert(b.f1 == 1);
+  assert(b.f2 == 3);
+  assert(b.f3 == 5);
+  assert(b.f4 == 7);
+  assert(b.f5 == 9);
+  
+  va_end(ap);
+
+  f.f1++;
+  return f;
+}
+
+int main() {
+  struct foo f = { 1, 2, 3, 4, 5, 6, 7 };
+  struct bar b = { 11, 12, 13, 14, 15 };
+  struct foo res = test1(-1, f, b);
+  assert(res.f1 == 2);
+  assert(res.f2 == 2);
+  assert(res.f3 == 3);
+  assert(res.f4 == 4);
+  assert(res.f5 == 5);
+  assert(res.f6 == 6);
+  assert(res.f7 == 7);
+  // check that f was not modified, as it's passed by value
+  assert(f.f1 == 1);
+
+  int i = 10;
+  long long int l = 1000;
+  struct foo f2 = { 10, 20, 30, 40, 50, 60, 70 };
+  struct bar b2 = { 1, 3, 5, 7, 9 };
+  test2(i, l, i, f, l, b, f2, b2);
+}