1 | /* |
2 | Simple DirectMedia Layer |
3 | Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org> |
4 | |
5 | This software is provided 'as-is', without any express or implied |
6 | warranty. In no event will the authors be held liable for any damages |
7 | arising from the use of this software. |
8 | |
9 | Permission is granted to anyone to use this software for any purpose, |
10 | including commercial applications, and to alter it and redistribute it |
11 | freely, subject to the following restrictions: |
12 | |
13 | 1. The origin of this software must not be misrepresented; you must not |
14 | claim that you wrote the original software. If you use this software |
15 | in a product, an acknowledgment in the product documentation would be |
16 | appreciated but is not required. |
17 | 2. Altered source versions must be plainly marked as such, and must not be |
18 | misrepresented as being the original software. |
19 | 3. This notice may not be removed or altered from any source distribution. |
20 | */ |
21 | |
22 | /* |
23 | |
24 | Data generators for fuzzing test data in a reproducible way. |
25 | |
26 | */ |
27 | |
28 | #include "SDL_config.h" |
29 | |
30 | #include <limits.h> |
31 | /* Visual Studio 2008 doesn't have stdint.h */ |
32 | #if defined(_MSC_VER) && _MSC_VER <= 1500 |
33 | #define UINT8_MAX _UI8_MAX |
34 | #define UINT16_MAX _UI16_MAX |
35 | #define UINT32_MAX _UI32_MAX |
36 | #define INT64_MIN _I64_MIN |
37 | #define INT64_MAX _I64_MAX |
38 | #define UINT64_MAX _UI64_MAX |
39 | #else |
40 | #include <stdint.h> |
41 | #endif |
42 | #include <stdio.h> |
43 | #include <stdlib.h> |
44 | #include <float.h> |
45 | |
46 | #include "SDL_test.h" |
47 | |
48 | /** |
49 | * Counter for fuzzer invocations |
50 | */ |
51 | static int fuzzerInvocationCounter = 0; |
52 | |
53 | /** |
54 | * Context for shared random number generator |
55 | */ |
56 | static SDLTest_RandomContext rndContext; |
57 | |
58 | /* |
59 | * Note: doxygen documentation markup for functions is in the header file. |
60 | */ |
61 | |
62 | void |
63 | SDLTest_FuzzerInit(Uint64 execKey) |
64 | { |
65 | Uint32 a = (execKey >> 32) & 0x00000000FFFFFFFF; |
66 | Uint32 b = execKey & 0x00000000FFFFFFFF; |
67 | SDL_memset((void *)&rndContext, 0, sizeof(SDLTest_RandomContext)); |
68 | SDLTest_RandomInit(&rndContext, a, b); |
69 | fuzzerInvocationCounter = 0; |
70 | } |
71 | |
72 | int |
73 | SDLTest_GetFuzzerInvocationCount() |
74 | { |
75 | return fuzzerInvocationCounter; |
76 | } |
77 | |
78 | Uint8 |
79 | SDLTest_RandomUint8() |
80 | { |
81 | fuzzerInvocationCounter++; |
82 | |
83 | return (Uint8) SDLTest_RandomInt(&rndContext) & 0x000000FF; |
84 | } |
85 | |
86 | Sint8 |
87 | SDLTest_RandomSint8() |
88 | { |
89 | fuzzerInvocationCounter++; |
90 | |
91 | return (Sint8) SDLTest_RandomInt(&rndContext) & 0x000000FF; |
92 | } |
93 | |
94 | Uint16 |
95 | SDLTest_RandomUint16() |
96 | { |
97 | fuzzerInvocationCounter++; |
98 | |
99 | return (Uint16) SDLTest_RandomInt(&rndContext) & 0x0000FFFF; |
100 | } |
101 | |
102 | Sint16 |
103 | SDLTest_RandomSint16() |
104 | { |
105 | fuzzerInvocationCounter++; |
106 | |
107 | return (Sint16) SDLTest_RandomInt(&rndContext) & 0x0000FFFF; |
108 | } |
109 | |
110 | Sint32 |
111 | SDLTest_RandomSint32() |
112 | { |
113 | fuzzerInvocationCounter++; |
114 | |
115 | return (Sint32) SDLTest_RandomInt(&rndContext); |
116 | } |
117 | |
118 | Uint32 |
119 | SDLTest_RandomUint32() |
120 | { |
121 | fuzzerInvocationCounter++; |
122 | |
123 | return (Uint32) SDLTest_RandomInt(&rndContext); |
124 | } |
125 | |
126 | Uint64 |
127 | SDLTest_RandomUint64() |
128 | { |
129 | union { |
130 | Uint64 v64; |
131 | Uint32 v32[2]; |
132 | } value; |
133 | value.v64 = 0; |
134 | |
135 | fuzzerInvocationCounter++; |
136 | |
137 | value.v32[0] = SDLTest_RandomSint32(); |
138 | value.v32[1] = SDLTest_RandomSint32(); |
139 | |
140 | return value.v64; |
141 | } |
142 | |
143 | Sint64 |
144 | SDLTest_RandomSint64() |
145 | { |
146 | union { |
147 | Uint64 v64; |
148 | Uint32 v32[2]; |
149 | } value; |
150 | value.v64 = 0; |
151 | |
152 | fuzzerInvocationCounter++; |
153 | |
154 | value.v32[0] = SDLTest_RandomSint32(); |
155 | value.v32[1] = SDLTest_RandomSint32(); |
156 | |
157 | return (Sint64)value.v64; |
158 | } |
159 | |
160 | |
161 | |
162 | Sint32 |
163 | SDLTest_RandomIntegerInRange(Sint32 pMin, Sint32 pMax) |
164 | { |
165 | Sint64 min = pMin; |
166 | Sint64 max = pMax; |
167 | Sint64 temp; |
168 | Sint64 number; |
169 | |
170 | if(pMin > pMax) { |
171 | temp = min; |
172 | min = max; |
173 | max = temp; |
174 | } else if(pMin == pMax) { |
175 | return (Sint32)min; |
176 | } |
177 | |
178 | number = SDLTest_RandomUint32(); |
179 | /* invocation count increment in preceeding call */ |
180 | |
181 | return (Sint32)((number % ((max + 1) - min)) + min); |
182 | } |
183 | |
184 | /* ! |
185 | * Generates a unsigned boundary value between the given boundaries. |
186 | * Boundary values are inclusive. See the examples below. |
187 | * If boundary2 < boundary1, the values are swapped. |
188 | * If boundary1 == boundary2, value of boundary1 will be returned |
189 | * |
190 | * Generating boundary values for Uint8: |
191 | * BoundaryValues(UINT8_MAX, 10, 20, True) -> [10,11,19,20] |
192 | * BoundaryValues(UINT8_MAX, 10, 20, False) -> [9,21] |
193 | * BoundaryValues(UINT8_MAX, 0, 15, True) -> [0, 1, 14, 15] |
194 | * BoundaryValues(UINT8_MAX, 0, 15, False) -> [16] |
195 | * BoundaryValues(UINT8_MAX, 0, 0xFF, False) -> [0], error set |
196 | * |
197 | * Generator works the same for other types of unsigned integers. |
198 | * |
199 | * \param maxValue The biggest value that is acceptable for this data type. |
200 | * For instance, for Uint8 -> 255, Uint16 -> 65536 etc. |
201 | * \param boundary1 defines lower boundary |
202 | * \param boundary2 defines upper boundary |
203 | * \param validDomain Generate only for valid domain (for the data type) |
204 | * |
205 | * \returns Returns a random boundary value for the domain or 0 in case of error |
206 | */ |
207 | static Uint64 |
208 | SDLTest_GenerateUnsignedBoundaryValues(const Uint64 maxValue, Uint64 boundary1, Uint64 boundary2, SDL_bool validDomain) |
209 | { |
210 | Uint64 b1, b2; |
211 | Uint64 delta; |
212 | Uint64 tempBuf[4]; |
213 | Uint8 index; |
214 | |
215 | /* Maybe swap */ |
216 | if (boundary1 > boundary2) { |
217 | b1 = boundary2; |
218 | b2 = boundary1; |
219 | } else { |
220 | b1 = boundary1; |
221 | b2 = boundary2; |
222 | } |
223 | |
224 | index = 0; |
225 | if (validDomain == SDL_TRUE) { |
226 | if (b1 == b2) { |
227 | return b1; |
228 | } |
229 | |
230 | /* Generate up to 4 values within bounds */ |
231 | delta = b2 - b1; |
232 | if (delta < 4) { |
233 | do { |
234 | tempBuf[index] = b1 + index; |
235 | index++; |
236 | } while (index < delta); |
237 | } else { |
238 | tempBuf[index] = b1; |
239 | index++; |
240 | tempBuf[index] = b1 + 1; |
241 | index++; |
242 | tempBuf[index] = b2 - 1; |
243 | index++; |
244 | tempBuf[index] = b2; |
245 | index++; |
246 | } |
247 | } else { |
248 | /* Generate up to 2 values outside of bounds */ |
249 | if (b1 > 0) { |
250 | tempBuf[index] = b1 - 1; |
251 | index++; |
252 | } |
253 | |
254 | if (b2 < maxValue) { |
255 | tempBuf[index] = b2 + 1; |
256 | index++; |
257 | } |
258 | } |
259 | |
260 | if (index == 0) { |
261 | /* There are no valid boundaries */ |
262 | SDL_Unsupported(); |
263 | return 0; |
264 | } |
265 | |
266 | return tempBuf[SDLTest_RandomUint8() % index]; |
267 | } |
268 | |
269 | |
270 | Uint8 |
271 | SDLTest_RandomUint8BoundaryValue(Uint8 boundary1, Uint8 boundary2, SDL_bool validDomain) |
272 | { |
273 | /* max value for Uint8 */ |
274 | const Uint64 maxValue = UCHAR_MAX; |
275 | return (Uint8)SDLTest_GenerateUnsignedBoundaryValues(maxValue, |
276 | (Uint64) boundary1, (Uint64) boundary2, |
277 | validDomain); |
278 | } |
279 | |
280 | Uint16 |
281 | SDLTest_RandomUint16BoundaryValue(Uint16 boundary1, Uint16 boundary2, SDL_bool validDomain) |
282 | { |
283 | /* max value for Uint16 */ |
284 | const Uint64 maxValue = USHRT_MAX; |
285 | return (Uint16)SDLTest_GenerateUnsignedBoundaryValues(maxValue, |
286 | (Uint64) boundary1, (Uint64) boundary2, |
287 | validDomain); |
288 | } |
289 | |
290 | Uint32 |
291 | SDLTest_RandomUint32BoundaryValue(Uint32 boundary1, Uint32 boundary2, SDL_bool validDomain) |
292 | { |
293 | /* max value for Uint32 */ |
294 | #if ((ULONG_MAX) == (UINT_MAX)) |
295 | const Uint64 maxValue = ULONG_MAX; |
296 | #else |
297 | const Uint64 maxValue = UINT_MAX; |
298 | #endif |
299 | return (Uint32)SDLTest_GenerateUnsignedBoundaryValues(maxValue, |
300 | (Uint64) boundary1, (Uint64) boundary2, |
301 | validDomain); |
302 | } |
303 | |
304 | Uint64 |
305 | SDLTest_RandomUint64BoundaryValue(Uint64 boundary1, Uint64 boundary2, SDL_bool validDomain) |
306 | { |
307 | /* max value for Uint64 */ |
308 | const Uint64 maxValue = UINT64_MAX; |
309 | return SDLTest_GenerateUnsignedBoundaryValues(maxValue, |
310 | boundary1, boundary2, |
311 | validDomain); |
312 | } |
313 | |
314 | /* ! |
315 | * Generates a signed boundary value between the given boundaries. |
316 | * Boundary values are inclusive. See the examples below. |
317 | * If boundary2 < boundary1, the values are swapped. |
318 | * If boundary1 == boundary2, value of boundary1 will be returned |
319 | * |
320 | * Generating boundary values for Sint8: |
321 | * SignedBoundaryValues(SCHAR_MIN, SCHAR_MAX, -10, 20, True) -> [-10,-9,19,20] |
322 | * SignedBoundaryValues(SCHAR_MIN, SCHAR_MAX, -10, 20, False) -> [-11,21] |
323 | * SignedBoundaryValues(SCHAR_MIN, SCHAR_MAX, -30, -15, True) -> [-30, -29, -16, -15] |
324 | * SignedBoundaryValues(SCHAR_MIN, SCHAR_MAX, -127, 15, False) -> [16] |
325 | * SignedBoundaryValues(SCHAR_MIN, SCHAR_MAX, -127, 127, False) -> [0], error set |
326 | * |
327 | * Generator works the same for other types of signed integers. |
328 | * |
329 | * \param minValue The smallest value that is acceptable for this data type. |
330 | * For instance, for Uint8 -> -127, etc. |
331 | * \param maxValue The biggest value that is acceptable for this data type. |
332 | * For instance, for Uint8 -> 127, etc. |
333 | * \param boundary1 defines lower boundary |
334 | * \param boundary2 defines upper boundary |
335 | * \param validDomain Generate only for valid domain (for the data type) |
336 | * |
337 | * \returns Returns a random boundary value for the domain or 0 in case of error |
338 | */ |
339 | static Sint64 |
340 | SDLTest_GenerateSignedBoundaryValues(const Sint64 minValue, const Sint64 maxValue, Sint64 boundary1, Sint64 boundary2, SDL_bool validDomain) |
341 | { |
342 | Sint64 b1, b2; |
343 | Sint64 delta; |
344 | Sint64 tempBuf[4]; |
345 | Uint8 index; |
346 | |
347 | /* Maybe swap */ |
348 | if (boundary1 > boundary2) { |
349 | b1 = boundary2; |
350 | b2 = boundary1; |
351 | } else { |
352 | b1 = boundary1; |
353 | b2 = boundary2; |
354 | } |
355 | |
356 | index = 0; |
357 | if (validDomain == SDL_TRUE) { |
358 | if (b1 == b2) { |
359 | return b1; |
360 | } |
361 | |
362 | /* Generate up to 4 values within bounds */ |
363 | delta = b2 - b1; |
364 | if (delta < 4) { |
365 | do { |
366 | tempBuf[index] = b1 + index; |
367 | index++; |
368 | } while (index < delta); |
369 | } else { |
370 | tempBuf[index] = b1; |
371 | index++; |
372 | tempBuf[index] = b1 + 1; |
373 | index++; |
374 | tempBuf[index] = b2 - 1; |
375 | index++; |
376 | tempBuf[index] = b2; |
377 | index++; |
378 | } |
379 | } else { |
380 | /* Generate up to 2 values outside of bounds */ |
381 | if (b1 > minValue) { |
382 | tempBuf[index] = b1 - 1; |
383 | index++; |
384 | } |
385 | |
386 | if (b2 < maxValue) { |
387 | tempBuf[index] = b2 + 1; |
388 | index++; |
389 | } |
390 | } |
391 | |
392 | if (index == 0) { |
393 | /* There are no valid boundaries */ |
394 | SDL_Unsupported(); |
395 | return minValue; |
396 | } |
397 | |
398 | return tempBuf[SDLTest_RandomUint8() % index]; |
399 | } |
400 | |
401 | |
402 | Sint8 |
403 | SDLTest_RandomSint8BoundaryValue(Sint8 boundary1, Sint8 boundary2, SDL_bool validDomain) |
404 | { |
405 | /* min & max values for Sint8 */ |
406 | const Sint64 maxValue = SCHAR_MAX; |
407 | const Sint64 minValue = SCHAR_MIN; |
408 | return (Sint8)SDLTest_GenerateSignedBoundaryValues(minValue, maxValue, |
409 | (Sint64) boundary1, (Sint64) boundary2, |
410 | validDomain); |
411 | } |
412 | |
413 | Sint16 |
414 | SDLTest_RandomSint16BoundaryValue(Sint16 boundary1, Sint16 boundary2, SDL_bool validDomain) |
415 | { |
416 | /* min & max values for Sint16 */ |
417 | const Sint64 maxValue = SHRT_MAX; |
418 | const Sint64 minValue = SHRT_MIN; |
419 | return (Sint16)SDLTest_GenerateSignedBoundaryValues(minValue, maxValue, |
420 | (Sint64) boundary1, (Sint64) boundary2, |
421 | validDomain); |
422 | } |
423 | |
424 | Sint32 |
425 | SDLTest_RandomSint32BoundaryValue(Sint32 boundary1, Sint32 boundary2, SDL_bool validDomain) |
426 | { |
427 | /* min & max values for Sint32 */ |
428 | #if ((ULONG_MAX) == (UINT_MAX)) |
429 | const Sint64 maxValue = LONG_MAX; |
430 | const Sint64 minValue = LONG_MIN; |
431 | #else |
432 | const Sint64 maxValue = INT_MAX; |
433 | const Sint64 minValue = INT_MIN; |
434 | #endif |
435 | return (Sint32)SDLTest_GenerateSignedBoundaryValues(minValue, maxValue, |
436 | (Sint64) boundary1, (Sint64) boundary2, |
437 | validDomain); |
438 | } |
439 | |
440 | Sint64 |
441 | SDLTest_RandomSint64BoundaryValue(Sint64 boundary1, Sint64 boundary2, SDL_bool validDomain) |
442 | { |
443 | /* min & max values for Sint64 */ |
444 | const Sint64 maxValue = INT64_MAX; |
445 | const Sint64 minValue = INT64_MIN; |
446 | return SDLTest_GenerateSignedBoundaryValues(minValue, maxValue, |
447 | boundary1, boundary2, |
448 | validDomain); |
449 | } |
450 | |
451 | float |
452 | SDLTest_RandomUnitFloat() |
453 | { |
454 | return SDLTest_RandomUint32() / (float) UINT_MAX; |
455 | } |
456 | |
457 | float |
458 | SDLTest_RandomFloat() |
459 | { |
460 | return (float) (SDLTest_RandomUnitDouble() * 2.0 * (double)FLT_MAX - (double)(FLT_MAX)); |
461 | } |
462 | |
463 | double |
464 | SDLTest_RandomUnitDouble() |
465 | { |
466 | return (double) (SDLTest_RandomUint64() >> 11) * (1.0/9007199254740992.0); |
467 | } |
468 | |
469 | double |
470 | SDLTest_RandomDouble() |
471 | { |
472 | double r = 0.0; |
473 | double s = 1.0; |
474 | do { |
475 | s /= UINT_MAX + 1.0; |
476 | r += (double)SDLTest_RandomInt(&rndContext) * s; |
477 | } while (s > DBL_EPSILON); |
478 | |
479 | fuzzerInvocationCounter++; |
480 | |
481 | return r; |
482 | } |
483 | |
484 | |
485 | char * |
486 | SDLTest_RandomAsciiString() |
487 | { |
488 | return SDLTest_RandomAsciiStringWithMaximumLength(255); |
489 | } |
490 | |
491 | char * |
492 | SDLTest_RandomAsciiStringWithMaximumLength(int maxLength) |
493 | { |
494 | int size; |
495 | |
496 | if(maxLength < 1) { |
497 | SDL_InvalidParamError("maxLength" ); |
498 | return NULL; |
499 | } |
500 | |
501 | size = (SDLTest_RandomUint32() % (maxLength + 1)); |
502 | |
503 | return SDLTest_RandomAsciiStringOfSize(size); |
504 | } |
505 | |
506 | char * |
507 | SDLTest_RandomAsciiStringOfSize(int size) |
508 | { |
509 | char *string; |
510 | int counter; |
511 | |
512 | |
513 | if(size < 1) { |
514 | SDL_InvalidParamError("size" ); |
515 | return NULL; |
516 | } |
517 | |
518 | string = (char *)SDL_malloc((size + 1) * sizeof(char)); |
519 | if (string==NULL) { |
520 | return NULL; |
521 | } |
522 | |
523 | for(counter = 0; counter < size; ++counter) { |
524 | string[counter] = (char)SDLTest_RandomIntegerInRange(32, 126); |
525 | } |
526 | |
527 | string[counter] = '\0'; |
528 | |
529 | fuzzerInvocationCounter++; |
530 | |
531 | return string; |
532 | } |
533 | |
534 | /* vi: set ts=4 sw=4 expandtab: */ |
535 | |