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