mirror of
https://salsa.debian.org/xorg-team/lib/pixman
synced 2025-09-06 20:33:31 +00:00

When a trapezoid has a top/bottom that is above/below the left/right edges, degenerate trapezoids become possible. For example the edge could be very short and close to horizontal. If the bottom edge is far below the bottom point of such a short edge, the result is that the lower right corner of the trapezoid will be extremely far to the left. This kind of trapezoid causes overflows in the rasterization code, so change pixman_trapezoid_valid() to reject them.
258 lines
6.5 KiB
C
258 lines
6.5 KiB
C
/* Based loosely on scaling-test */
|
|
|
|
#include <assert.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include "utils.h"
|
|
|
|
#define MAX_SRC_WIDTH 48
|
|
#define MAX_SRC_HEIGHT 48
|
|
#define MAX_DST_WIDTH 48
|
|
#define MAX_DST_HEIGHT 48
|
|
#define MAX_STRIDE 4
|
|
|
|
static pixman_format_code_t formats[] =
|
|
{
|
|
PIXMAN_a8r8g8b8, PIXMAN_a8, PIXMAN_r5g6b5, PIXMAN_a1, PIXMAN_a4
|
|
};
|
|
|
|
static pixman_format_code_t mask_formats[] =
|
|
{
|
|
PIXMAN_a1, PIXMAN_a4, PIXMAN_a8,
|
|
};
|
|
|
|
static pixman_op_t operators[] =
|
|
{
|
|
PIXMAN_OP_OVER, PIXMAN_OP_ADD, PIXMAN_OP_SRC, PIXMAN_OP_IN
|
|
};
|
|
|
|
#define RANDOM_ELT(array) \
|
|
((array)[lcg_rand_n(ARRAY_LENGTH((array)))])
|
|
|
|
static void
|
|
destroy_bits (pixman_image_t *image, void *data)
|
|
{
|
|
fence_free (data);
|
|
}
|
|
|
|
static pixman_fixed_t
|
|
random_fixed (int n)
|
|
{
|
|
return lcg_rand_N (n << 16);
|
|
}
|
|
|
|
/*
|
|
* Composite operation with pseudorandom images
|
|
*/
|
|
uint32_t
|
|
test_composite (int testnum,
|
|
int verbose)
|
|
{
|
|
int i;
|
|
pixman_image_t * src_img;
|
|
pixman_image_t * dst_img;
|
|
pixman_region16_t clip;
|
|
int dst_width, dst_height;
|
|
int dst_stride;
|
|
int dst_x, dst_y;
|
|
int dst_bpp;
|
|
pixman_op_t op;
|
|
uint32_t * dst_bits;
|
|
uint32_t crc32;
|
|
pixman_format_code_t mask_format, dst_format;
|
|
pixman_trapezoid_t *traps;
|
|
int src_x, src_y;
|
|
int n_traps;
|
|
|
|
static pixman_color_t colors[] =
|
|
{
|
|
{ 0xffff, 0xffff, 0xffff, 0xffff },
|
|
{ 0x0000, 0x0000, 0x0000, 0x0000 },
|
|
{ 0xabcd, 0xabcd, 0x0000, 0xabcd },
|
|
{ 0x0000, 0x0000, 0x0000, 0xffff },
|
|
{ 0x0101, 0x0101, 0x0101, 0x0101 },
|
|
{ 0x7777, 0x6666, 0x5555, 0x9999 },
|
|
};
|
|
|
|
FLOAT_REGS_CORRUPTION_DETECTOR_START ();
|
|
|
|
lcg_srand (testnum);
|
|
|
|
op = RANDOM_ELT (operators);
|
|
mask_format = RANDOM_ELT (mask_formats);
|
|
|
|
/* Create source image */
|
|
|
|
if (lcg_rand_n (4) == 0)
|
|
{
|
|
src_img = pixman_image_create_solid_fill (
|
|
&(colors[lcg_rand_n (ARRAY_LENGTH (colors))]));
|
|
|
|
src_x = 10;
|
|
src_y = 234;
|
|
}
|
|
else
|
|
{
|
|
pixman_format_code_t src_format = RANDOM_ELT(formats);
|
|
int src_bpp = (PIXMAN_FORMAT_BPP (src_format) + 7) / 8;
|
|
int src_width = lcg_rand_n (MAX_SRC_WIDTH) + 1;
|
|
int src_height = lcg_rand_n (MAX_SRC_HEIGHT) + 1;
|
|
int src_stride = src_width * src_bpp + lcg_rand_n (MAX_STRIDE) * src_bpp;
|
|
uint32_t *bits;
|
|
|
|
src_x = -(src_width / 4) + lcg_rand_n (src_width * 3 / 2);
|
|
src_y = -(src_height / 4) + lcg_rand_n (src_height * 3 / 2);
|
|
|
|
src_stride = (src_stride + 3) & ~3;
|
|
|
|
bits = (uint32_t *)make_random_bytes (src_stride * src_height);
|
|
|
|
src_img = pixman_image_create_bits (
|
|
src_format, src_width, src_height, bits, src_stride);
|
|
|
|
pixman_image_set_destroy_function (src_img, destroy_bits, bits);
|
|
|
|
if (lcg_rand_n (8) == 0)
|
|
{
|
|
pixman_box16_t clip_boxes[2];
|
|
int n = lcg_rand_n (2) + 1;
|
|
|
|
for (i = 0; i < n; i++)
|
|
{
|
|
clip_boxes[i].x1 = lcg_rand_n (src_width);
|
|
clip_boxes[i].y1 = lcg_rand_n (src_height);
|
|
clip_boxes[i].x2 =
|
|
clip_boxes[i].x1 + lcg_rand_n (src_width - clip_boxes[i].x1);
|
|
clip_boxes[i].y2 =
|
|
clip_boxes[i].y1 + lcg_rand_n (src_height - clip_boxes[i].y1);
|
|
|
|
if (verbose)
|
|
{
|
|
printf ("source clip box: [%d,%d-%d,%d]\n",
|
|
clip_boxes[i].x1, clip_boxes[i].y1,
|
|
clip_boxes[i].x2, clip_boxes[i].y2);
|
|
}
|
|
}
|
|
|
|
pixman_region_init_rects (&clip, clip_boxes, n);
|
|
pixman_image_set_clip_region (src_img, &clip);
|
|
pixman_image_set_source_clipping (src_img, 1);
|
|
pixman_region_fini (&clip);
|
|
}
|
|
|
|
image_endian_swap (src_img);
|
|
}
|
|
|
|
/* Create destination image */
|
|
{
|
|
dst_format = RANDOM_ELT(formats);
|
|
dst_bpp = (PIXMAN_FORMAT_BPP (dst_format) + 7) / 8;
|
|
dst_width = lcg_rand_n (MAX_DST_WIDTH) + 1;
|
|
dst_height = lcg_rand_n (MAX_DST_HEIGHT) + 1;
|
|
dst_stride = dst_width * dst_bpp + lcg_rand_n (MAX_STRIDE) * dst_bpp;
|
|
dst_stride = (dst_stride + 3) & ~3;
|
|
|
|
dst_bits = (uint32_t *)make_random_bytes (dst_stride * dst_height);
|
|
|
|
dst_x = -(dst_width / 4) + lcg_rand_n (dst_width * 3 / 2);
|
|
dst_y = -(dst_height / 4) + lcg_rand_n (dst_height * 3 / 2);
|
|
|
|
dst_img = pixman_image_create_bits (
|
|
dst_format, dst_width, dst_height, dst_bits, dst_stride);
|
|
|
|
image_endian_swap (dst_img);
|
|
}
|
|
|
|
/* Create traps */
|
|
{
|
|
int i;
|
|
|
|
n_traps = lcg_rand_n (25);
|
|
traps = fence_malloc (n_traps * sizeof (pixman_trapezoid_t));
|
|
|
|
for (i = 0; i < n_traps; ++i)
|
|
{
|
|
pixman_trapezoid_t *t = &(traps[i]);
|
|
|
|
t->top = random_fixed (MAX_DST_HEIGHT) - MAX_DST_HEIGHT / 2;
|
|
t->bottom = t->top + random_fixed (MAX_DST_HEIGHT);
|
|
t->left.p1.x = random_fixed (MAX_DST_WIDTH) - MAX_DST_WIDTH / 2;
|
|
t->left.p1.y = t->top - random_fixed (50);
|
|
t->left.p2.x = random_fixed (MAX_DST_WIDTH) - MAX_DST_WIDTH / 2;
|
|
t->left.p2.y = t->bottom + random_fixed (50);
|
|
t->right.p1.x = t->left.p1.x + random_fixed (MAX_DST_WIDTH);
|
|
t->right.p1.y = t->top - random_fixed (50);
|
|
t->right.p2.x = t->left.p2.x + random_fixed (MAX_DST_WIDTH);
|
|
t->right.p2.y = t->bottom - random_fixed (50);
|
|
}
|
|
}
|
|
|
|
if (lcg_rand_n (8) == 0)
|
|
{
|
|
pixman_box16_t clip_boxes[2];
|
|
int n = lcg_rand_n (2) + 1;
|
|
for (i = 0; i < n; i++)
|
|
{
|
|
clip_boxes[i].x1 = lcg_rand_n (dst_width);
|
|
clip_boxes[i].y1 = lcg_rand_n (dst_height);
|
|
clip_boxes[i].x2 =
|
|
clip_boxes[i].x1 + lcg_rand_n (dst_width - clip_boxes[i].x1);
|
|
clip_boxes[i].y2 =
|
|
clip_boxes[i].y1 + lcg_rand_n (dst_height - clip_boxes[i].y1);
|
|
|
|
if (verbose)
|
|
{
|
|
printf ("destination clip box: [%d,%d-%d,%d]\n",
|
|
clip_boxes[i].x1, clip_boxes[i].y1,
|
|
clip_boxes[i].x2, clip_boxes[i].y2);
|
|
}
|
|
}
|
|
pixman_region_init_rects (&clip, clip_boxes, n);
|
|
pixman_image_set_clip_region (dst_img, &clip);
|
|
pixman_region_fini (&clip);
|
|
}
|
|
|
|
pixman_composite_trapezoids (op, src_img, dst_img, mask_format,
|
|
src_x, src_y, dst_x, dst_y, n_traps, traps);
|
|
|
|
if (dst_format == PIXMAN_x8r8g8b8)
|
|
{
|
|
/* ignore unused part */
|
|
for (i = 0; i < dst_stride * dst_height / 4; i++)
|
|
dst_bits[i] &= 0xFFFFFF;
|
|
}
|
|
|
|
image_endian_swap (dst_img);
|
|
|
|
if (verbose)
|
|
{
|
|
int j;
|
|
|
|
for (i = 0; i < dst_height; i++)
|
|
{
|
|
for (j = 0; j < dst_stride; j++)
|
|
printf ("%02X ", *((uint8_t *)dst_bits + i * dst_stride + j));
|
|
|
|
printf ("\n");
|
|
}
|
|
}
|
|
|
|
crc32 = compute_crc32 (0, dst_bits, dst_stride * dst_height);
|
|
|
|
fence_free (dst_bits);
|
|
|
|
pixman_image_unref (src_img);
|
|
pixman_image_unref (dst_img);
|
|
fence_free (traps);
|
|
|
|
FLOAT_REGS_CORRUPTION_DETECTOR_FINISH ();
|
|
return crc32;
|
|
}
|
|
|
|
int
|
|
main (int argc, const char *argv[])
|
|
{
|
|
return fuzzer_test_main("composite traps", 40000, 0x4346479C,
|
|
test_composite, argc, argv);
|
|
}
|