summaryrefslogtreecommitdiff
path: root/test/utils.h
blob: f05488715718d926830c0cf8376056ee30eb26a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <assert.h>
#include "pixman-private.h" /* For 'inline' definition */
#include "utils-prng.h"

#define ARRAY_LENGTH(A) ((int) (sizeof (A) / sizeof ((A) [0])))

/* A primitive pseudorandom number generator,
 * taken from POSIX.1-2001 example
 */

extern prng_t prng_state_data;
extern prng_t *prng_state;
#ifdef USE_OPENMP
#pragma omp threadprivate(prng_state_data)
#pragma omp threadprivate(prng_state)
#endif

static inline uint32_t
prng_rand (void)
{
    return prng_rand_r (prng_state);
}

static inline void
prng_srand (uint32_t seed)
{
    if (!prng_state)
    {
        /* Without setting a seed, PRNG does not work properly (is just
         * returning zeros). So we only initialize the pointer here to
         * make sure that 'prng_srand' is always called before any
         * other 'prng_*' function. The wrongdoers violating this order
         * will get a segfault. */
        prng_state = &prng_state_data;
    }
    prng_srand_r (prng_state, seed);
}

static inline uint32_t
prng_rand_n (int max)
{
    return prng_rand () % max;
}

static inline uint32_t
prng_rand_N (int max)
{
    return prng_rand () % max;
}

static inline uint32_t
prng_rand_u32 (void)
{
    return prng_rand ();
}

static inline void
prng_randmemset (void *buffer, size_t size, prng_randmemset_flags_t flags)
{
    prng_randmemset_r (prng_state, buffer, size, flags);
}

/* CRC 32 computation
 */
uint32_t
compute_crc32 (uint32_t    in_crc32,
	       const void *buf,
	       size_t      buf_len);

uint32_t
compute_crc32_for_image (uint32_t        in_crc32,
			 pixman_image_t *image);

/* Returns TRUE if running on a little endian system
 */
static force_inline pixman_bool_t
is_little_endian (void)
{
    unsigned long endian_check_var = 1;
    return *(unsigned char *)&endian_check_var == 1;
}

/* perform endian conversion of pixel data
 */
void
image_endian_swap (pixman_image_t *img);

/* Allocate memory that is bounded by protected pages,
 * so that out-of-bounds access will cause segfaults
 */
void *
fence_malloc (int64_t len);

void
fence_free (void *data);

/* Generate n_bytes random bytes in fence_malloced memory */
uint8_t *
make_random_bytes (int n_bytes);

/* Return current time in seconds */
double
gettime (void);

uint32_t
get_random_seed (void);

/* main body of the fuzzer test */
int
fuzzer_test_main (const char *test_name,
		  int         default_number_of_iterations,
		  uint32_t    expected_checksum,
		  uint32_t    (*test_function)(int testnum, int verbose),
		  int         argc,
		  const char *argv[]);

void
fail_after (int seconds, const char *msg);

/* If possible, enable traps for floating point exceptions */
void enable_divbyzero_exceptions(void);

/* Converts a8r8g8b8 pixels to pixels that
 *  - are not premultiplied,
 *  - are stored in this order in memory: R, G, B, A, regardless of
 *    the endianness of the computer.
 * It is allowed for @src and @dst to point to the same memory buffer.
 */
void
a8r8g8b8_to_rgba_np (uint32_t *dst, uint32_t *src, int n_pixels);

pixman_bool_t
write_png (pixman_image_t *image, const char *filename);

/* A pair of macros which can help to detect corruption of
 * floating point registers after a function call. This may
 * happen if _mm_empty() call is forgotten in MMX/SSE2 fast
 * path code, or ARM NEON assembly optimized function forgets
 * to save/restore d8-d15 registers before use.
 */

#define FLOAT_REGS_CORRUPTION_DETECTOR_START()                 \
    static volatile double frcd_volatile_constant1 = 123451;   \
    static volatile double frcd_volatile_constant2 = 123452;   \
    static volatile double frcd_volatile_constant3 = 123453;   \
    static volatile double frcd_volatile_constant4 = 123454;   \
    static volatile double frcd_volatile_constant5 = 123455;   \
    static volatile double frcd_volatile_constant6 = 123456;   \
    static volatile double frcd_volatile_constant7 = 123457;   \
    static volatile double frcd_volatile_constant8 = 123458;   \
    double frcd_canary_variable1 = frcd_volatile_constant1;    \
    double frcd_canary_variable2 = frcd_volatile_constant2;    \
    double frcd_canary_variable3 = frcd_volatile_constant3;    \
    double frcd_canary_variable4 = frcd_volatile_constant4;    \
    double frcd_canary_variable5 = frcd_volatile_constant5;    \
    double frcd_canary_variable6 = frcd_volatile_constant6;    \
    double frcd_canary_variable7 = frcd_volatile_constant7;    \
    double frcd_canary_variable8 = frcd_volatile_constant8;

#define FLOAT_REGS_CORRUPTION_DETECTOR_FINISH()                \
    assert (frcd_canary_variable1 == frcd_volatile_constant1); \
    assert (frcd_canary_variable2 == frcd_volatile_constant2); \
    assert (frcd_canary_variable3 == frcd_volatile_constant3); \
    assert (frcd_canary_variable4 == frcd_volatile_constant4); \
    assert (frcd_canary_variable5 == frcd_volatile_constant5); \
    assert (frcd_canary_variable6 == frcd_volatile_constant6); \
    assert (frcd_canary_variable7 == frcd_volatile_constant7); \
    assert (frcd_canary_variable8 == frcd_volatile_constant8);

/* Try to get an aligned memory chunk */
void *
aligned_malloc (size_t align, size_t size);

double
convert_srgb_to_linear (double component);

double
convert_linear_to_srgb (double component);

void
initialize_palette (pixman_indexed_t *palette, uint32_t depth, int is_rgb);

typedef struct
{
    double r, g, b, a;
} color_t;

void
round_color (pixman_format_code_t format, color_t *color);

typedef struct
{
    pixman_format_code_t format;
    uint32_t am, rm, gm, bm;
    uint32_t as, rs, gs, bs;
    uint32_t aw, rw, gw, bw;
} pixel_checker_t;

void
pixel_checker_init (pixel_checker_t *checker, pixman_format_code_t format);

void
pixel_checker_split_pixel (const pixel_checker_t *checker, uint32_t pixel,
			   int *a, int *r, int *g, int *b);

void
pixel_checker_get_max (const pixel_checker_t *checker, color_t *color,
		       int *a, int *r, int *g, int *b);

void
pixel_checker_get_min (const pixel_checker_t *checker, color_t *color,
		       int *a, int *r, int *g, int *b);

pixman_bool_t
pixel_checker_check (const pixel_checker_t *checker,
		     uint32_t pixel, color_t *color);