1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2020 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
SDLTest_FuzzerInit(Uint64 execKey)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
SDLTest_GetFuzzerInvocationCount()73 SDLTest_GetFuzzerInvocationCount()
74 {
75     return fuzzerInvocationCounter;
76 }
77 
78 Uint8
SDLTest_RandomUint8()79 SDLTest_RandomUint8()
80 {
81     fuzzerInvocationCounter++;
82 
83     return (Uint8) SDLTest_RandomInt(&rndContext) & 0x000000FF;
84 }
85 
86 Sint8
SDLTest_RandomSint8()87 SDLTest_RandomSint8()
88 {
89     fuzzerInvocationCounter++;
90 
91     return (Sint8) SDLTest_RandomInt(&rndContext) & 0x000000FF;
92 }
93 
94 Uint16
SDLTest_RandomUint16()95 SDLTest_RandomUint16()
96 {
97     fuzzerInvocationCounter++;
98 
99     return (Uint16) SDLTest_RandomInt(&rndContext) & 0x0000FFFF;
100 }
101 
102 Sint16
SDLTest_RandomSint16()103 SDLTest_RandomSint16()
104 {
105     fuzzerInvocationCounter++;
106 
107     return (Sint16) SDLTest_RandomInt(&rndContext) & 0x0000FFFF;
108 }
109 
110 Sint32
SDLTest_RandomSint32()111 SDLTest_RandomSint32()
112 {
113     fuzzerInvocationCounter++;
114 
115     return (Sint32) SDLTest_RandomInt(&rndContext);
116 }
117 
118 Uint32
SDLTest_RandomUint32()119 SDLTest_RandomUint32()
120 {
121     fuzzerInvocationCounter++;
122 
123     return (Uint32) SDLTest_RandomInt(&rndContext);
124 }
125 
126 Uint64
SDLTest_RandomUint64()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
SDLTest_RandomSint64()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
SDLTest_RandomIntegerInRange(Sint32 pMin,Sint32 pMax)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
SDLTest_GenerateUnsignedBoundaryValues(const Uint64 maxValue,Uint64 boundary1,Uint64 boundary2,SDL_bool validDomain)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
SDLTest_RandomUint8BoundaryValue(Uint8 boundary1,Uint8 boundary2,SDL_bool validDomain)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
SDLTest_RandomUint16BoundaryValue(Uint16 boundary1,Uint16 boundary2,SDL_bool validDomain)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
SDLTest_RandomUint32BoundaryValue(Uint32 boundary1,Uint32 boundary2,SDL_bool validDomain)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
SDLTest_RandomUint64BoundaryValue(Uint64 boundary1,Uint64 boundary2,SDL_bool validDomain)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
SDLTest_GenerateSignedBoundaryValues(const Sint64 minValue,const Sint64 maxValue,Sint64 boundary1,Sint64 boundary2,SDL_bool validDomain)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
SDLTest_RandomSint8BoundaryValue(Sint8 boundary1,Sint8 boundary2,SDL_bool validDomain)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
SDLTest_RandomSint16BoundaryValue(Sint16 boundary1,Sint16 boundary2,SDL_bool validDomain)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
SDLTest_RandomSint32BoundaryValue(Sint32 boundary1,Sint32 boundary2,SDL_bool validDomain)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
SDLTest_RandomSint64BoundaryValue(Sint64 boundary1,Sint64 boundary2,SDL_bool validDomain)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
SDLTest_RandomUnitFloat()452 SDLTest_RandomUnitFloat()
453 {
454     return SDLTest_RandomUint32() / (float) UINT_MAX;
455 }
456 
457 float
SDLTest_RandomFloat()458 SDLTest_RandomFloat()
459 {
460         return (float) (SDLTest_RandomUnitDouble() * 2.0 * (double)FLT_MAX - (double)(FLT_MAX));
461 }
462 
463 double
SDLTest_RandomUnitDouble()464 SDLTest_RandomUnitDouble()
465 {
466     return (double) (SDLTest_RandomUint64() >> 11) * (1.0/9007199254740992.0);
467 }
468 
469 double
SDLTest_RandomDouble()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 *
SDLTest_RandomAsciiString()486 SDLTest_RandomAsciiString()
487 {
488     return SDLTest_RandomAsciiStringWithMaximumLength(255);
489 }
490 
491 char *
SDLTest_RandomAsciiStringWithMaximumLength(int maxLength)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 *
SDLTest_RandomAsciiStringOfSize(int size)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