src/test/SDL_test_fuzzer.c
author Ryan C. Gordon <icculus@icculus.org>
Sun, 21 Oct 2018 22:40:17 -0400
changeset 12345 50e1cca28b39
parent 11903 732b6ef4aae7
child 12503 806492103856
permissions -rw-r--r--
wasapi/win32: Sort initial device lists by device GUID.

This makes an unchanged set of hardware always report devices in the same
order on each run.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2018 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                 (Uint64) boundary1, (Uint64) 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() * (double)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: */