sdl

FORK: Simple Directmedia Layer
git clone https://git.neptards.moe/neptards/sdl.git
Log | Files | Refs

SDL_test_fuzzer.c (13629B)


      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
     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                 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
    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
    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
    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
    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
    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
    452 SDLTest_RandomUnitFloat()
    453 {
    454     return SDLTest_RandomUint32() / (float) UINT_MAX;
    455 }
    456 
    457 float
    458 SDLTest_RandomFloat()
    459 {
    460         return (float) (SDLTest_RandomUnitDouble() * 2.0 * (double)FLT_MAX - (double)(FLT_MAX));
    461 }
    462 
    463 double
    464 SDLTest_RandomUnitDouble()
    465 {
    466     return (double) (SDLTest_RandomUint64() >> 11) * (1.0/9007199254740992.0);
    467 }
    468 
    469 double
    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 *
    486 SDLTest_RandomAsciiString()
    487 {
    488     return SDLTest_RandomAsciiStringWithMaximumLength(255);
    489 }
    490 
    491 char *
    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 *
    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: */