src/test/SDL_test_fuzzer.c
author Andreas Schiffler <aschiffler@ferzkopp.net>
Tue, 12 Feb 2013 22:23:42 -0800
changeset 6872 2f4c95464651
parent 6839 2494f667555c
child 6885 700f1b25f77f
permissions -rw-r--r--
Fix fuzzer random boundary functions; add tests for fuzzer
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2012 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  */
    49 static int fuzzerInvocationCounter = 0;
    50 
    51 /**
    52  * Context for shared random number generator
    53  */
    54 static SDLTest_RandomContext rndContext;
    55 
    56 /*
    57  * Note: doxygen documentation markup for functions is in the header file.
    58  */
    59 
    60 void
    61 SDLTest_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 
    70 int
    71 SDLTest_GetFuzzerInvocationCount()
    72 {
    73 	return fuzzerInvocationCounter;
    74 }
    75 
    76 Uint8
    77 SDLTest_RandomUint8()
    78 {
    79 	fuzzerInvocationCounter++;
    80 
    81 	return (Uint8) SDLTest_RandomInt(&rndContext) & 0x000000FF;
    82 }
    83 
    84 Sint8
    85 SDLTest_RandomSint8()
    86 {
    87 	fuzzerInvocationCounter++;
    88 
    89 	return (Sint8) SDLTest_RandomInt(&rndContext) & 0x000000FF;
    90 }
    91 
    92 Uint16
    93 SDLTest_RandomUint16()
    94 {
    95 	fuzzerInvocationCounter++;
    96 
    97 	return (Uint16) SDLTest_RandomInt(&rndContext) & 0x0000FFFF;
    98 }
    99 
   100 Sint16
   101 SDLTest_RandomSint16()
   102 {
   103 	fuzzerInvocationCounter++;
   104 
   105 	return (Sint16) SDLTest_RandomInt(&rndContext) & 0x0000FFFF;
   106 }
   107 
   108 Sint32
   109 SDLTest_RandomSint32()
   110 {
   111 	fuzzerInvocationCounter++;
   112 
   113 	return (Sint32) SDLTest_RandomInt(&rndContext);
   114 }
   115 
   116 Uint32
   117 SDLTest_RandomUint32()
   118 {
   119 	fuzzerInvocationCounter++;
   120 
   121 	return (Uint32) SDLTest_RandomInt(&rndContext);
   122 }
   123 
   124 Uint64
   125 SDLTest_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 
   138 Sint64
   139 SDLTest_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 
   154 Sint32
   155 SDLTest_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  */
   199 Uint64
   200 SDLTest_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_Error(SDL_UNSUPPORTED);
   255 		return 0;
   256 	}
   257 
   258 	return tempBuf[SDLTest_RandomUint8() % index];
   259 }
   260 
   261 
   262 Uint8
   263 SDLTest_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 
   272 Uint16
   273 SDLTest_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 
   282 Uint32
   283 SDLTest_RandomUint32BoundaryValue(Uint32 boundary1, Uint32 boundary2, SDL_bool validDomain)
   284 {
   285 	/* max value for Uint32 */
   286 	const Uint64 maxValue = ULONG_MAX;
   287 	return (Uint32)SDLTest_GenerateUnsignedBoundaryValues(maxValue,
   288 				(Uint64) boundary1, (Uint64) boundary2,
   289 				validDomain);
   290 }
   291 
   292 Uint64
   293 SDLTest_RandomUint64BoundaryValue(Uint64 boundary1, Uint64 boundary2, SDL_bool validDomain)
   294 {
   295 	/* max value for Uint64 */
   296 	const Uint64 maxValue = ULLONG_MAX;
   297 	return SDLTest_GenerateUnsignedBoundaryValues(maxValue,
   298 				(Uint64) boundary1, (Uint64) boundary2,
   299 				validDomain);
   300 }
   301 
   302 /*!
   303  * Generates a signed boundary value between the given boundaries.
   304  * Boundary values are inclusive. See the examples below.
   305  * If boundary2 < boundary1, the values are swapped.
   306  * If boundary1 == boundary2, value of boundary1 will be returned
   307  *
   308  * Generating boundary values for Sint8:
   309  * SignedBoundaryValues(SCHAR_MIN, SCHAR_MAX, -10, 20, True) -> [-10,-9,19,20]
   310  * SignedBoundaryValues(SCHAR_MIN, SCHAR_MAX, -10, 20, False) -> [-11,21]
   311  * SignedBoundaryValues(SCHAR_MIN, SCHAR_MAX, -30, -15, True) -> [-30, -29, -16, -15]
   312  * SignedBoundaryValues(SCHAR_MIN, SCHAR_MAX, -127, 15, False) -> [16]
   313  * SignedBoundaryValues(SCHAR_MIN, SCHAR_MAX, -127, 127, False) -> [0], error set
   314  *
   315  * Generator works the same for other types of signed integers.
   316  *
   317  * \param minValue The smallest value that is acceptable for this data type.
   318  * 					For instance, for Uint8 -> -127, etc.
   319  * \param maxValue The biggest value that is acceptable for this data type.
   320  * 					For instance, for Uint8 -> 127, etc.
   321  * \param boundary1 defines lower boundary
   322  * \param boundary2 defines upper boundary
   323  * \param validDomain Generate only for valid domain (for the data type)
   324  *
   325  * \returns Returns a random boundary value for the domain or 0 in case of error
   326  */
   327 Sint64
   328 SDLTest_GenerateSignedBoundaryValues(const Sint64 minValue, const Sint64 maxValue, Sint64 boundary1, Sint64 boundary2, SDL_bool validDomain)
   329 {
   330         Sint64 b1, b2;
   331 	Sint64 delta;
   332 	Sint64 tempBuf[4];
   333 	Uint8 index;
   334 	
   335         /* Maybe swap */
   336 	if (boundary1 > boundary2) {
   337 		b1 = boundary2;
   338 		b2 = boundary1;
   339 	} else {
   340 		b1 = boundary1;
   341 		b2 = boundary2;
   342         }
   343 
   344 	index = 0;
   345 	if (validDomain == SDL_TRUE) {
   346 	        if (b1 == b2) {
   347 	            return b1;
   348 	        }
   349 	        
   350 	        /* Generate up to 4 values within bounds */
   351 	        delta = b2 - b1;
   352 	        if (delta < 4) {
   353 	            do {
   354 		        tempBuf[index] = b1 + index;
   355 		        index++;
   356                     } while (index < delta);
   357 	        } else {
   358 		  tempBuf[index] = b1;
   359 		  index++;
   360 		  tempBuf[index] = b1 + 1;
   361 		  index++;
   362 		  tempBuf[index] = b2 - 1;
   363 		  index++;
   364 		  tempBuf[index] = b2;
   365 		  index++;
   366 	        }
   367         } else {                
   368 	        /* Generate up to 2 values outside of bounds */
   369 		if (b1 > minValue) {
   370 			tempBuf[index] = b1 - 1;
   371 			index++;
   372 		}
   373 
   374 		if (b2 < maxValue) {
   375 			tempBuf[index] = b2 + 1;
   376 			index++;
   377 		}
   378 	}
   379 
   380 	if (index == 0) {
   381 		/* There are no valid boundaries */
   382 		SDL_Error(SDL_UNSUPPORTED);
   383 		return minValue;
   384 	}
   385 
   386 	return tempBuf[SDLTest_RandomUint8() % index];
   387 }
   388 
   389 
   390 Sint8
   391 SDLTest_RandomSint8BoundaryValue(Sint8 boundary1, Sint8 boundary2, SDL_bool validDomain)
   392 {
   393 	/* min & max values for Sint8 */
   394 	const Sint64 maxValue = SCHAR_MAX;
   395 	const Sint64 minValue = SCHAR_MIN;
   396 	return (Sint8)SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
   397 				(Sint64) boundary1, (Sint64) boundary2,
   398 				validDomain);
   399 }
   400 
   401 Sint16
   402 SDLTest_RandomSint16BoundaryValue(Sint16 boundary1, Sint16 boundary2, SDL_bool validDomain)
   403 {
   404 	/* min & max values for Sint16 */
   405 	const Sint64 maxValue = SHRT_MAX;
   406 	const Sint64 minValue = SHRT_MIN;
   407 	return (Sint16)SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
   408 				(Sint64) boundary1, (Sint64) boundary2,
   409 				validDomain);
   410 }
   411 
   412 Sint32
   413 SDLTest_RandomSint32BoundaryValue(Sint32 boundary1, Sint32 boundary2, SDL_bool validDomain)
   414 {
   415 	/* min & max values for Sint32 */
   416 	const Sint64 maxValue = LONG_MAX;
   417 	const Sint64 minValue = LONG_MIN;
   418 	return (Sint32)SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
   419 				(Sint64) boundary1, (Sint64) boundary2,
   420 				validDomain);
   421 }
   422 
   423 Sint64
   424 SDLTest_RandomSint64BoundaryValue(Sint64 boundary1, Sint64 boundary2, SDL_bool validDomain)
   425 {
   426 	/* min & max values for Sint64 */
   427 	const Sint64 maxValue = LLONG_MAX;
   428 	const Sint64 minValue = LLONG_MIN;
   429 	return SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
   430 				boundary1, boundary2,
   431 				validDomain);
   432 }
   433 
   434 float
   435 SDLTest_RandomUnitFloat()
   436 {
   437 	return (float) SDLTest_RandomUint32() / UINT_MAX;
   438 }
   439 
   440 float
   441 SDLTest_RandomFloat()
   442 {
   443         return (float) (SDLTest_RandomUnitDouble() * (double)2.0 * (double)FLT_MAX - (double)(FLT_MAX));
   444 }
   445 
   446 double
   447 SDLTest_RandomUnitDouble()
   448 {
   449 	return (double) (SDLTest_RandomUint64() >> 11) * (1.0/9007199254740992.0);
   450 }
   451 
   452 double
   453 SDLTest_RandomDouble()
   454 {
   455 	double r = 0.0;
   456 	double s = 1.0;
   457 	do {
   458 	  s /= UINT_MAX + 1.0;
   459 	  r += (double)SDLTest_RandomInt(&rndContext) * s;
   460 	} while (s > DBL_EPSILON);
   461 	  
   462 	fuzzerInvocationCounter++;
   463 	
   464 	return r;
   465 }
   466 
   467 
   468 char *
   469 SDLTest_RandomAsciiString()
   470 {
   471 	return SDLTest_RandomAsciiStringWithMaximumLength(255);
   472 }
   473 
   474 char *
   475 SDLTest_RandomAsciiStringWithMaximumLength(int maxLength)
   476 {
   477 	int size;
   478 
   479 	if(maxLength < 1) {
   480                 SDL_InvalidParamError("maxLength");
   481 		return NULL;
   482 	}
   483 
   484 	size = (SDLTest_RandomUint32() % (maxLength + 1));
   485 	
   486 	return SDLTest_RandomAsciiStringOfSize(size);	
   487 }
   488 
   489 char *
   490 SDLTest_RandomAsciiStringOfSize(int size)
   491 {
   492 	char *string;
   493 	int counter;
   494 
   495 
   496 	if(size < 1) {
   497                 SDL_InvalidParamError("size");
   498 		return NULL;
   499 	}
   500 
   501 	string = (char *)SDL_malloc((size + 1) * sizeof(char));
   502 	if (string==NULL) {
   503 	  return NULL;
   504         }
   505 
   506 	for(counter = 0; counter < size; ++counter) {
   507 		string[counter] = (char)SDLTest_RandomIntegerInRange(32, 126);
   508 	}
   509 
   510 	string[counter] = '\0';
   511 
   512 	fuzzerInvocationCounter++;
   513 
   514 	return string;
   515 }