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