upgrade SDL to version 2.0.8
[platform/upstream/SDL.git] / src / test / SDL_test_fuzzer.c
1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2018 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                 (Uint64) boundary1, (Uint64) 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
403 Sint8
404 SDLTest_RandomSint8BoundaryValue(Sint8 boundary1, Sint8 boundary2, SDL_bool validDomain)
405 {
406     /* min & max values for Sint8 */
407     const Sint64 maxValue = SCHAR_MAX;
408     const Sint64 minValue = SCHAR_MIN;
409     return (Sint8)SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
410                 (Sint64) boundary1, (Sint64) boundary2,
411                 validDomain);
412 }
413
414 Sint16
415 SDLTest_RandomSint16BoundaryValue(Sint16 boundary1, Sint16 boundary2, SDL_bool validDomain)
416 {
417     /* min & max values for Sint16 */
418     const Sint64 maxValue = SHRT_MAX;
419     const Sint64 minValue = SHRT_MIN;
420     return (Sint16)SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
421                 (Sint64) boundary1, (Sint64) boundary2,
422                 validDomain);
423 }
424
425 Sint32
426 SDLTest_RandomSint32BoundaryValue(Sint32 boundary1, Sint32 boundary2, SDL_bool validDomain)
427 {
428     /* min & max values for Sint32 */
429     #if ((ULONG_MAX) == (UINT_MAX))
430       const Sint64 maxValue = LONG_MAX;
431       const Sint64 minValue = LONG_MIN;
432         #else
433       const Sint64 maxValue = INT_MAX;
434       const Sint64 minValue = INT_MIN;
435         #endif
436     return (Sint32)SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
437                 (Sint64) boundary1, (Sint64) boundary2,
438                 validDomain);
439 }
440
441 Sint64
442 SDLTest_RandomSint64BoundaryValue(Sint64 boundary1, Sint64 boundary2, SDL_bool validDomain)
443 {
444     /* min & max values for Sint64 */
445     const Sint64 maxValue = INT64_MAX;
446     const Sint64 minValue = INT64_MIN;
447     return SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
448                 boundary1, boundary2,
449                 validDomain);
450 }
451
452 float
453 SDLTest_RandomUnitFloat()
454 {
455     return SDLTest_RandomUint32() / (float) UINT_MAX;
456 }
457
458 float
459 SDLTest_RandomFloat()
460 {
461         return (float) (SDLTest_RandomUnitDouble() * (double)2.0 * (double)FLT_MAX - (double)(FLT_MAX));
462 }
463
464 double
465 SDLTest_RandomUnitDouble()
466 {
467     return (double) (SDLTest_RandomUint64() >> 11) * (1.0/9007199254740992.0);
468 }
469
470 double
471 SDLTest_RandomDouble()
472 {
473     double r = 0.0;
474     double s = 1.0;
475     do {
476       s /= UINT_MAX + 1.0;
477       r += (double)SDLTest_RandomInt(&rndContext) * s;
478     } while (s > DBL_EPSILON);
479
480     fuzzerInvocationCounter++;
481
482     return r;
483 }
484
485
486 char *
487 SDLTest_RandomAsciiString()
488 {
489     return SDLTest_RandomAsciiStringWithMaximumLength(255);
490 }
491
492 char *
493 SDLTest_RandomAsciiStringWithMaximumLength(int maxLength)
494 {
495     int size;
496
497     if(maxLength < 1) {
498                 SDL_InvalidParamError("maxLength");
499         return NULL;
500     }
501
502     size = (SDLTest_RandomUint32() % (maxLength + 1));
503
504     return SDLTest_RandomAsciiStringOfSize(size);
505 }
506
507 char *
508 SDLTest_RandomAsciiStringOfSize(int size)
509 {
510     char *string;
511     int counter;
512
513
514     if(size < 1) {
515                 SDL_InvalidParamError("size");
516         return NULL;
517     }
518
519     string = (char *)SDL_malloc((size + 1) * sizeof(char));
520     if (string==NULL) {
521       return NULL;
522         }
523
524     for(counter = 0; counter < size; ++counter) {
525         string[counter] = (char)SDLTest_RandomIntegerInRange(32, 126);
526     }
527
528     string[counter] = '\0';
529
530     fuzzerInvocationCounter++;
531
532     return string;
533 }
534
535 /* vi: set ts=4 sw=4 expandtab: */