summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann Pedersen <ssp@redhat.com>2013-10-02 14:38:16 -0400
committerSøren Sandmann Pedersen <ssp@redhat.com>2013-10-17 11:14:14 -0400
commit3dce229772354877ef297dd9979097fe8ebaebf4 (patch)
tree623f631686dab6ad0904f5f1f52257e8d525998b
parent9e81419ed5c0ee490ddacf7bada516a25cae87eb (diff)
utils.c: On x86-32 unalign the stack before calling test_function
GCC when compiling with -msse2 and -mssse3 will assume that the stack is aligned to 16 bytes even on x86-32 and accordingly issue movdqa instructions for stack allocated variables. But despite what GCC thinks, the standard ABI on x86-32 only requires a 4-byte aligned stack. This is true at least on Windows, but there also was (and maybe still is) Linux code in the wild that assumed this. When such code calls into pixman and hits something compiled with -msse2, we get a segfault from the unaligned movdqas. Pixman has worked around this issue in the past with the gcc attribute "force_align_arg_pointer" but the problem has resurfaced now in https://bugs.freedesktop.org/show_bug.cgi?id=68300 because pixman_composite_glyphs() is missing this attribute. This patch makes fuzzer_test_main() call the test_function through a trampoline, which, on x86-32, has a bit of assembly that deliberately avoids aligning the stack to 16 bytes as GCC normally expects. The result is that glyph-test now crashes. V2: Mark caller-save registers as clobbered, rather than using noinline on the trampoline.
-rw-r--r--test/utils.c32
1 files changed, 30 insertions, 2 deletions
diff --git a/test/utils.c b/test/utils.c
index 0cd982e7..281f6b4e 100644
--- a/test/utils.c
+++ b/test/utils.c
@@ -641,6 +641,32 @@ draw_checkerboard (pixman_image_t *image,
}
}
+static uint32_t
+call_test_function (uint32_t (*test_function)(int testnum, int verbose),
+ int testnum,
+ int verbose)
+{
+ uint32_t retval;
+
+#if defined (__GNUC__) && (defined (__i386) || defined (__i386__))
+ __asm__ (
+ /* Deliberately avoid aligning the stack to 16 bytes */
+ "pushl %1\n\t"
+ "pushl %2\n\t"
+ "call *%3\n\t"
+ "addl $8, %%esp\n\t"
+ : "=a" (retval)
+ : "r" (verbose),
+ "r" (testnum),
+ "r" (test_function)
+ : "edx", "ecx"); /* caller save registers */
+#else
+ retval = test_function (testnum, verbose);
+#endif
+
+ return retval;
+}
+
/*
* A function, which can be used as a core part of the test programs,
* intended to detect various problems with the help of fuzzing input
@@ -710,7 +736,9 @@ fuzzer_test_main (const char *test_name,
else if (argc >= 2)
{
n2 = atoi (argv[1]);
- checksum = test_function (n2, 1);
+
+ checksum = call_test_function (test_function, n2, 1);
+
printf ("%d: checksum=%08X\n", n2, checksum);
return 0;
}
@@ -726,7 +754,7 @@ fuzzer_test_main (const char *test_name,
#endif
for (i = n1; i <= n2; i++)
{
- uint32_t crc = test_function (i, 0);
+ uint32_t crc = call_test_function (test_function, i, 0);
if (verbose)
printf ("%d: %08X\n", i, crc);
checksum += crc;