diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/Makefile | 9 | ||||
-rw-r--r-- | test/variadic/inner.c | 46 | ||||
-rw-r--r-- | test/variadic/main.c | 70 | ||||
-rw-r--r-- | test/variadic/outer.c | 21 |
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; +} |