The fuzzer logic is as follows:
For each iteration:
- Extract several decimal strings from single libFuzzer input using internal logic
- Call the
initialize
function of every loaded module.- If any
initialize
call returns failure, then go to step 9
- If any
- Call the
bignum_from_string
function of every loaded module for every decimal string extracted in step 1- If any
bignum_from_string
call returns failure, then go to step 9
- If any
- Extract an
operation_t
struct and anuint8_t
"opt" value from the libFuzzer input using internal logic- If there is insuffcient data left in the libFuzzer input to extract an
operation_t
struct and anuint8_t
"opt" value, then go to step 9
- If there is insuffcient data left in the libFuzzer input to extract an
- Call the
operation
function of every loaded module- If any
operation
call returns failure, then go to step 9
- If any
- Call the
string_from_bignum
function of every loaded module for each of their internal bignum representations- If any
string_from_bignum
call returns failure, then go to step 9
- If any
- Compare the strings collected in step 6 with one another, and
abort()
if a mismatch is found - Go to step 4
- Call the
shutdown
function of every loaded module, and proceed to next iteration
Each module must implement a module_t
struct, defined in include/bndiff/module.h
.
Currently, this struct contains 6 instruction pointers and 1 string pointer.
Objective:
- If applicable, allocate resources or initialize objects that must be available throughout a single iteration.
Note:
- This function is called once per iteration.
Return value:
0
for success-1
for failure
Objective:
- Convert
input
, which is a null-terminated, base 10 string representation of an integer, to an internal bignum representation. - Store the pointer to the internal bignum representation to
*output
;
Notes:
- The (pointer to the) internal bignum representation must persist in memory until
destroy_bignum
is called on it. input
may be prefixed by the minus symbol-
do denote that the number that follows it is negative.- This function performs the inverse operation of
int string_from_bignum(void* bignum, char** output)
.
Return value:
0
for success-1
for failure
Objective:
- Convert the internal bignum representation pointed to by
bignum
to a base 10 null-terminated string. - Store the pointer to this string in
*output
Notes:
- This allocation for the string that this function produces MUST be done with
malloc()
. - If the bignum at hand represents a negative value, the output string must be prefixed with the minus symbol
-
. - This function performs the inverse operation of
int bignum_from_string(const char* input, void** output)
.
Return value:
0
for success-1
for failure
Objective:
- Free any resources that the internal bignum representation pointer to by
bignum
uses.
Return value:
- Does not return a value
Objective:
- Perform
operation
on the bignums inbignum_cluster
. - The semantics of each operation type are prescribed in the chapter
Operations
below.
Notes:
- This function may return failure (see below) if it does not support the requested operation, or otherwise can not or will not comply to the request.
- The
op
variable can be used to choose from several internal, semantically equivalent functions. For example:
switch ( operation ) {
...
...
case BN_FUZZ_OP_ADD:
if ( (opt & 1) == 0 ) {
internal_add_function_1(...);
} else {
internal_add_function_2(...);
}
}
Return value:
0
for success-1
for failure
Objective:
- If applicable, free resources or destroy objects that must were created with
int initialize(void)
.
Note:
- This function is called once per iteration.
Return value:
- Does not return a value
Objective: A null-terminated string that is a concise, human-readable description of the module.
#include <bndiff/module.h>
#include <bndiff/operation.h>
#include <bndiff/bignum.h>
static int initialize(void) { /* TODO */ }
static int bignum_from_string(const char* input, void** output) { /* TODO */ }
static int string_from_bignum(void* input, char** output) { /* TODO */ }
static void destroy_bignum(void* bignum) { /* TODO */ }
static int operation(
bignum_cluster_t* bignum_cluster,
operation_t operation,
uint8_t opt) { /* TODO */ }
static void shutdown(void) { /* TODO */ }
module_t mod_example = {
.initialize = initialize,
.bignum_from_string = bignum_from_string,
.string_from_bignum = string_from_bignum,
.destroy_bignum = destroy_bignum,
.operation = operation,
.shutdown = shutdown,
.name = "Example module"
};
Currently supported operations, defined in include/bndiff/operation.h
.
In the summary below, the symbols A, B, C and D represent the first, second, third and fourth bignum pointers present in a bignum_cluster_t
, respectively.
A = B + C
A = B - C
A = B * C
A = B / C
A = B MOD C
A = (B ** C) MOD D
A = B << 1
A = B >> 1
A = GCD(A, B)
A = (B + C) MOD D
A = B ** C
if B > C then A = 1
if B < C then A = -1
if B == C then A = 0
A = B * B
A = 0 - B
A = ABS(B)
if B is a prime number then A = 1
if B is not a prime number then A = 0
A = (B - C) MOD D
TMP = A
A = B
B = TMP
A = (B * C) MOD D
A |= 1 << B
- This operation is free to do whatever it wants, but it must not alter any bignums