From a6a77a8ad9c5a4154f3726c5a225a0aec93501cc Mon Sep 17 00:00:00 2001 From: Andreas Schiffler Date: Tue, 27 Nov 2012 21:40:46 -0800 Subject: [PATCH] Add fuzzer to test lib --- include/SDL_test.h | 1 + include/SDL_test_fuzzer.h | 371 +++++++++++++++++++++ include/SDL_test_random.h | 6 +- src/test/SDL_test_fuzzer.c | 637 +++++++++++++++++++++++++++++++++++++ 4 files changed, 1011 insertions(+), 4 deletions(-) create mode 100644 include/SDL_test_fuzzer.h create mode 100644 src/test/SDL_test_fuzzer.c diff --git a/include/SDL_test.h b/include/SDL_test.h index 1d215a914..5b2827eba 100644 --- a/include/SDL_test.h +++ b/include/SDL_test.h @@ -33,6 +33,7 @@ #include "SDL.h" #include "SDL_test_font.h" #include "SDL_test_random.h" +#include "SDL_test_fuzzer.h" #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ diff --git a/include/SDL_test_fuzzer.h b/include/SDL_test_fuzzer.h new file mode 100644 index 000000000..8cd05f098 --- /dev/null +++ b/include/SDL_test_fuzzer.h @@ -0,0 +1,371 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/** + * \file SDL_test_fuzzer.h + * + * Include file for SDL test framework. + * + * This code is a part of the SDL2_test library, not the main SDL library. + */ + +/* + + Data generators for fuzzing test data in a reproducible way. + +*/ + +#ifndef _SDL_test_fuzzer_h +#define _SDL_test_fuzzer_h + +#include "begin_code.h" +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + + +/* + Based on GSOC code by Markus Kauppila +*/ + + +/** + * \file + * Note: The fuzzer implementation uses a static instance of random context + * internally which makes it thread-UNsafe. + */ + +/** + * Initializes the fuzzer for a test + * + * /param execKey Execution "Key" that initializes the random number generator uniquely for the test. + * + */ +void SDLTest_FuzzerInit(Uint64 execKey); + + +/** + * Returns a random Uint8 + * + * \returns Generated integer + */ +Uint8 SDLTest_RandomUint8(); + +/** + * Returns a random Sint8 + * + * \returns Generated signed integer + */ +Sint8 SDLTest_RandomSint8(); + + +/** + * Returns a random Uint16 + * + * \returns Generated integer + */ +Uint16 SDLTest_RandomUint16(); + +/** + * Returns a random Sint16 + * + * \returns Generated signed integer + */ +Sint16 SDLTest_RandomSint16(); + + +/** + * Returns a random integer + * + * \returns Generated integer + */ +Sint32 SDLTest_RandomSint32(); + + +/** + * Returns a random positive integer + * + * \returns Generated integer + */ +Uint32 SDLTest_RandomUint32(); + +/** + * Returns random Uint64. + * + * \returns Generated integer + */ +Uint64 SDLTest_RandomUint64(); + + +/** + * Returns random Sint64. + * + * \returns Generated signed integer + */ +Sint64 SDLTest_RandomSint64(); + +/** + * \returns random float in range [0.0 - 1.0[ + */ +float SDLTest_RandomUnitFloat(); + +/** + * \returns random double in range [0.0 - 1.0[ + */ +double SDLTest_RandomUnitDouble(); + +/** + * \returns random float. + * + */ +float SDLTest_RandomFloat(); + +/** + * \returns random double. + * + */ +double SDLTest_RandomDouble(); + +/** + * Returns a random boundary value for Uint8 within the given boundaries. + * Boundaries are inclusive, see the usage examples below. If validDomain + * is true, the function will only return valid boundaries, otherwise non-valid + * boundaries are also possible. + * If boundary1 > boundary2, the values are swapped + * + * Usage examples: + * RandomUint8BoundaryValue(10, 20, SDL_TRUE) returns 10, 11, 19 or 20 + * RandomUint8BoundaryValue(1, 20, SDL_FALSE) returns 0 or 21 + * RandomUint8BoundaryValue(0, 99, SDL_FALSE) returns 100 + * RandomUint8BoundaryValue(0, 255, SDL_FALSE) returns -1 (== error value) + * + * \param boundary1 Lower boundary limit + * \param boundary2 Upper boundary limit + * \param validDomain Should the generated boundary be valid or not? + * + * \returns Boundary value in given range or error value (-1) + */ +Uint8 SDLTest_RandomUint8BoundaryValue(Uint8 boundary1, Uint8 boundary2, SDL_bool validDomain); + +/** + * Returns a random boundary value for Uint16 within the given boundaries. + * Boundaries are inclusive, see the usage examples below. If validDomain + * is true, the function will only return valid boundaries, otherwise non-valid + * boundaries are also possible. + * If boundary1 > boundary2, the values are swapped + * + * Usage examples: + * RandomUint16BoundaryValue(10, 20, SDL_TRUE) returns 10, 11, 19 or 20 + * RandomUint16BoundaryValue(1, 20, SDL_FALSE) returns 0 or 21 + * RandomUint16BoundaryValue(0, 99, SDL_FALSE) returns 100 + * RandomUint16BoundaryValue(0, 0xFFFF, SDL_FALSE) returns -1 (== error value) + * + * \param boundary1 Lower boundary limit + * \param boundary2 Upper boundary limit + * \param validDomain Should the generated boundary be valid or not? + * + * \returns Boundary value in given range or error value (-1) + */ +Uint16 SDLTest_RandomUint16BoundaryValue(Uint16 boundary1, Uint16 boundary2, SDL_bool validDomain); + +/** + * Returns a random boundary value for Uint32 within the given boundaries. + * Boundaries are inclusive, see the usage examples below. If validDomain + * is true, the function will only return valid boundaries, otherwise non-valid + * boundaries are also possible. + * If boundary1 > boundary2, the values are swapped + * + * Usage examples: + * RandomUint32BoundaryValue(10, 20, SDL_TRUE) returns 10, 11, 19 or 20 + * RandomUint32BoundaryValue(1, 20, SDL_FALSE) returns 0 or 21 + * RandomUint32BoundaryValue(0, 99, SDL_FALSE) returns 100 + * RandomUint32BoundaryValue(0, 0xFFFFFFFF, SDL_FALSE) returns -1 (== error value) + * + * \param boundary1 Lower boundary limit + * \param boundary2 Upper boundary limit + * \param validDomain Should the generated boundary be valid or not? + * + * \returns Boundary value in given range or error value (-1) + */ +Uint32 SDLTest_RandomUint32BoundaryValue(Uint32 boundary1, Uint32 boundary2, SDL_bool validDomain); + +/** + * Returns a random boundary value for Uint64 within the given boundaries. + * Boundaries are inclusive, see the usage examples below. If validDomain + * is true, the function will only return valid boundaries, otherwise non-valid + * boundaries are also possible. + * If boundary1 > boundary2, the values are swapped + * + * Usage examples: + * RandomUint64BoundaryValue(10, 20, SDL_TRUE) returns 10, 11, 19 or 20 + * RandomUint64BoundaryValue(1, 20, SDL_FALSE) returns 0 or 21 + * RandomUint64BoundaryValue(0, 99, SDL_FALSE) returns 100 + * RandomUint64BoundaryValue(0, 0xFFFFFFFFFFFFFFFF, SDL_FALSE) returns -1 (== error value) + * + * \param boundary1 Lower boundary limit + * \param boundary2 Upper boundary limit + * \param validDomain Should the generated boundary be valid or not? + * + * \returns Boundary value in given range or error value (-1) + */ +Uint64 SDLTest_RandomUint64BoundaryValue(Uint64 boundary1, Uint64 boundary2, SDL_bool validDomain); + +/** + * Returns a random boundary value for Sint8 within the given boundaries. + * Boundaries are inclusive, see the usage examples below. If validDomain + * is true, the function will only return valid boundaries, otherwise non-valid + * boundaries are also possible. + * If boundary1 > boundary2, the values are swapped + * + * Usage examples: + * RandomSint8BoundaryValue(-10, 20, SDL_TRUE) returns -11, -10, 19 or 20 + * RandomSint8BoundaryValue(-100, -10, SDL_FALSE) returns -101 or -9 + * RandomSint8BoundaryValue(-128, 99, SDL_FALSE) returns 100 + * RandomSint8BoundaryValue(-128, 127, SDL_FALSE) returns SINT8_MIN (== error value) + * + * \param boundary1 Lower boundary limit + * \param boundary2 Upper boundary limit + * \param validDomain Should the generated boundary be valid or not? + * + * \returns Boundary value in given range or error value (-1) + */ +Sint8 SDLTest_RandomSint8BoundaryValue(Sint8 boundary1, Sint8 boundary2, SDL_bool validDomain); + + +/** + * Returns a random boundary value for Sint16 within the given boundaries. + * Boundaries are inclusive, see the usage examples below. If validDomain + * is true, the function will only return valid boundaries, otherwise non-valid + * boundaries are also possible. + * If boundary1 > boundary2, the values are swapped + * + * Usage examples: + * RandomSint16BoundaryValue(-10, 20, SDL_TRUE) returns -11, -10, 19 or 20 + * RandomSint16BoundaryValue(-100, -10, SDL_FALSE) returns -101 or -9 + * RandomSint16BoundaryValue(SINT8_MIN, 99, SDL_FALSE) returns 100 + * RandomSint16BoundaryValue(SINT8_MIN, SINT8_MAX, SDL_FALSE) returns SINT16_MIN (== error value) + * + * \param boundary1 Lower boundary limit + * \param boundary2 Upper boundary limit + * \param validDomain Should the generated boundary be valid or not? + * + * \returns Boundary value in given range or error value (-1) + */ +Sint16 SDLTest_RandomSint16BoundaryValue(Sint16 boundary1, Sint16 boundary2, SDL_bool validDomain); + +/** + * Returns a random boundary value for Sint32 within the given boundaries. + * Boundaries are inclusive, see the usage examples below. If validDomain + * is true, the function will only return valid boundaries, otherwise non-valid + * boundaries are also possible. + * If boundary1 > boundary2, the values are swapped + * + * Usage examples: + * RandomSint32BoundaryValue(-10, 20, SDL_TRUE) returns -11, -10, 19 or 20 + * RandomSint32BoundaryValue(-100, -10, SDL_FALSE) returns -101 or -9 + * RandomSint32BoundaryValue(SINT32_MIN, 99, SDL_FALSE) returns 100 + * RandomSint32BoundaryValue(SINT32_MIN, SINT32_MAX, SDL_FALSE) returns SINT32_MIN (== error value) + * + * \param boundary1 Lower boundary limit + * \param boundary2 Upper boundary limit + * \param validDomain Should the generated boundary be valid or not? + * + * \returns Boundary value in given range or error value (-1) + */ +Sint32 SDLTest_RandomSint32BoundaryValue(Sint32 boundary1, Sint32 boundary2, SDL_bool validDomain); + +/** + * Returns a random boundary value for Sint64 within the given boundaries. + * Boundaries are inclusive, see the usage examples below. If validDomain + * is true, the function will only return valid boundaries, otherwise non-valid + * boundaries are also possible. + * If boundary1 > boundary2, the values are swapped + * + * Usage examples: + * RandomSint64BoundaryValue(-10, 20, SDL_TRUE) returns -11, -10, 19 or 20 + * RandomSint64BoundaryValue(-100, -10, SDL_FALSE) returns -101 or -9 + * RandomSint64BoundaryValue(SINT64_MIN, 99, SDL_FALSE) returns 100 + * RandomSint64BoundaryValue(SINT64_MIN, SINT32_MAX, SDL_FALSE) returns SINT64_MIN (== error value) + * + * \param boundary1 Lower boundary limit + * \param boundary2 Upper boundary limit + * \param validDomain Should the generated boundary be valid or not? + * + * \returns Boundary value in given range or error value (-1) + */ +Sint64 SDLTest_RandomSint64BoundaryValue(Sint64 boundary1, Sint64 boundary2, SDL_bool validDomain); + + +/** + * Returns integer in range [min, max] (inclusive). + * Min and max values can be negative values. + * If Max in smaller tham min, then the values are swapped. + * Min and max are the same value, that value will be returned. + * + * \returns Generated integer + */ +Sint32 SDLTest_RandomIntegerInRange(Sint32 min, Sint32 max); + + +/** + * Generates random null-terminated string. The maximum length for + * the string is 255 characters and it can contain ASCII characters + * from 1 to 127. + * + * Note: Returned string needs to be deallocated. + * + * \returns newly allocated random string + */ +char * SDLTest_RandomAsciiString(); + + +/** + * Generates random null-terminated string. The maximum length for + * the string is defined by maxLenght parameter. + * String can contain ASCII characters from 1 to 127. + * + * Note: Returned string needs to be deallocated. + * + * \param maxLength Maximum length of the generated string + * + * \returns newly allocated random string + */ +char * SDLTest_RandomAsciiStringWithMaximumLength(int maxLength); + +/** + * Returns the invocation count for the fuzzer since last ...FuzzerInit. + */ +int SDLTest_GetFuzzerInvocationCount(); + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif +#include "close_code.h" + +#endif /* _SDL_test_fuzzer_h */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/include/SDL_test_random.h b/include/SDL_test_random.h index b5666d5cb..ac44911ac 100644 --- a/include/SDL_test_random.h +++ b/include/SDL_test_random.h @@ -54,11 +54,9 @@ extern "C" { /* ------- Definitions ------- */ /* - * Macros that return random number in a specific format. - * Float values are in the range [0.0-1.0]. + * Macros that return a random number in a specific format. */ -#define SDL_TestRandomInt(c) ((int)SDL_TestRandom(c)) -#define SDL_TestRandomFloat(c) ((double)SDL_TestRandom(c)/(unsigned long)0xffffffff) +#define SDLTest_RandomInt(c) ((int)SDLTest_Random(c)) /* * Context structure for the random number generator state. diff --git a/src/test/SDL_test_fuzzer.c b/src/test/SDL_test_fuzzer.c new file mode 100644 index 000000000..c0c19f42d --- /dev/null +++ b/src/test/SDL_test_fuzzer.c @@ -0,0 +1,637 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* + + Data generators for fuzzing test data in a reproducible way. + +*/ + +#include "SDL_config.h" + +#include +#include +#include +#include +#include + +#include "SDL_test.h" + +/** + *Counter for fuzzer invocations + */ +static int fuzzerInvocationCounter; + +/** + * Context for shared random number generator + */ +static SDLTest_RandomContext rndContext; + +/* + * Note: doxygen documentation markup for functions is in the header file. + */ + +void +SDLTest_FuzzerInit(Uint64 execKey) +{ + Uint32 a = (execKey >> 32) & 0x00000000FFFFFFFF; + Uint32 b = execKey & 0x00000000FFFFFFFF; + SDLTest_RandomInit(&rndContext, a, b); +} + +int +SDLTest_GetInvocationCount() +{ + return fuzzerInvocationCounter; +} + +Uint8 +SDLTest_RandomUint8() +{ + fuzzerInvocationCounter++; + + return (Uint8) SDLTest_RandomInt(&rndContext) & 0x000000FF; +} + +Sint8 +SDLTest_RandomSint8() +{ + fuzzerInvocationCounter++; + + return (Sint8) SDLTest_RandomInt(&rndContext) & 0x000000FF; +} + +Uint16 +SDLTest_RandomUint16() +{ + fuzzerInvocationCounter++; + + return (Uint16) SDLTest_RandomInt(&rndContext) & 0x0000FFFF; +} + +Sint16 +SDLTest_RandomSint16() +{ + fuzzerInvocationCounter++; + + return (Sint16) SDLTest_RandomInt(&rndContext) & 0x0000FFFF; +} + +Sint32 +SDLTest_RandomSint32() +{ + fuzzerInvocationCounter++; + + return (Sint32) SDLTest_RandomInt(&rndContext); +} + +Uint32 +SDLTest_RandomUint32() +{ + fuzzerInvocationCounter++; + + return (Uint32) SDLTest_RandomInt(&rndContext); +} + +Uint64 +SDLTest_RandomUint64() +{ + Uint64 value; + Uint32 *vp = (void*)&value; + + fuzzerInvocationCounter++; + + vp[0] = SDLTest_RandomSint32(); + vp[1] = SDLTest_RandomSint32(); + + return value; +} + +Sint64 +SDLTest_RandomSint64() +{ + Uint64 value; + Uint32 *vp = (void*)&value; + + fuzzerInvocationCounter++; + + vp[0] = SDLTest_RandomSint32(); + vp[1] = SDLTest_RandomSint32(); + + return value; +} + + + +Sint32 +SDLTest_RandomIntegerInRange(Sint32 pMin, Sint32 pMax) +{ + Sint64 min = pMin; + Sint64 max = pMax; + Sint64 temp; + Sint64 number; + + if(pMin > pMax) { + temp = min; + min = max; + max = temp; + } else if(pMin == pMax) { + return (Sint32)min; + } + + number = SDLTest_RandomUint32(); // invocation count increment in there + + return (Sint32)((number % ((max + 1) - min)) + min); +} + +/*! + * Generates boundary values between the given boundaries. + * Boundary values are inclusive. See the examples below. + * If boundary2 < boundary1, the values are swapped. + * If boundary1 == boundary2, value of boundary1 will be returned + * + * Generating boundary values for Uint8: + * BoundaryValues(sizeof(Uint8), 10, 20, True) -> [10,11,19,20] + * BoundaryValues(sizeof(Uint8), 10, 20, False) -> [9,21] + * BoundaryValues(sizeof(Uint8), 0, 15, True) -> [0, 1, 14, 15] + * BoundaryValues(sizeof(Uint8), 0, 15, False) -> [16] + * BoundaryValues(sizeof(Uint8), 0, 255, False) -> NULL + * + * Generator works the same for other types of unsigned integers. + * + * Note: outBuffer will be allocated and needs to be freed later. + * If outbuffer != NULL, it'll be freed. + * + * \param maxValue The biggest value that is acceptable for this data type. + * For instance, for Uint8 -> 255, Uint16 -> 65536 etc. + * \param pBoundary1 defines lower boundary + * \param pBoundary2 defines upper boundary + * \param validDomain Generate only for valid domain (for the data type) + * + * \param outBuffer The generated boundary values are put here + * + * \returns Returns the number of elements in outBuffer or -1 in case of error + */ +Uint32 +SDLTest_GenerateUnsignedBoundaryValues(const Uint64 maxValue, + Uint64 pBoundary1, Uint64 pBoundary2, SDL_bool validDomain, + Uint64 *outBuffer) +{ + Uint64 boundary1 = pBoundary1, boundary2 = pBoundary2; + Uint64 temp; + Uint64 tempBuf[4]; + int index; + + if(outBuffer != NULL) { + SDL_free(outBuffer); + } + + if(boundary1 > boundary2) { + temp = boundary1; + boundary1 = boundary2; + boundary2 = temp; + } + + index = 0; + if(boundary1 == boundary2) { + tempBuf[index++] = boundary1; + } + else if(validDomain) { + tempBuf[index++] = boundary1; + + if(boundary1 < UINT64_MAX) + tempBuf[index++] = boundary1 + 1; + + tempBuf[index++] = boundary2 - 1; + tempBuf[index++] = boundary2; + } + else { + if(boundary1 > 0) { + tempBuf[index++] = boundary1 - 1; + } + + if(boundary2 < maxValue && boundary2 < UINT64_MAX) { + tempBuf[index++] = boundary2 + 1; + } + } + + if(index == 0) { + // There are no valid boundaries + return 0; + } + + // Create the return buffer + outBuffer = (Uint64 *)SDL_malloc(index * sizeof(Uint64)); + if(outBuffer == NULL) { + return 0; + } + + SDL_memcpy(outBuffer, tempBuf, index * sizeof(Uint64)); + + return index; +} + +Uint8 +SDLTest_RandomUint8BoundaryValue(Uint8 boundary1, Uint8 boundary2, SDL_bool validDomain) +{ + Uint64 *buffer = NULL; + Uint32 size; + Uint32 index; + Uint8 retVal; + + // max value for Uint8 + const Uint64 maxValue = UINT8_MAX; + + size = SDLTest_GenerateUnsignedBoundaryValues(maxValue, + (Uint64) boundary1, (Uint64) boundary2, + validDomain, buffer); + if (size == 0) { + return 0; + } + + index = SDLTest_RandomSint32() % size; + retVal = (Uint8)buffer[index]; + + SDL_free(buffer); + + fuzzerInvocationCounter++; + + return retVal; +} + +Uint16 +SDLTest_RandomUint16BoundaryValue(Uint16 boundary1, Uint16 boundary2, SDL_bool validDomain) +{ + Uint64 *buffer = NULL; + Uint32 size; + Uint32 index; + Uint16 retVal; + + // max value for Uint16 + const Uint64 maxValue = UINT16_MAX; + + size = SDLTest_GenerateUnsignedBoundaryValues(maxValue, + (Uint64) boundary1, (Uint64) boundary2, + validDomain, buffer); + if(size == 0) { + return 0; + } + + index = SDLTest_RandomSint32() % size; + retVal = (Uint16) buffer[index]; + + SDL_free(buffer); + + fuzzerInvocationCounter++; + + return retVal; +} + +Uint32 +SDLTest_RandomUint32BoundaryValue(Uint32 boundary1, Uint32 boundary2, SDL_bool validDomain) +{ + Uint64 *buffer = NULL; + Uint32 size; + Uint32 index; + Uint32 retVal; + + // max value for Uint32 + const Uint64 maxValue = UINT32_MAX; + + size = SDLTest_GenerateUnsignedBoundaryValues(maxValue, + (Uint64) boundary1, (Uint64) boundary2, + validDomain, buffer); + if(size == 0) { + return 0; + } + + index = SDLTest_RandomSint32() % size; + retVal = (Uint32) buffer[index]; + + SDL_free(buffer); + + fuzzerInvocationCounter++; + + return retVal; +} + +Uint64 +SDLTest_RandomUint64BoundaryValue(Uint64 boundary1, Uint64 boundary2, SDL_bool validDomain) +{ + Uint64 *buffer = NULL; + Uint32 size; + Uint32 index; + Uint64 retVal; + + // max value for Uint64 + const Uint64 maxValue = UINT64_MAX; + + size = SDLTest_GenerateUnsignedBoundaryValues(maxValue, + (Uint64) boundary1, (Uint64) boundary2, + validDomain, buffer); + if(size == 0) { + return 0; + } + + index = SDLTest_RandomSint32() % size; + retVal = (Uint64) buffer[index]; + + SDL_free(buffer); + + fuzzerInvocationCounter++; + + return retVal; +} + +/*! + * Generates boundary values between the given boundaries. + * Boundary values are inclusive. See the examples below. + * If boundary2 < boundary1, the values are swapped. + * If boundary1 == boundary2, value of boundary1 will be returned + * + * Generating boundary values for Sint8: + * SignedBoundaryValues(sizeof(Sint8), -10, 20, True) -> [-11,-10,19,20] + * SignedBoundaryValues(sizeof(Sint8), -10, 20, False) -> [-11,21] + * SignedBoundaryValues(sizeof(Sint8), -30, -15, True) -> [-30, -29, -16, -15] + * SignedBoundaryValues(sizeof(Sint8), -128, 15, False) -> [16] + * SignedBoundaryValues(sizeof(Sint8), -128, 127, False) -> NULL + * + * Generator works the same for other types of signed integers. + * + * Note: outBuffer will be allocated and needs to be freed later. + * If outbuffer != NULL, it'll be freed. + * + * + * \param minValue The smallest value that is acceptable for this data type. + * For instance, for Uint8 -> -128, Uint16 -> -32,768 etc. + * \param maxValue The biggest value that is acceptable for this data type. + * For instance, for Uint8 -> 127, Uint16 -> 32767 etc. + * \param pBoundary1 defines lower boundary + * \param pBoundary2 defines upper boundary + * \param validDomain Generate only for valid domain (for the data type) + * + * \param outBuffer The generated boundary values are put here + * + * \returns Returns the number of elements in outBuffer or -1 in case of error + */ +Uint32 +SDLTest_GenerateSignedBoundaryValues(const Sint64 minValue, const Sint64 maxValue, + Sint64 pBoundary1, Sint64 pBoundary2, SDL_bool validDomain, + Sint64 *outBuffer) +{ + int index; + Sint64 tempBuf[4]; + Sint64 boundary1 = pBoundary1, boundary2 = pBoundary2; + + if(outBuffer != NULL) { + SDL_free(outBuffer); + } + + if(boundary1 > boundary2) { + Sint64 temp = boundary1; + boundary1 = boundary2; + boundary2 = temp; + } + + index = 0; + if(boundary1 == boundary2) { + tempBuf[index++] = boundary1; + } + else if(validDomain) { + tempBuf[index++] = boundary1; + + if(boundary1 < LLONG_MAX) + tempBuf[index++] = boundary1 + 1; + + if(boundary2 > LLONG_MIN) + tempBuf[index++] = boundary2 - 1; + + tempBuf[index++] = boundary2; + } + else { + if(boundary1 > minValue && boundary1 > LLONG_MIN) { + tempBuf[index++] = boundary1 - 1; + } + + if(boundary2 < maxValue && boundary2 < UINT64_MAX) { + tempBuf[index++] = boundary2 + 1; + } + } + + if(index == 0) { + // There are no valid boundaries + return 0; + } + + // Create the return buffer + outBuffer = (Sint64 *)SDL_malloc(index * sizeof(Sint64)); + if(outBuffer == NULL) { + return 0; + } + + SDL_memcpy((void *)outBuffer, (void *)tempBuf, index * sizeof(Sint64)); + + return (Uint32)index; +} + +Sint8 +SDLTest_RandomSint8BoundaryValue(Sint8 boundary1, Sint8 boundary2, SDL_bool validDomain) +{ + // min & max values for Sint8 + const Sint64 maxValue = CHAR_MAX; + const Sint64 minValue = CHAR_MIN; + + Sint64 *buffer = NULL; + Uint32 size; + Uint32 index; + Sint8 retVal; + + size = SDLTest_GenerateSignedBoundaryValues(minValue, maxValue, + (Sint64) boundary1, (Sint64) boundary2, + validDomain, buffer); + if(size == 0) { + return CHAR_MIN; + } + + index = SDLTest_RandomSint32() % size; + retVal = (Sint8) buffer[index]; + + SDL_free(buffer); + + fuzzerInvocationCounter++; + + return retVal; +} + +Sint16 +SDLTest_RandomSint16BoundaryValue(Sint16 boundary1, Sint16 boundary2, SDL_bool validDomain) +{ + // min & max values for Sint16 + const Sint64 maxValue = SHRT_MAX; + const Sint64 minValue = SHRT_MIN; + Sint64 *buffer = NULL; + Uint32 size; + Uint32 index; + Sint16 retVal; + + size = SDLTest_GenerateSignedBoundaryValues(minValue, maxValue, + (Sint64) boundary1, (Sint64) boundary2, + validDomain, buffer); + if(size == 0) { + return SHRT_MIN; + } + + index = SDLTest_RandomSint32() % size; + retVal = (Sint16) buffer[index]; + + SDL_free(buffer); + + fuzzerInvocationCounter++; + + return retVal; +} + +Sint32 +SDLTest_RandomSint32BoundaryValue(Sint32 boundary1, Sint32 boundary2, SDL_bool validDomain) +{ + // min & max values for Sint32 + const Sint64 maxValue = INT_MAX; + const Sint64 minValue = INT_MIN; + + Sint64 *buffer = NULL; + Uint32 size; + Uint32 index; + Sint32 retVal; + + size = SDLTest_GenerateSignedBoundaryValues(minValue, maxValue, + (Sint64) boundary1, (Sint64) boundary2, + validDomain, buffer); + if(size == 0) { + return INT_MIN; + } + + index = SDLTest_RandomSint32() % size; + retVal = (Sint32) buffer[index]; + + SDL_free(buffer); + + fuzzerInvocationCounter++; + + return retVal; +} + +Sint64 +SDLTest_RandomSint64BoundaryValue(Sint64 boundary1, Sint64 boundary2, SDL_bool validDomain) +{ + Sint64 *buffer = NULL; + Uint32 size; + Uint32 index; + Sint64 retVal; + + // min & max values for Sint64 + const Sint64 maxValue = LLONG_MAX; + const Sint64 minValue = LLONG_MIN; + + size = SDLTest_GenerateSignedBoundaryValues(minValue, maxValue, + (Sint64) boundary1, (Sint64) boundary2, + validDomain, buffer); + if(size == 0) { + return LLONG_MIN; + } + + index = SDLTest_RandomSint32() % size; + retVal = (Sint64) buffer[index]; + + SDL_free(buffer); + + fuzzerInvocationCounter++; + + return retVal; +} + +float +SDLTest_RandomUnitFloat() +{ + return (float) SDLTest_RandomUint32() / UINT_MAX; +} + +float +SDLTest_RandomFloat() +{ + return (float) (FLT_MIN + SDLTest_RandomUnitDouble() * (FLT_MAX - FLT_MIN)); +} + +double +SDLTest_RandomUnitDouble() +{ + return (double) (SDLTest_RandomUint64() >> 11) * (1.0/9007199254740992.0); +} + +double +SDLTest_RandomDouble() +{ + double r = 0.0; + double s = 1.0; + do { + s /= UINT_MAX + 1.0; + r += (double)SDLTest_RandomInt(&rndContext) * s; + } while (s > DBL_EPSILON); + + fuzzerInvocationCounter++; + + return r; +} + + +char * +SDLTest_RandomAsciiString() +{ + // note: fuzzerInvocationCounter is increment in the RandomAsciiStringWithMaximumLenght + return SDLTest_RandomAsciiStringWithMaximumLength(255); +} + +char * +SDLTest_RandomAsciiStringWithMaximumLength(int maxSize) +{ + int size; + char *string; + int counter; + + fuzzerInvocationCounter++; + + if(maxSize < 1) { + return NULL; + } + + size = (SDLTest_RandomUint32() % (maxSize + 1)) + 1; + string = (char *)SDL_malloc(size * sizeof(char)); + if (string==NULL) { + return NULL; + } + + for(counter = 0; counter < size; ++counter) { + string[counter] = (char)SDLTest_RandomIntegerInRange(1, 127); + } + + string[counter] = '\0'; + + return string; +}