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