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