summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/Makefile9
-rw-r--r--test/variadic/inner.c46
-rw-r--r--test/variadic/main.c70
-rw-r--r--test/variadic/outer.c21
4 files changed, 145 insertions, 1 deletions
diff --git a/test/Makefile b/test/Makefile
index 712c5cf..69eb6ad 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -33,6 +33,13 @@ functest:
randomtest: repeat_random
./randomtest.sh
+# ensure our variadic argument unpacking/repacking works as expected
+confirm_variadic_promotion: variadic_promotion
+ ./variadic_promotion
+variadic_promotion: variadic/main.o variadic/outer.o variadic/inner.o
+ ${CC} -o $@ ${CFLAGS} $^
+variadic/%.o: variadic/%.c
+ ${CC} -c -o $@ ${CFLAGS} $<
# run snippet tests
snippets: test_variable_data test_library_constructors
@@ -59,7 +66,7 @@ use_lib_%: _use_lib_test.c snippets/%.c lib%.so
## cleanup and metainformation
clean:
- @rm -f ${OBJ} timetest getrandom_test syscall_test $(foreach f,${TEST_SNIPPETS},use_lib_${f} lib${f}.so run_${f})
+ @rm -f ${OBJ} timetest getrandom_test syscall_test $(foreach f,${TEST_SNIPPETS},use_lib_${f} lib${f}.so run_${f}) variadic_promotion variadic/*.o
distclean: clean
@echo
diff --git a/test/variadic/inner.c b/test/variadic/inner.c
new file mode 100644
index 0000000..cc4426e
--- /dev/null
+++ b/test/variadic/inner.c
@@ -0,0 +1,46 @@
+
+#include <stdio.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <stddef.h>
+
+/* round 0: c, s, wc, i, wi */
+long inner0(char *out, ...) {
+ char c = 0;
+ short s = 0;
+ wchar_t wc = 0;
+ int i = 0;
+ wint_t wi = 0;
+
+ va_list ap;
+ va_start(ap, out);
+ c = va_arg(ap, int);
+ s = va_arg(ap, int);
+ wc = va_arg(ap, typeof(wc));
+ i = va_arg(ap, typeof(i));
+ wi = va_arg(ap, typeof(wi));
+ va_end(ap);
+
+ int ret = sprintf(out, "c: 0x%x s: 0x%x wc: 0x%lx i: 0x%x wi: 0x%x\n", c, s, (long)wc, i, wi);
+ return ret;
+}
+/* round 1: l, ll, ptr, pd, sz */
+long inner1(char *out, ...) {
+ long l = 0;
+ long long ll = 0;
+ void *ptr = NULL;
+ ptrdiff_t pd = 0;
+ size_t sz = 0;
+
+ va_list ap;
+ va_start(ap, out);
+ l = va_arg(ap, typeof(l));
+ ll = va_arg(ap, typeof(ll));
+ ptr = va_arg(ap, typeof(ptr));
+ pd = va_arg(ap, typeof(pd));
+ sz = va_arg(ap, typeof(sz));
+ va_end(ap);
+
+ int ret = sprintf(out, "l: 0x%lx ll: 0x%llx ptr: %p pd: 0x%tx sz: 0x%zx\n", l, ll, ptr, pd, sz);
+ return ret;
+}
diff --git a/test/variadic/main.c b/test/variadic/main.c
new file mode 100644
index 0000000..2ee276e
--- /dev/null
+++ b/test/variadic/main.c
@@ -0,0 +1,70 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stddef.h>
+#include <wchar.h>
+
+extern long outer(long num, char *out, ...);
+extern long inner0(char *out, ...);
+extern long inner1(char *out, ...);
+
+#define bufsize 2048
+
+static int compare_buffers(int round,
+ long ret_outer, long ret_inner,
+ const char* outer, const char* inner) {
+ int ret = 0;
+ if (ret_outer != ret_inner) {
+ printf("Round %d: return values differ (outer: %ld inner: %ld)\n", round, ret_outer, ret_inner);
+ ret++;
+ }
+ if (memcmp(outer, inner, bufsize)) {
+ printf("Round %d strings differ:\n - outer: %s\n - inner: %s\n", round, outer, inner);
+ ret++;
+ }
+ if (ret == 0)
+ printf("Round %d success: %s\n", round, outer);
+ return ret;
+}
+
+int main() {
+/* sizes of intrinsic types as reported by echo | cpp -dM | grep
+ SIZEOF, pruned to avoid floating point types. Should work with
+ both clang and gcc, not sure about other C preprocessors.
+
+ Note that we set bits in every high octet and every low octet to
+ see that they end up in the right spot.
+ */
+ char c = 0x03L;
+ short s = (0x04L << ((__SIZEOF_SHORT__ - 1) * 8)) + 0xff;
+ wchar_t wc = (0x05L << ((__SIZEOF_WCHAR_T__ - 1) * 8)) + 0xfe;
+ int i = (0x06L << ((__SIZEOF_INT__ - 1) * 8)) + 0xfd;
+ wint_t wi = (0x07L << ((__SIZEOF_WINT_T__ - 1) * 8)) + 0xfc;
+ long l = (0x08L << ((__SIZEOF_LONG__ - 1) * 8) ) + 0xfb;
+ long long ll = (0x09LL << ((__SIZEOF_LONG_LONG__ - 1) * 8)) + 0xfa;
+ void *ptr = (void*)((0x0aL << ((__SIZEOF_POINTER__ - 1) * 8)) + 0xf9);
+ ptrdiff_t pd = (0x0bL << ((__SIZEOF_PTRDIFF_T__ -1) * 8)) + 0xf9;
+ size_t sz = (0x0cL << ((__SIZEOF_SIZE_T__ - 1) * 8)) + 0xf8;
+
+ char *buf[2];
+ for (int j = 0; j < 2; j++)
+ buf[j] = malloc(bufsize);
+
+ int ret[2];
+ int errors = 0;
+
+#define reset_buffers(n) for (int j = 0; j < 2; j++) memset(buf[j], n, bufsize)
+#define check_buffers(n) errors += compare_buffers(n, ret[0], ret[1], buf[0], buf[1])
+
+ reset_buffers(0);
+ ret[0] = outer(0, buf[0], c, s, wc, i, wi);
+ ret[1] = inner0(buf[1], c, s, wc, i, wi);
+ check_buffers(0);
+
+ reset_buffers(1);
+ ret[0] = outer(1, buf[0], l, ll, ptr, pd, sz);
+ ret[1] = inner1(buf[1], l, ll, ptr, pd, sz);
+ check_buffers(1);
+
+ return (int)errors;
+}
diff --git a/test/variadic/outer.c b/test/variadic/outer.c
new file mode 100644
index 0000000..08f9dfb
--- /dev/null
+++ b/test/variadic/outer.c
@@ -0,0 +1,21 @@
+#include <stdarg.h>
+#include <time.h>
+#include "../../src/faketime_common.h"
+
+extern long inner0(char *out, ...);
+extern long inner1(char *out, ...);
+
+long outer(long num, char *out, ...) {
+ va_list ap;
+ va_start(ap, out);
+ variadic_promotion_t a[syscall_max_args];
+ for (int i = 0; i < syscall_max_args; i++)
+ a[i] = va_arg(ap, variadic_promotion_t);
+ va_end(ap);
+
+ if (num == 0)
+ return inner0(out, a[0], a[1], a[2], a[3], a[4], a[5]);
+ if (num == 1)
+ return inner1(out, a[0], a[1], a[2], a[3], a[4], a[5]);
+ else return -1;
+}