src/test/SDL_test_fuzzer.c
author Andreas Schiffler <aschiffler@ferzkopp.net>
Sun, 16 Dec 2012 21:59:29 -0800
changeset 6760 04dcce3081e6
parent 6757 9935f71c8c81
child 6763 9cbd31a3450b
permissions -rw-r--r--
Port clipboard and rwops test suites from GSOC code; minor updates to harness and fuzzer in test lib
     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 #include <stdint.h>
    31 #include <stdio.h>
    32 #include <stdlib.h>
    33 #include <limits.h>
    34 #include <float.h>
    35 
    36 #include "SDL_test.h"
    37 
    38 /** 
    39  *Counter for fuzzer invocations
    40  */
    41 static int fuzzerInvocationCounter = 0;
    42 
    43 /**
    44  * Context for shared random number generator
    45  */
    46 static SDLTest_RandomContext rndContext;
    47 
    48 /*
    49  * Note: doxygen documentation markup for functions is in the header file.
    50  */
    51 
    52 void
    53 SDLTest_FuzzerInit(Uint64 execKey)
    54 {
    55 	Uint32 a = (execKey >> 32) & 0x00000000FFFFFFFF;
    56 	Uint32 b = execKey & 0x00000000FFFFFFFF;
    57 	SDL_memset((void *)&rndContext, 0, sizeof(SDLTest_RandomContext));
    58 	SDLTest_RandomInit(&rndContext, a, b);
    59 	fuzzerInvocationCounter = 0;
    60 }
    61 
    62 int
    63 SDLTest_GetFuzzerInvocationCount()
    64 {
    65 	return fuzzerInvocationCounter;
    66 }
    67 
    68 Uint8
    69 SDLTest_RandomUint8()
    70 {
    71 	fuzzerInvocationCounter++;
    72 
    73 	return (Uint8) SDLTest_RandomInt(&rndContext) & 0x000000FF;
    74 }
    75 
    76 Sint8
    77 SDLTest_RandomSint8()
    78 {
    79 	fuzzerInvocationCounter++;
    80 
    81 	return (Sint8) SDLTest_RandomInt(&rndContext) & 0x000000FF;
    82 }
    83 
    84 Uint16
    85 SDLTest_RandomUint16()
    86 {
    87 	fuzzerInvocationCounter++;
    88 
    89 	return (Uint16) SDLTest_RandomInt(&rndContext) & 0x0000FFFF;
    90 }
    91 
    92 Sint16
    93 SDLTest_RandomSint16()
    94 {
    95 	fuzzerInvocationCounter++;
    96 
    97 	return (Sint16) SDLTest_RandomInt(&rndContext) & 0x0000FFFF;
    98 }
    99 
   100 Sint32
   101 SDLTest_RandomSint32()
   102 {
   103 	fuzzerInvocationCounter++;
   104 
   105 	return (Sint32) SDLTest_RandomInt(&rndContext);
   106 }
   107 
   108 Uint32
   109 SDLTest_RandomUint32()
   110 {
   111 	fuzzerInvocationCounter++;
   112 
   113 	return (Uint32) SDLTest_RandomInt(&rndContext);
   114 }
   115 
   116 Uint64
   117 SDLTest_RandomUint64()
   118 {
   119 	Uint64 value;
   120 	Uint32 *vp = (void*)&value;
   121 
   122 	fuzzerInvocationCounter++;
   123 
   124 	vp[0] = SDLTest_RandomSint32();
   125 	vp[1] = SDLTest_RandomSint32();
   126 
   127 	return value;
   128 }
   129 
   130 Sint64
   131 SDLTest_RandomSint64()
   132 {
   133 	Uint64 value;
   134 	Uint32 *vp = (void*)&value;
   135 
   136 	fuzzerInvocationCounter++;
   137 
   138 	vp[0] = SDLTest_RandomSint32();
   139 	vp[1] = SDLTest_RandomSint32();
   140 
   141 	return value;
   142 }
   143 
   144 
   145 
   146 Sint32
   147 SDLTest_RandomIntegerInRange(Sint32 pMin, Sint32 pMax)
   148 {
   149 	Sint64 min = pMin;
   150 	Sint64 max = pMax;
   151 	Sint64 temp;
   152 	Sint64 number;
   153 
   154 	if(pMin > pMax) {
   155 		temp = min;
   156 		min = max;
   157 		max = temp;
   158 	} else if(pMin == pMax) {
   159 		return (Sint32)min;
   160 	}
   161 
   162 	number = SDLTest_RandomUint32(); // invocation count increment in there
   163 
   164 	return (Sint32)((number % ((max + 1) - min)) + min);
   165 }
   166 
   167 /*!
   168  * Generates boundary values between the given boundaries.
   169  * Boundary values are inclusive. See the examples below.
   170  * If boundary2 < boundary1, the values are swapped.
   171  * If boundary1 == boundary2, value of boundary1 will be returned
   172  *
   173  * Generating boundary values for Uint8:
   174  * BoundaryValues(sizeof(Uint8), 10, 20, True) -> [10,11,19,20]
   175  * BoundaryValues(sizeof(Uint8), 10, 20, False) -> [9,21]
   176  * BoundaryValues(sizeof(Uint8), 0, 15, True) -> [0, 1, 14, 15]
   177  * BoundaryValues(sizeof(Uint8), 0, 15, False) -> [16]
   178  * BoundaryValues(sizeof(Uint8), 0, 255, False) -> NULL
   179  *
   180  * Generator works the same for other types of unsigned integers.
   181  *
   182  * Note: outBuffer will be allocated and needs to be freed later.
   183  * If outbuffer != NULL, it'll be freed.
   184  *
   185  * \param maxValue The biggest value that is acceptable for this data type.
   186  * 					For instance, for Uint8 -> 255, Uint16 -> 65536 etc.
   187  * \param pBoundary1 defines lower boundary
   188  * \param pBoundary2 defines upper boundary
   189  * \param validDomain Generate only for valid domain (for the data type)
   190  *
   191  * \param outBuffer The generated boundary values are put here
   192  *
   193  * \returns Returns the number of elements in outBuffer or -1 in case of error
   194  */
   195 Uint32
   196 SDLTest_GenerateUnsignedBoundaryValues(const Uint64 maxValue,
   197 					Uint64 pBoundary1, Uint64 pBoundary2, SDL_bool validDomain,
   198 					Uint64 *outBuffer)
   199 {
   200 	Uint64 boundary1 = pBoundary1, boundary2 = pBoundary2;
   201 	Uint64 temp;
   202 	Uint64 tempBuf[4];
   203 	int index;
   204 
   205 	if(outBuffer != NULL) {
   206 		SDL_free(outBuffer);
   207 	}
   208 
   209 	if(boundary1 > boundary2) {
   210 		temp = boundary1;
   211 		boundary1 = boundary2;
   212 		boundary2 = temp;
   213 	}
   214 
   215 	index = 0;
   216 	if(boundary1 == boundary2) {
   217 		tempBuf[index++] = boundary1;
   218 	}
   219 	else if(validDomain) {
   220 		tempBuf[index++] = boundary1;
   221 
   222 		if(boundary1 < UINT64_MAX)
   223 			tempBuf[index++] = boundary1 + 1;
   224 
   225 		tempBuf[index++] = boundary2 - 1;
   226 		tempBuf[index++] = boundary2;
   227 	}
   228 	else {
   229 		if(boundary1 > 0) {
   230 			tempBuf[index++] = boundary1 - 1;
   231 		}
   232 
   233 		if(boundary2 < maxValue && boundary2 < UINT64_MAX) {
   234 			tempBuf[index++] = boundary2 + 1;
   235 		}
   236 	}
   237 
   238 	if(index == 0) {
   239 		// There are no valid boundaries
   240 		return 0;
   241 	}
   242 
   243 	// Create the return buffer
   244 	outBuffer = (Uint64 *)SDL_malloc(index * sizeof(Uint64));
   245 	if(outBuffer == NULL) {
   246 		return 0;
   247 	}
   248 
   249 	SDL_memcpy(outBuffer, tempBuf, index * sizeof(Uint64));
   250 
   251 	return index;
   252 }
   253 
   254 Uint8
   255 SDLTest_RandomUint8BoundaryValue(Uint8 boundary1, Uint8 boundary2, SDL_bool validDomain)
   256 {
   257 	Uint64 *buffer = NULL;
   258 	Uint32 size;
   259 	Uint32 index;
   260 	Uint8 retVal;
   261 
   262 	// max value for Uint8
   263 	const Uint64 maxValue = UINT8_MAX;
   264 
   265 	size = SDLTest_GenerateUnsignedBoundaryValues(maxValue,
   266 				(Uint64) boundary1, (Uint64) boundary2,
   267 				validDomain, buffer);
   268 	if (buffer == NULL || size == 0) {
   269 		return 0;
   270 	}
   271 
   272 	index = SDLTest_RandomSint32() % size;
   273 	retVal = (Uint8)buffer[index];
   274 
   275 	SDL_free(buffer);
   276 
   277 	fuzzerInvocationCounter++;
   278 
   279 	return retVal;
   280 }
   281 
   282 Uint16
   283 SDLTest_RandomUint16BoundaryValue(Uint16 boundary1, Uint16 boundary2, SDL_bool validDomain)
   284 {
   285 	Uint64 *buffer = NULL;
   286 	Uint32 size;
   287 	Uint32 index;
   288 	Uint16 retVal;
   289 
   290 	// max value for Uint16
   291 	const Uint64 maxValue = UINT16_MAX;
   292 
   293 	size = SDLTest_GenerateUnsignedBoundaryValues(maxValue,
   294 				(Uint64) boundary1, (Uint64) boundary2,
   295 				validDomain, buffer);
   296 	if (buffer == NULL || size == 0) {
   297 		return 0;
   298 	}
   299 
   300 	index = SDLTest_RandomSint32() % size;
   301 	retVal = (Uint16) buffer[index];
   302 
   303 	SDL_free(buffer);
   304 
   305 	fuzzerInvocationCounter++;
   306 
   307 	return retVal;
   308 }
   309 
   310 Uint32
   311 SDLTest_RandomUint32BoundaryValue(Uint32 boundary1, Uint32 boundary2, SDL_bool validDomain)
   312 {
   313 	Uint64 *buffer = NULL;
   314 	Uint32 size;
   315 	Uint32 index;
   316 	Uint32 retVal;
   317 
   318 	// max value for Uint32
   319 	const Uint64 maxValue = UINT32_MAX;
   320 
   321 	size = SDLTest_GenerateUnsignedBoundaryValues(maxValue,
   322 				(Uint64) boundary1, (Uint64) boundary2,
   323 				validDomain, buffer);
   324 	if (buffer == NULL || size == 0) {
   325 		return 0;
   326 	}
   327 
   328 	index = SDLTest_RandomSint32() % size;
   329 	retVal = (Uint32) buffer[index];
   330 
   331 	SDL_free(buffer);
   332 
   333 	fuzzerInvocationCounter++;
   334 
   335 	return retVal;
   336 }
   337 
   338 Uint64
   339 SDLTest_RandomUint64BoundaryValue(Uint64 boundary1, Uint64 boundary2, SDL_bool validDomain)
   340 {
   341 	Uint64 *buffer = NULL;
   342 	Uint32 size;
   343 	Uint32 index;
   344 	Uint64 retVal;
   345 
   346 	// max value for Uint64
   347 	const Uint64 maxValue = UINT64_MAX;
   348 
   349 	size = SDLTest_GenerateUnsignedBoundaryValues(maxValue,
   350 				(Uint64) boundary1, (Uint64) boundary2,
   351 				validDomain, buffer);
   352 	if (buffer == NULL || size == 0) {
   353 		return 0;
   354 	}
   355 
   356 	index = SDLTest_RandomSint32() % size;
   357 	retVal = (Uint64) buffer[index];
   358 
   359 	SDL_free(buffer);
   360 
   361 	fuzzerInvocationCounter++;
   362 
   363 	return retVal;
   364 }
   365 
   366 /*!
   367  * Generates boundary values between the given boundaries.
   368  * Boundary values are inclusive. See the examples below.
   369  * If boundary2 < boundary1, the values are swapped.
   370  * If boundary1 == boundary2, value of boundary1 will be returned
   371  *
   372  * Generating boundary values for Sint8:
   373  * SignedBoundaryValues(sizeof(Sint8), -10, 20, True) -> [-11,-10,19,20]
   374  * SignedBoundaryValues(sizeof(Sint8), -10, 20, False) -> [-11,21]
   375  * SignedBoundaryValues(sizeof(Sint8), -30, -15, True) -> [-30, -29, -16, -15]
   376  * SignedBoundaryValues(sizeof(Sint8), -128, 15, False) -> [16]
   377  * SignedBoundaryValues(sizeof(Sint8), -128, 127, False) -> NULL
   378  *
   379  * Generator works the same for other types of signed integers.
   380  *
   381  * Note: outBuffer will be allocated and needs to be freed later.
   382  * If outbuffer != NULL, it'll be freed.
   383  *
   384  *
   385  * \param minValue The smallest value  that is acceptable for this data type.
   386  *					For instance, for Uint8 -> -128, Uint16 -> -32,768 etc.
   387  * \param maxValue The biggest value that is acceptable for this data type.
   388  * 					For instance, for Uint8 -> 127, Uint16 -> 32767 etc.
   389  * \param pBoundary1 defines lower boundary
   390  * \param pBoundary2 defines upper boundary
   391  * \param validDomain Generate only for valid domain (for the data type)
   392  *
   393  * \param outBuffer The generated boundary values are put here
   394  *
   395  * \returns Returns the number of elements in outBuffer or -1 in case of error
   396  */
   397 Uint32
   398 SDLTest_GenerateSignedBoundaryValues(const Sint64 minValue, const Sint64 maxValue,
   399 					Sint64 pBoundary1, Sint64 pBoundary2, SDL_bool validDomain,
   400 					Sint64 *outBuffer)
   401 {
   402 	int index;
   403 	Sint64 tempBuf[4];
   404 	Sint64 boundary1 = pBoundary1, boundary2 = pBoundary2;
   405 
   406 	if(outBuffer != NULL) {
   407 		SDL_free(outBuffer);
   408 	}
   409 
   410 	if(boundary1 > boundary2) {
   411 		Sint64 temp = boundary1;
   412 		boundary1 = boundary2;
   413 		boundary2 = temp;
   414 	}
   415 
   416 	index = 0;
   417 	if(boundary1 == boundary2) {
   418 		tempBuf[index++] = boundary1;
   419 	}
   420 	else if(validDomain) {
   421 		tempBuf[index++] = boundary1;
   422 
   423 		if(boundary1 < LLONG_MAX)
   424 			tempBuf[index++] = boundary1 + 1;
   425 
   426 		if(boundary2 > LLONG_MIN)
   427 			tempBuf[index++] = boundary2 - 1;
   428 
   429 		tempBuf[index++] = boundary2;
   430 	}
   431 	else {
   432 		if(boundary1 > minValue &&  boundary1 > LLONG_MIN) {
   433 			tempBuf[index++] = boundary1 - 1;
   434 		}
   435 
   436 		if(boundary2 < maxValue && boundary2 < UINT64_MAX) {
   437 			tempBuf[index++] = boundary2 + 1;
   438 		}
   439 	}
   440 
   441 	if(index == 0) {
   442 		// There are no valid boundaries
   443 		return 0;
   444 	}
   445 
   446 	// Create the return buffer
   447 	outBuffer = (Sint64 *)SDL_malloc(index * sizeof(Sint64));
   448 	if(outBuffer == NULL) {
   449 		return 0;
   450 	}
   451 
   452 	SDL_memcpy((void *)outBuffer, (void *)tempBuf, index * sizeof(Sint64));
   453 
   454 	return (Uint32)index;
   455 }
   456 
   457 Sint8
   458 SDLTest_RandomSint8BoundaryValue(Sint8 boundary1, Sint8 boundary2, SDL_bool validDomain)
   459 {
   460 	// min & max values for Sint8
   461 	const Sint64 maxValue = CHAR_MAX;
   462 	const Sint64 minValue = CHAR_MIN;
   463 
   464 	Sint64 *buffer = NULL;
   465 	Uint32 size;
   466 	Uint32 index;
   467 	Sint8 retVal;
   468 
   469 	size = SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
   470 				(Sint64) boundary1, (Sint64) boundary2,
   471 				validDomain, buffer);
   472 	if (buffer == NULL || size == 0) {
   473 		return CHAR_MIN;
   474 	}
   475 
   476 	index = SDLTest_RandomSint32() % size;
   477 	retVal = (Sint8) buffer[index];
   478 
   479 	SDL_free(buffer);
   480 
   481 	fuzzerInvocationCounter++;
   482 
   483 	return retVal;
   484 }
   485 
   486 Sint16
   487 SDLTest_RandomSint16BoundaryValue(Sint16 boundary1, Sint16 boundary2, SDL_bool validDomain)
   488 {
   489 	// min & max values for Sint16
   490 	const Sint64 maxValue = SHRT_MAX;
   491 	const Sint64 minValue = SHRT_MIN;
   492 	Sint64 *buffer = NULL;
   493 	Uint32 size;
   494 	Uint32 index;
   495 	Sint16 retVal;
   496 
   497 	size = SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
   498 					(Sint64) boundary1, (Sint64) boundary2,
   499 					validDomain, buffer);
   500 	if (buffer == NULL || size == 0) {
   501 		return SHRT_MIN;
   502 	}
   503 
   504 	index = SDLTest_RandomSint32() % size;
   505 	retVal = (Sint16) buffer[index];
   506 
   507 	SDL_free(buffer);
   508 
   509 	fuzzerInvocationCounter++;
   510 
   511 	return retVal;
   512 }
   513 
   514 Sint32
   515 SDLTest_RandomSint32BoundaryValue(Sint32 boundary1, Sint32 boundary2, SDL_bool validDomain)
   516 {
   517 	// min & max values for Sint32
   518 	const Sint64 maxValue = INT_MAX;
   519 	const Sint64 minValue = INT_MIN;
   520 
   521 	Sint64 *buffer = NULL;
   522 	Uint32 size;
   523 	Uint32 index;
   524 	Sint32 retVal;
   525 
   526 	size = SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
   527 				(Sint64) boundary1, (Sint64) boundary2,
   528 				validDomain, buffer);
   529 	if (buffer == NULL || size == 0) {
   530 		return INT_MIN;
   531 	}
   532 
   533 	index = SDLTest_RandomSint32() % size;
   534 	retVal = (Sint32) buffer[index];
   535 
   536 	SDL_free(buffer);
   537 
   538 	fuzzerInvocationCounter++;
   539 
   540 	return retVal;
   541 }
   542 
   543 Sint64
   544 SDLTest_RandomSint64BoundaryValue(Sint64 boundary1, Sint64 boundary2, SDL_bool validDomain)
   545 {
   546 	Sint64 *buffer = NULL;
   547 	Uint32 size;
   548 	Uint32 index;
   549 	Sint64 retVal;
   550 
   551 	// min & max values for Sint64
   552 	const Sint64 maxValue = LLONG_MAX;
   553 	const Sint64 minValue = LLONG_MIN;
   554 
   555 	size = SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
   556 				(Sint64) boundary1, (Sint64) boundary2,
   557 				validDomain, buffer);
   558 	if (buffer == NULL || size == 0) {
   559 		return LLONG_MIN;
   560 	}
   561 
   562 	index = SDLTest_RandomSint32() % size;
   563 	retVal = (Sint64) buffer[index];
   564 
   565 	SDL_free(buffer);
   566 
   567 	fuzzerInvocationCounter++;
   568 
   569 	return retVal;
   570 }
   571 
   572 float
   573 SDLTest_RandomUnitFloat()
   574 {
   575 	return (float) SDLTest_RandomUint32() / UINT_MAX;
   576 }
   577 
   578 float
   579 SDLTest_RandomFloat()
   580 {
   581         return (float) (FLT_MIN + SDLTest_RandomUnitDouble() * (FLT_MAX - FLT_MIN));
   582 }
   583 
   584 double
   585 SDLTest_RandomUnitDouble()
   586 {
   587 	return (double) (SDLTest_RandomUint64() >> 11) * (1.0/9007199254740992.0);
   588 }
   589 
   590 double
   591 SDLTest_RandomDouble()
   592 {
   593 	double r = 0.0;
   594 	double s = 1.0;
   595 	do {
   596 	  s /= UINT_MAX + 1.0;
   597 	  r += (double)SDLTest_RandomInt(&rndContext) * s;
   598 	} while (s > DBL_EPSILON);
   599 	  
   600 	fuzzerInvocationCounter++;
   601 	
   602 	return r;
   603 }
   604 
   605 
   606 char *
   607 SDLTest_RandomAsciiString()
   608 {
   609 	// note: fuzzerInvocationCounter is increment in the RandomAsciiStringWithMaximumLenght
   610 	return SDLTest_RandomAsciiStringWithMaximumLength(255);
   611 }
   612 
   613 char *
   614 SDLTest_RandomAsciiStringWithMaximumLength(int maxSize)
   615 {
   616 	int size;
   617 	char *string;
   618 	int counter;
   619 
   620 	fuzzerInvocationCounter++;
   621 
   622 	if(maxSize < 1) {
   623 		return NULL;
   624 	}
   625 
   626 	size = (SDLTest_RandomUint32() % (maxSize + 1)) + 1;
   627 	string = (char *)SDL_malloc(size * sizeof(char));
   628 	if (string==NULL) {
   629 	  return NULL;
   630         }
   631 
   632 	for(counter = 0; counter < size; ++counter) {
   633 		string[counter] = (char)SDLTest_RandomIntegerInRange(32, 126);
   634 	}
   635 
   636 	string[counter] = '\0';
   637 
   638 	return string;
   639 }