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