src/test/SDL_test_fuzzer.c
author Andreas Schiffler <aschiffler@ferzkopp.net>
Sun, 12 May 2013 15:00:00 -0700
changeset 7172 b3569dff1c6e
parent 7037 3fedf1f25b94
child 7191 75360622e65f
permissions -rw-r--r--
Fix fuzzer/fuzzer tests on 64bit Linux; remove invalid negative SDL_Scancode test; disable failing surface/render test cases
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2013 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_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 	#if ((ULONG_MAX) == (UINT_MAX))
   287 	  const Uint64 maxValue = ULONG_MAX;
   288         #else
   289 	  const Uint64 maxValue = UINT_MAX;
   290         #endif
   291 	return (Uint32)SDLTest_GenerateUnsignedBoundaryValues(maxValue,
   292 				(Uint64) boundary1, (Uint64) boundary2,
   293 				validDomain);
   294 }
   295 
   296 Uint64
   297 SDLTest_RandomUint64BoundaryValue(Uint64 boundary1, Uint64 boundary2, SDL_bool validDomain)
   298 {
   299 	/* max value for Uint64 */
   300 	const Uint64 maxValue = ULLONG_MAX;
   301 	return SDLTest_GenerateUnsignedBoundaryValues(maxValue,
   302 				(Uint64) boundary1, (Uint64) boundary2,
   303 				validDomain);
   304 }
   305 
   306 /*!
   307  * Generates a signed boundary value between the given boundaries.
   308  * Boundary values are inclusive. See the examples below.
   309  * If boundary2 < boundary1, the values are swapped.
   310  * If boundary1 == boundary2, value of boundary1 will be returned
   311  *
   312  * Generating boundary values for Sint8:
   313  * SignedBoundaryValues(SCHAR_MIN, SCHAR_MAX, -10, 20, True) -> [-10,-9,19,20]
   314  * SignedBoundaryValues(SCHAR_MIN, SCHAR_MAX, -10, 20, False) -> [-11,21]
   315  * SignedBoundaryValues(SCHAR_MIN, SCHAR_MAX, -30, -15, True) -> [-30, -29, -16, -15]
   316  * SignedBoundaryValues(SCHAR_MIN, SCHAR_MAX, -127, 15, False) -> [16]
   317  * SignedBoundaryValues(SCHAR_MIN, SCHAR_MAX, -127, 127, False) -> [0], error set
   318  *
   319  * Generator works the same for other types of signed integers.
   320  *
   321  * \param minValue The smallest value that is acceptable for this data type.
   322  * 					For instance, for Uint8 -> -127, etc.
   323  * \param maxValue The biggest value that is acceptable for this data type.
   324  * 					For instance, for Uint8 -> 127, etc.
   325  * \param boundary1 defines lower boundary
   326  * \param boundary2 defines upper boundary
   327  * \param validDomain Generate only for valid domain (for the data type)
   328  *
   329  * \returns Returns a random boundary value for the domain or 0 in case of error
   330  */
   331 Sint64
   332 SDLTest_GenerateSignedBoundaryValues(const Sint64 minValue, const Sint64 maxValue, Sint64 boundary1, Sint64 boundary2, SDL_bool validDomain)
   333 {
   334         Sint64 b1, b2;
   335 	Sint64 delta;
   336 	Sint64 tempBuf[4];
   337 	Uint8 index;
   338 	
   339         /* Maybe swap */
   340 	if (boundary1 > boundary2) {
   341 		b1 = boundary2;
   342 		b2 = boundary1;
   343 	} else {
   344 		b1 = boundary1;
   345 		b2 = boundary2;
   346         }
   347 
   348 	index = 0;
   349 	if (validDomain == SDL_TRUE) {
   350 	        if (b1 == b2) {
   351 	            return b1;
   352 	        }
   353 	        
   354 	        /* Generate up to 4 values within bounds */
   355 	        delta = b2 - b1;
   356 	        if (delta < 4) {
   357 	            do {
   358 		        tempBuf[index] = b1 + index;
   359 		        index++;
   360                     } while (index < delta);
   361 	        } else {
   362 		  tempBuf[index] = b1;
   363 		  index++;
   364 		  tempBuf[index] = b1 + 1;
   365 		  index++;
   366 		  tempBuf[index] = b2 - 1;
   367 		  index++;
   368 		  tempBuf[index] = b2;
   369 		  index++;
   370 	        }
   371         } else {                
   372 	        /* Generate up to 2 values outside of bounds */
   373 		if (b1 > minValue) {
   374 			tempBuf[index] = b1 - 1;
   375 			index++;
   376 		}
   377 
   378 		if (b2 < maxValue) {
   379 			tempBuf[index] = b2 + 1;
   380 			index++;
   381 		}
   382 	}
   383 
   384 	if (index == 0) {
   385 		/* There are no valid boundaries */
   386 		SDL_Unsupported();
   387 		return minValue;
   388 	}
   389 
   390 	return tempBuf[SDLTest_RandomUint8() % index];
   391 }
   392 
   393 
   394 Sint8
   395 SDLTest_RandomSint8BoundaryValue(Sint8 boundary1, Sint8 boundary2, SDL_bool validDomain)
   396 {
   397 	/* min & max values for Sint8 */
   398 	const Sint64 maxValue = SCHAR_MAX;
   399 	const Sint64 minValue = SCHAR_MIN;
   400 	return (Sint8)SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
   401 				(Sint64) boundary1, (Sint64) boundary2,
   402 				validDomain);
   403 }
   404 
   405 Sint16
   406 SDLTest_RandomSint16BoundaryValue(Sint16 boundary1, Sint16 boundary2, SDL_bool validDomain)
   407 {
   408 	/* min & max values for Sint16 */
   409 	const Sint64 maxValue = SHRT_MAX;
   410 	const Sint64 minValue = SHRT_MIN;
   411 	return (Sint16)SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
   412 				(Sint64) boundary1, (Sint64) boundary2,
   413 				validDomain);
   414 }
   415 
   416 Sint32
   417 SDLTest_RandomSint32BoundaryValue(Sint32 boundary1, Sint32 boundary2, SDL_bool validDomain)
   418 {
   419 	/* min & max values for Sint32 */
   420 	#if ((ULONG_MAX) == (UINT_MAX))
   421   	  const Sint64 maxValue = LONG_MAX;
   422 	  const Sint64 minValue = LONG_MIN;
   423         #else
   424   	  const Sint64 maxValue = INT_MAX;
   425 	  const Sint64 minValue = INT_MIN;
   426         #endif
   427 	return (Sint32)SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
   428 				(Sint64) boundary1, (Sint64) boundary2,
   429 				validDomain);
   430 }
   431 
   432 Sint64
   433 SDLTest_RandomSint64BoundaryValue(Sint64 boundary1, Sint64 boundary2, SDL_bool validDomain)
   434 {
   435 	/* min & max values for Sint64 */
   436 	const Sint64 maxValue = LLONG_MAX;
   437 	const Sint64 minValue = LLONG_MIN;
   438 	return SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
   439 				boundary1, boundary2,
   440 				validDomain);
   441 }
   442 
   443 float
   444 SDLTest_RandomUnitFloat()
   445 {
   446 	return (float) SDLTest_RandomUint32() / UINT_MAX;
   447 }
   448 
   449 float
   450 SDLTest_RandomFloat()
   451 {
   452         return (float) (SDLTest_RandomUnitDouble() * (double)2.0 * (double)FLT_MAX - (double)(FLT_MAX));
   453 }
   454 
   455 double
   456 SDLTest_RandomUnitDouble()
   457 {
   458 	return (double) (SDLTest_RandomUint64() >> 11) * (1.0/9007199254740992.0);
   459 }
   460 
   461 double
   462 SDLTest_RandomDouble()
   463 {
   464 	double r = 0.0;
   465 	double s = 1.0;
   466 	do {
   467 	  s /= UINT_MAX + 1.0;
   468 	  r += (double)SDLTest_RandomInt(&rndContext) * s;
   469 	} while (s > DBL_EPSILON);
   470 	  
   471 	fuzzerInvocationCounter++;
   472 	
   473 	return r;
   474 }
   475 
   476 
   477 char *
   478 SDLTest_RandomAsciiString()
   479 {
   480 	return SDLTest_RandomAsciiStringWithMaximumLength(255);
   481 }
   482 
   483 char *
   484 SDLTest_RandomAsciiStringWithMaximumLength(int maxLength)
   485 {
   486 	int size;
   487 
   488 	if(maxLength < 1) {
   489                 SDL_InvalidParamError("maxLength");
   490 		return NULL;
   491 	}
   492 
   493 	size = (SDLTest_RandomUint32() % (maxLength + 1));
   494 	
   495 	return SDLTest_RandomAsciiStringOfSize(size);	
   496 }
   497 
   498 char *
   499 SDLTest_RandomAsciiStringOfSize(int size)
   500 {
   501 	char *string;
   502 	int counter;
   503 
   504 
   505 	if(size < 1) {
   506                 SDL_InvalidParamError("size");
   507 		return NULL;
   508 	}
   509 
   510 	string = (char *)SDL_malloc((size + 1) * sizeof(char));
   511 	if (string==NULL) {
   512 	  return NULL;
   513         }
   514 
   515 	for(counter = 0; counter < size; ++counter) {
   516 		string[counter] = (char)SDLTest_RandomIntegerInRange(32, 126);
   517 	}
   518 
   519 	string[counter] = '\0';
   520 
   521 	fuzzerInvocationCounter++;
   522 
   523 	return string;
   524 }