src/test/SDL_test_fuzzer.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 01 Jan 2017 18:33:28 -0800
changeset 10737 3406a0f8b041
parent 10635 49026b20848e
child 11465 9843b1895c45
permissions -rw-r--r--
Updated copyright for 2017
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2017 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     Uint64 value = 0;
   130     Uint32 *vp = (void *)&value;
   131 
   132     fuzzerInvocationCounter++;
   133 
   134     vp[0] = SDLTest_RandomSint32();
   135     vp[1] = SDLTest_RandomSint32();
   136 
   137     return value;
   138 }
   139 
   140 Sint64
   141 SDLTest_RandomSint64()
   142 {
   143     Uint64 value = 0;
   144     Uint32 *vp = (void *)&value;
   145 
   146     fuzzerInvocationCounter++;
   147 
   148     vp[0] = SDLTest_RandomSint32();
   149     vp[1] = SDLTest_RandomSint32();
   150 
   151     return value;
   152 }
   153 
   154 
   155 
   156 Sint32
   157 SDLTest_RandomIntegerInRange(Sint32 pMin, Sint32 pMax)
   158 {
   159     Sint64 min = pMin;
   160     Sint64 max = pMax;
   161     Sint64 temp;
   162     Sint64 number;
   163 
   164     if(pMin > pMax) {
   165         temp = min;
   166         min = max;
   167         max = temp;
   168     } else if(pMin == pMax) {
   169         return (Sint32)min;
   170     }
   171 
   172     number = SDLTest_RandomUint32();
   173     /* invocation count increment in preceeding call */
   174 
   175     return (Sint32)((number % ((max + 1) - min)) + min);
   176 }
   177 
   178 /* !
   179  * Generates a unsigned boundary value between the given boundaries.
   180  * Boundary values are inclusive. See the examples below.
   181  * If boundary2 < boundary1, the values are swapped.
   182  * If boundary1 == boundary2, value of boundary1 will be returned
   183  *
   184  * Generating boundary values for Uint8:
   185  * BoundaryValues(UINT8_MAX, 10, 20, True) -> [10,11,19,20]
   186  * BoundaryValues(UINT8_MAX, 10, 20, False) -> [9,21]
   187  * BoundaryValues(UINT8_MAX, 0, 15, True) -> [0, 1, 14, 15]
   188  * BoundaryValues(UINT8_MAX, 0, 15, False) -> [16]
   189  * BoundaryValues(UINT8_MAX, 0, 0xFF, False) -> [0], error set
   190  *
   191  * Generator works the same for other types of unsigned integers.
   192  *
   193  * \param maxValue The biggest value that is acceptable for this data type.
   194  *                  For instance, for Uint8 -> 255, Uint16 -> 65536 etc.
   195  * \param boundary1 defines lower boundary
   196  * \param boundary2 defines upper boundary
   197  * \param validDomain Generate only for valid domain (for the data type)
   198  *
   199  * \returns Returns a random boundary value for the domain or 0 in case of error
   200  */
   201 static Uint64
   202 SDLTest_GenerateUnsignedBoundaryValues(const Uint64 maxValue, Uint64 boundary1, Uint64 boundary2, SDL_bool validDomain)
   203 {
   204         Uint64 b1, b2;
   205     Uint64 delta;
   206     Uint64 tempBuf[4];
   207     Uint8 index;
   208 
   209         /* Maybe swap */
   210     if (boundary1 > boundary2) {
   211         b1 = boundary2;
   212         b2 = boundary1;
   213     } else {
   214         b1 = boundary1;
   215         b2 = boundary2;
   216         }
   217 
   218     index = 0;
   219     if (validDomain == SDL_TRUE) {
   220             if (b1 == b2) {
   221                 return b1;
   222             }
   223 
   224             /* Generate up to 4 values within bounds */
   225             delta = b2 - b1;
   226             if (delta < 4) {
   227                 do {
   228                 tempBuf[index] = b1 + index;
   229                 index++;
   230                     } while (index < delta);
   231             } else {
   232           tempBuf[index] = b1;
   233           index++;
   234           tempBuf[index] = b1 + 1;
   235           index++;
   236           tempBuf[index] = b2 - 1;
   237           index++;
   238           tempBuf[index] = b2;
   239           index++;
   240             }
   241         } else {
   242             /* Generate up to 2 values outside of bounds */
   243         if (b1 > 0) {
   244             tempBuf[index] = b1 - 1;
   245             index++;
   246         }
   247 
   248         if (b2 < maxValue) {
   249             tempBuf[index] = b2 + 1;
   250             index++;
   251         }
   252     }
   253 
   254     if (index == 0) {
   255         /* There are no valid boundaries */
   256         SDL_Unsupported();
   257         return 0;
   258     }
   259 
   260     return tempBuf[SDLTest_RandomUint8() % index];
   261 }
   262 
   263 
   264 Uint8
   265 SDLTest_RandomUint8BoundaryValue(Uint8 boundary1, Uint8 boundary2, SDL_bool validDomain)
   266 {
   267     /* max value for Uint8 */
   268     const Uint64 maxValue = UCHAR_MAX;
   269     return (Uint8)SDLTest_GenerateUnsignedBoundaryValues(maxValue,
   270                 (Uint64) boundary1, (Uint64) boundary2,
   271                 validDomain);
   272 }
   273 
   274 Uint16
   275 SDLTest_RandomUint16BoundaryValue(Uint16 boundary1, Uint16 boundary2, SDL_bool validDomain)
   276 {
   277     /* max value for Uint16 */
   278     const Uint64 maxValue = USHRT_MAX;
   279     return (Uint16)SDLTest_GenerateUnsignedBoundaryValues(maxValue,
   280                 (Uint64) boundary1, (Uint64) boundary2,
   281                 validDomain);
   282 }
   283 
   284 Uint32
   285 SDLTest_RandomUint32BoundaryValue(Uint32 boundary1, Uint32 boundary2, SDL_bool validDomain)
   286 {
   287     /* max value for Uint32 */
   288     #if ((ULONG_MAX) == (UINT_MAX))
   289       const Uint64 maxValue = ULONG_MAX;
   290         #else
   291       const Uint64 maxValue = UINT_MAX;
   292         #endif
   293     return (Uint32)SDLTest_GenerateUnsignedBoundaryValues(maxValue,
   294                 (Uint64) boundary1, (Uint64) boundary2,
   295                 validDomain);
   296 }
   297 
   298 Uint64
   299 SDLTest_RandomUint64BoundaryValue(Uint64 boundary1, Uint64 boundary2, SDL_bool validDomain)
   300 {
   301     /* max value for Uint64 */
   302     const Uint64 maxValue = UINT64_MAX;
   303     return SDLTest_GenerateUnsignedBoundaryValues(maxValue,
   304                 (Uint64) boundary1, (Uint64) boundary2,
   305                 validDomain);
   306 }
   307 
   308 /* !
   309  * Generates a signed boundary value between the given boundaries.
   310  * Boundary values are inclusive. See the examples below.
   311  * If boundary2 < boundary1, the values are swapped.
   312  * If boundary1 == boundary2, value of boundary1 will be returned
   313  *
   314  * Generating boundary values for Sint8:
   315  * SignedBoundaryValues(SCHAR_MIN, SCHAR_MAX, -10, 20, True) -> [-10,-9,19,20]
   316  * SignedBoundaryValues(SCHAR_MIN, SCHAR_MAX, -10, 20, False) -> [-11,21]
   317  * SignedBoundaryValues(SCHAR_MIN, SCHAR_MAX, -30, -15, True) -> [-30, -29, -16, -15]
   318  * SignedBoundaryValues(SCHAR_MIN, SCHAR_MAX, -127, 15, False) -> [16]
   319  * SignedBoundaryValues(SCHAR_MIN, SCHAR_MAX, -127, 127, False) -> [0], error set
   320  *
   321  * Generator works the same for other types of signed integers.
   322  *
   323  * \param minValue The smallest value that is acceptable for this data type.
   324  *                  For instance, for Uint8 -> -127, etc.
   325  * \param maxValue The biggest value that is acceptable for this data type.
   326  *                  For instance, for Uint8 -> 127, etc.
   327  * \param boundary1 defines lower boundary
   328  * \param boundary2 defines upper boundary
   329  * \param validDomain Generate only for valid domain (for the data type)
   330  *
   331  * \returns Returns a random boundary value for the domain or 0 in case of error
   332  */
   333 static Sint64
   334 SDLTest_GenerateSignedBoundaryValues(const Sint64 minValue, const Sint64 maxValue, Sint64 boundary1, Sint64 boundary2, SDL_bool validDomain)
   335 {
   336         Sint64 b1, b2;
   337     Sint64 delta;
   338     Sint64 tempBuf[4];
   339     Uint8 index;
   340 
   341         /* Maybe swap */
   342     if (boundary1 > boundary2) {
   343         b1 = boundary2;
   344         b2 = boundary1;
   345     } else {
   346         b1 = boundary1;
   347         b2 = boundary2;
   348         }
   349 
   350     index = 0;
   351     if (validDomain == SDL_TRUE) {
   352             if (b1 == b2) {
   353                 return b1;
   354             }
   355 
   356             /* Generate up to 4 values within bounds */
   357             delta = b2 - b1;
   358             if (delta < 4) {
   359                 do {
   360                 tempBuf[index] = b1 + index;
   361                 index++;
   362                     } while (index < delta);
   363             } else {
   364           tempBuf[index] = b1;
   365           index++;
   366           tempBuf[index] = b1 + 1;
   367           index++;
   368           tempBuf[index] = b2 - 1;
   369           index++;
   370           tempBuf[index] = b2;
   371           index++;
   372             }
   373         } else {
   374             /* Generate up to 2 values outside of bounds */
   375         if (b1 > minValue) {
   376             tempBuf[index] = b1 - 1;
   377             index++;
   378         }
   379 
   380         if (b2 < maxValue) {
   381             tempBuf[index] = b2 + 1;
   382             index++;
   383         }
   384     }
   385 
   386     if (index == 0) {
   387         /* There are no valid boundaries */
   388         SDL_Unsupported();
   389         return minValue;
   390     }
   391 
   392     return tempBuf[SDLTest_RandomUint8() % index];
   393 }
   394 
   395 
   396 Sint8
   397 SDLTest_RandomSint8BoundaryValue(Sint8 boundary1, Sint8 boundary2, SDL_bool validDomain)
   398 {
   399     /* min & max values for Sint8 */
   400     const Sint64 maxValue = SCHAR_MAX;
   401     const Sint64 minValue = SCHAR_MIN;
   402     return (Sint8)SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
   403                 (Sint64) boundary1, (Sint64) boundary2,
   404                 validDomain);
   405 }
   406 
   407 Sint16
   408 SDLTest_RandomSint16BoundaryValue(Sint16 boundary1, Sint16 boundary2, SDL_bool validDomain)
   409 {
   410     /* min & max values for Sint16 */
   411     const Sint64 maxValue = SHRT_MAX;
   412     const Sint64 minValue = SHRT_MIN;
   413     return (Sint16)SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
   414                 (Sint64) boundary1, (Sint64) boundary2,
   415                 validDomain);
   416 }
   417 
   418 Sint32
   419 SDLTest_RandomSint32BoundaryValue(Sint32 boundary1, Sint32 boundary2, SDL_bool validDomain)
   420 {
   421     /* min & max values for Sint32 */
   422     #if ((ULONG_MAX) == (UINT_MAX))
   423       const Sint64 maxValue = LONG_MAX;
   424       const Sint64 minValue = LONG_MIN;
   425         #else
   426       const Sint64 maxValue = INT_MAX;
   427       const Sint64 minValue = INT_MIN;
   428         #endif
   429     return (Sint32)SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
   430                 (Sint64) boundary1, (Sint64) boundary2,
   431                 validDomain);
   432 }
   433 
   434 Sint64
   435 SDLTest_RandomSint64BoundaryValue(Sint64 boundary1, Sint64 boundary2, SDL_bool validDomain)
   436 {
   437     /* min & max values for Sint64 */
   438     const Sint64 maxValue = INT64_MAX;
   439     const Sint64 minValue = INT64_MIN;
   440     return SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
   441                 boundary1, boundary2,
   442                 validDomain);
   443 }
   444 
   445 float
   446 SDLTest_RandomUnitFloat()
   447 {
   448     return SDLTest_RandomUint32() / (float) UINT_MAX;
   449 }
   450 
   451 float
   452 SDLTest_RandomFloat()
   453 {
   454         return (float) (SDLTest_RandomUnitDouble() * (double)2.0 * (double)FLT_MAX - (double)(FLT_MAX));
   455 }
   456 
   457 double
   458 SDLTest_RandomUnitDouble()
   459 {
   460     return (double) (SDLTest_RandomUint64() >> 11) * (1.0/9007199254740992.0);
   461 }
   462 
   463 double
   464 SDLTest_RandomDouble()
   465 {
   466     double r = 0.0;
   467     double s = 1.0;
   468     do {
   469       s /= UINT_MAX + 1.0;
   470       r += (double)SDLTest_RandomInt(&rndContext) * s;
   471     } while (s > DBL_EPSILON);
   472 
   473     fuzzerInvocationCounter++;
   474 
   475     return r;
   476 }
   477 
   478 
   479 char *
   480 SDLTest_RandomAsciiString()
   481 {
   482     return SDLTest_RandomAsciiStringWithMaximumLength(255);
   483 }
   484 
   485 char *
   486 SDLTest_RandomAsciiStringWithMaximumLength(int maxLength)
   487 {
   488     int size;
   489 
   490     if(maxLength < 1) {
   491                 SDL_InvalidParamError("maxLength");
   492         return NULL;
   493     }
   494 
   495     size = (SDLTest_RandomUint32() % (maxLength + 1));
   496 
   497     return SDLTest_RandomAsciiStringOfSize(size);
   498 }
   499 
   500 char *
   501 SDLTest_RandomAsciiStringOfSize(int size)
   502 {
   503     char *string;
   504     int counter;
   505 
   506 
   507     if(size < 1) {
   508                 SDL_InvalidParamError("size");
   509         return NULL;
   510     }
   511 
   512     string = (char *)SDL_malloc((size + 1) * sizeof(char));
   513     if (string==NULL) {
   514       return NULL;
   515         }
   516 
   517     for(counter = 0; counter < size; ++counter) {
   518         string[counter] = (char)SDLTest_RandomIntegerInRange(32, 126);
   519     }
   520 
   521     string[counter] = '\0';
   522 
   523     fuzzerInvocationCounter++;
   524 
   525     return string;
   526 }