• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifdef HAVE_CONFIG_H
2 #include <config.h>
3 #endif
4 
5 #include <assert.h>
6 #include "pixman-private.h" /* For 'inline' definition */
7 #include "utils-prng.h"
8 
9 #if defined(_MSC_VER)
10 #define snprintf _snprintf
11 #define strcasecmp _stricmp
12 #endif
13 
14 #define ARRAY_LENGTH(A) ((int) (sizeof (A) / sizeof ((A) [0])))
15 
16 /* A primitive pseudorandom number generator,
17  * taken from POSIX.1-2001 example
18  */
19 
20 extern prng_t prng_state_data;
21 extern prng_t *prng_state;
22 #ifdef USE_OPENMP
23 #pragma omp threadprivate(prng_state_data)
24 #pragma omp threadprivate(prng_state)
25 #endif
26 
27 static inline uint32_t
prng_rand(void)28 prng_rand (void)
29 {
30     return prng_rand_r (prng_state);
31 }
32 
33 static inline void
prng_srand(uint32_t seed)34 prng_srand (uint32_t seed)
35 {
36     if (!prng_state)
37     {
38         /* Without setting a seed, PRNG does not work properly (is just
39          * returning zeros). So we only initialize the pointer here to
40          * make sure that 'prng_srand' is always called before any
41          * other 'prng_*' function. The wrongdoers violating this order
42          * will get a segfault. */
43         prng_state = &prng_state_data;
44     }
45     prng_srand_r (prng_state, seed);
46 }
47 
48 static inline uint32_t
prng_rand_n(int max)49 prng_rand_n (int max)
50 {
51     return prng_rand () % max;
52 }
53 
54 static inline void
prng_randmemset(void * buffer,size_t size,prng_randmemset_flags_t flags)55 prng_randmemset (void *buffer, size_t size, prng_randmemset_flags_t flags)
56 {
57     prng_randmemset_r (prng_state, buffer, size, flags);
58 }
59 
60 /* CRC 32 computation
61  */
62 uint32_t
63 compute_crc32 (uint32_t    in_crc32,
64 	       const void *buf,
65 	       size_t      buf_len);
66 
67 uint32_t
68 compute_crc32_for_image (uint32_t        in_crc32,
69 			 pixman_image_t *image);
70 
71 /* Print the image in hexadecimal */
72 void
73 print_image (pixman_image_t *image);
74 
75 /* Returns TRUE if running on a little endian system
76  */
77 static force_inline pixman_bool_t
is_little_endian(void)78 is_little_endian (void)
79 {
80     unsigned long endian_check_var = 1;
81     return *(unsigned char *)&endian_check_var == 1;
82 }
83 
84 /* perform endian conversion of pixel data
85  */
86 void
87 image_endian_swap (pixman_image_t *img);
88 
89 #if defined (HAVE_MPROTECT) && defined (HAVE_GETPAGESIZE) && \
90     defined (HAVE_SYS_MMAN_H) && defined (HAVE_MMAP)
91 /* fence_malloc and friends have working fence implementation.
92  * Without this, fence_malloc still allocs but does not catch
93  * out-of-bounds accesses.
94  */
95 #define FENCE_MALLOC_ACTIVE 1
96 #else
97 #define FENCE_MALLOC_ACTIVE 0
98 #endif
99 
100 /* Allocate memory that is bounded by protected pages,
101  * so that out-of-bounds access will cause segfaults
102  */
103 void *
104 fence_malloc (int64_t len);
105 
106 void
107 fence_free (void *data);
108 
109 pixman_image_t *
110 fence_image_create_bits (pixman_format_code_t format,
111                          int min_width,
112                          int height,
113                          pixman_bool_t stride_fence);
114 
115 /* Return the page size if FENCE_MALLOC_ACTIVE, or zero otherwise */
116 unsigned long
117 fence_get_page_size ();
118 
119 /* Generate n_bytes random bytes in fence_malloced memory */
120 uint8_t *
121 make_random_bytes (int n_bytes);
122 float *
123 make_random_floats (int n_bytes);
124 
125 /* Return current time in seconds */
126 double
127 gettime (void);
128 
129 uint32_t
130 get_random_seed (void);
131 
132 /* main body of the fuzzer test */
133 int
134 fuzzer_test_main (const char *test_name,
135 		  int         default_number_of_iterations,
136 		  uint32_t    expected_checksum,
137 		  uint32_t    (*test_function)(int testnum, int verbose),
138 		  int         argc,
139 		  const char *argv[]);
140 
141 void
142 fail_after (int seconds, const char *msg);
143 
144 /* If possible, enable traps for floating point exceptions */
145 void enable_divbyzero_exceptions(void);
146 void enable_invalid_exceptions(void);
147 
148 /* Converts a8r8g8b8 pixels to pixels that
149  *  - are not premultiplied,
150  *  - are stored in this order in memory: R, G, B, A, regardless of
151  *    the endianness of the computer.
152  * It is allowed for @src and @dst to point to the same memory buffer.
153  */
154 void
155 a8r8g8b8_to_rgba_np (uint32_t *dst, uint32_t *src, int n_pixels);
156 
157 pixman_bool_t
158 write_png (pixman_image_t *image, const char *filename);
159 
160 void
161 draw_checkerboard (pixman_image_t *image,
162 		   int check_size,
163 		   uint32_t color1, uint32_t color2);
164 
165 /* A pair of macros which can help to detect corruption of
166  * floating point registers after a function call. This may
167  * happen if _mm_empty() call is forgotten in MMX/SSE2 fast
168  * path code, or ARM NEON assembly optimized function forgets
169  * to save/restore d8-d15 registers before use.
170  */
171 
172 #define FLOAT_REGS_CORRUPTION_DETECTOR_START()                 \
173     static volatile double frcd_volatile_constant1 = 123451;   \
174     static volatile double frcd_volatile_constant2 = 123452;   \
175     static volatile double frcd_volatile_constant3 = 123453;   \
176     static volatile double frcd_volatile_constant4 = 123454;   \
177     static volatile double frcd_volatile_constant5 = 123455;   \
178     static volatile double frcd_volatile_constant6 = 123456;   \
179     static volatile double frcd_volatile_constant7 = 123457;   \
180     static volatile double frcd_volatile_constant8 = 123458;   \
181     double frcd_canary_variable1 = frcd_volatile_constant1;    \
182     double frcd_canary_variable2 = frcd_volatile_constant2;    \
183     double frcd_canary_variable3 = frcd_volatile_constant3;    \
184     double frcd_canary_variable4 = frcd_volatile_constant4;    \
185     double frcd_canary_variable5 = frcd_volatile_constant5;    \
186     double frcd_canary_variable6 = frcd_volatile_constant6;    \
187     double frcd_canary_variable7 = frcd_volatile_constant7;    \
188     double frcd_canary_variable8 = frcd_volatile_constant8;
189 
190 #define FLOAT_REGS_CORRUPTION_DETECTOR_FINISH()                \
191     assert (frcd_canary_variable1 == frcd_volatile_constant1); \
192     assert (frcd_canary_variable2 == frcd_volatile_constant2); \
193     assert (frcd_canary_variable3 == frcd_volatile_constant3); \
194     assert (frcd_canary_variable4 == frcd_volatile_constant4); \
195     assert (frcd_canary_variable5 == frcd_volatile_constant5); \
196     assert (frcd_canary_variable6 == frcd_volatile_constant6); \
197     assert (frcd_canary_variable7 == frcd_volatile_constant7); \
198     assert (frcd_canary_variable8 == frcd_volatile_constant8);
199 
200 /* Try to get an aligned memory chunk */
201 void *
202 aligned_malloc (size_t align, size_t size);
203 
204 double
205 convert_srgb_to_linear (double component);
206 
207 double
208 convert_linear_to_srgb (double component);
209 
210 void
211 initialize_palette (pixman_indexed_t *palette, uint32_t depth, int is_rgb);
212 
213 pixman_format_code_t
214 format_from_string (const char *s);
215 
216 void
217 list_formats (void);
218 
219 void
220 list_operators (void);
221 
222 void list_dithers (void);
223 
224 pixman_op_t
225 operator_from_string (const char *s);
226 
227 pixman_dither_t
228 dither_from_string (const char *s);
229 
230 const char *
231 operator_name (pixman_op_t op);
232 
233 const char *
234 format_name (pixman_format_code_t format);
235 
236 const char *
237 dither_name (pixman_dither_t dither);
238 
239 typedef struct
240 {
241     double r, g, b, a;
242 } color_t;
243 
244 void
245 do_composite (pixman_op_t op,
246 	      const color_t *src,
247 	      const color_t *mask,
248 	      const color_t *dst,
249 	      color_t *result,
250 	      pixman_bool_t component_alpha);
251 
252 void
253 round_color (pixman_format_code_t format, color_t *color);
254 
255 typedef struct
256 {
257     pixman_format_code_t format;
258     uint32_t am, rm, gm, bm;
259     uint32_t as, rs, gs, bs;
260     uint32_t aw, rw, gw, bw;
261     float ad, rd, gd, bd;
262 } pixel_checker_t;
263 
264 void
265 pixel_checker_init (pixel_checker_t *checker, pixman_format_code_t format);
266 
267 void
268 pixel_checker_allow_dither (pixel_checker_t *checker);
269 
270 void
271 pixel_checker_split_pixel (const pixel_checker_t *checker, uint32_t pixel,
272 			   int *a, int *r, int *g, int *b);
273 
274 void
275 pixel_checker_get_max (const pixel_checker_t *checker, color_t *color,
276 		       int *a, int *r, int *g, int *b);
277 
278 void
279 pixel_checker_get_min (const pixel_checker_t *checker, color_t *color,
280 		       int *a, int *r, int *g, int *b);
281 
282 pixman_bool_t
283 pixel_checker_check (const pixel_checker_t *checker,
284 		     uint32_t pixel, color_t *color);
285 
286 void
287 pixel_checker_convert_pixel_to_color (const pixel_checker_t *checker,
288                                       uint32_t pixel, color_t *color);
289 
290 void
291 pixel_checker_get_masks (const pixel_checker_t *checker,
292                          uint32_t              *am,
293                          uint32_t              *rm,
294                          uint32_t              *gm,
295                          uint32_t              *bm);
296