pixman: Branch 'master' - 2 commits
Søren Sandmann Pedersen
sandmann at kemper.freedesktop.org
Thu Oct 17 08:15:39 PDT 2013
pixman/pixman-glyph.c | 6 ++++++
test/utils.c | 32 ++++++++++++++++++++++++++++++--
2 files changed, 36 insertions(+), 2 deletions(-)
New commits:
commit 3c2f4b651747c1ac484c39d5128cae5483094342
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date: Fri Oct 11 00:49:44 2013 -0400
pixman-glyph.c: Add __force_align_arg_pointer to composite functions
The functions pixman_composite_glyphs_no_mask() and
pixman_composite_glyphs() can call into code compiled with -msse2,
which requires the stack to be aligned to 16 bytes. Since the ABIs on
Windows and Linux for x86-32 don't provide this guarantee, we need to
use this attribute to make GCC generate a prologue that realigns the
stack.
This fixes the crash introduced in the previous commit and also
https://bugs.freedesktop.org/show_bug.cgi?id=70348
and
https://bugs.freedesktop.org/show_bug.cgi?id=68300
diff --git a/pixman/pixman-glyph.c b/pixman/pixman-glyph.c
index 5a271b6..96a349a 100644
--- a/pixman/pixman-glyph.c
+++ b/pixman/pixman-glyph.c
@@ -391,6 +391,9 @@ box32_intersect (pixman_box32_t *dest,
return dest->x2 > dest->x1 && dest->y2 > dest->y1;
}
+#if defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
+__attribute__((__force_align_arg_pointer__))
+#endif
PIXMAN_EXPORT void
pixman_composite_glyphs_no_mask (pixman_op_t op,
pixman_image_t *src,
@@ -630,6 +633,9 @@ out:
* - Trim the mask to the destination clip/image?
* - Trim composite region based on sources, when the op ignores 0s.
*/
+#if defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
+__attribute__((__force_align_arg_pointer__))
+#endif
PIXMAN_EXPORT void
pixman_composite_glyphs (pixman_op_t op,
pixman_image_t *src,
commit 3dce229772354877ef297dd9979097fe8ebaebf4
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date: Wed Oct 2 14:38:16 2013 -0400
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.
diff --git a/test/utils.c b/test/utils.c
index 0cd982e..281f6b4 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;
More information about the xorg-commit
mailing list