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