diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/afl-fuzz.h | 129 | ||||
-rw-r--r-- | include/afl-prealloc.h | 5 | ||||
-rw-r--r-- | include/alloc-inl.h | 97 | ||||
-rw-r--r-- | include/common.h | 326 | ||||
-rw-r--r-- | include/list.h | 49 | ||||
-rw-r--r-- | include/types.h | 22 |
6 files changed, 246 insertions, 382 deletions
diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 7dddefb0..56135d0e 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -239,8 +239,6 @@ enum { }; -extern u8 *doc_path; /* gath to documentation dir */ - /* Python stuff */ #ifdef USE_PYTHON @@ -290,8 +288,20 @@ typedef struct py_mutator { PyObject *py_module; PyObject *py_functions[PY_FUNC_COUNT]; - void *afl_state; - void *py_data; + void * afl_state; + void * py_data; + + u8 * fuzz_buf; + size_t fuzz_size; + + u8 * pre_save_buf; + size_t pre_save_size; + + u8 * trim_buf; + size_t trim_size; + + u8 * havoc_buf; + size_t havoc_size; } py_mutator_t; @@ -472,11 +482,6 @@ typedef struct afl_state { unique_tmouts, /* Timeouts with unique signatures */ unique_hangs, /* Hangs with unique signatures */ total_execs, /* Total execve() calls */ - slowest_exec_ms, /* Slowest testcase non hang in ms */ - start_time, /* Unix start time (ms) */ - last_path_time, /* Time for most recent path (ms) */ - last_crash_time, /* Time for most recent crash (ms) */ - last_hang_time, /* Time for most recent hang (ms) */ last_crash_execs, /* Exec counter at last crash */ queue_cycle, /* Queue round counter */ cycles_wo_finds, /* Cycles without any new paths */ @@ -484,9 +489,14 @@ typedef struct afl_state { bytes_trim_in, /* Bytes coming into the trimmer */ bytes_trim_out, /* Bytes coming outa the trimmer */ blocks_eff_total, /* Blocks subject to effector maps */ - blocks_eff_select; /* Blocks selected as fuzzable */ + blocks_eff_select, /* Blocks selected as fuzzable */ + start_time, /* Unix start time (ms) */ + last_path_time, /* Time for most recent path (ms) */ + last_crash_time, /* Time for most recent crash (ms) */ + last_hang_time; /* Time for most recent hang (ms) */ - u32 subseq_tmouts; /* Number of timeouts in a row */ + u32 slowest_exec_ms, /* Slowest testcase non hang in ms */ + subseq_tmouts; /* Number of timeouts in a row */ u8 *stage_name, /* Name of the current fuzz stage */ *stage_short, /* Short stage name */ @@ -541,7 +551,11 @@ typedef struct afl_state { struct extra_data *a_extras; /* Automatically selected extras */ u32 a_extras_cnt; /* Total number of tokens available */ - u8 *(*post_handler)(u8 *buf, u32 *len); + /* afl_postprocess API */ + void *(*post_init)(struct afl_state *afl); + size_t (*post_handler)(void *data, u8 *buf, u32 len, u8 **out_buf); + void *(*post_deinit)(void *data); + void *post_data; /* CmpLog */ @@ -550,9 +564,6 @@ typedef struct afl_state { /* Custom mutators */ struct custom_mutator *mutator; -#ifdef USE_PYTHON - struct custom_mutator *py_mutator; -#endif /* cmplog forkserver ids */ s32 cmplog_fsrv_ctl_fd, cmplog_fsrv_st_fd; @@ -580,6 +591,26 @@ typedef struct afl_state { u8 clean_trace_custom[MAP_SIZE]; u8 first_trace[MAP_SIZE]; + /*needed for afl_fuzz_one */ + // TODO: see which we can reuse + u8 * out_buf; + size_t out_size; + + u8 * out_scratch_buf; + size_t out_scratch_size; + + u8 * eff_buf; + size_t eff_size; + + u8 * in_buf; + size_t in_size; + + u8 * in_scratch_buf; + size_t in_scratch_size; + + u8 * ex_buf; + size_t ex_size; + } afl_state_t; /* A global pointer to all instances is needed (for now) for signals to arrive @@ -591,8 +622,10 @@ struct custom_mutator { const char *name; void * dh; + u8 * pre_save_buf; + size_t pre_save_size; - void *data; /* custom mutator data ptr */ + void *data; /* custom mutator data ptr */ /* hooks for the custom mutator function */ @@ -611,16 +644,18 @@ struct custom_mutator { * (Optional for now. Required in the future) * * @param data pointer returned in afl_custom_init for this fuzz case - * @param[inout] buf Pointer to the input data to be mutated and the mutated + * @param[in] buf Pointer to the input data to be mutated and the mutated * output * @param[in] buf_size Size of the input/output data + * @param[out] out_buf the new buffer. We may reuse *buf if large enough. + * *out_buf = NULL is treated as FATAL. * @param[in] add_buf Buffer containing the additional test case * @param[in] add_buf_size Size of the additional test case * @param[in] max_size Maximum size of the mutated output. The mutation must * not produce data larger than max_size. * @return Size of the mutated output. */ - size_t (*afl_custom_fuzz)(void *data, u8 **buf, size_t buf_size, + size_t (*afl_custom_fuzz)(void *data, u8 *buf, size_t buf_size, u8 **out_buf, u8 *add_buf, size_t add_buf_size, size_t max_size); /** @@ -633,10 +668,10 @@ struct custom_mutator { * @param[in] data pointer returned in afl_custom_init for this fuzz case * @param[in] buf Buffer containing the test case to be executed * @param[in] buf_size Size of the test case - * @param[out] out_buf Pointer to the buffer of storing the test case after - * processing. External library should allocate memory for out_buf. AFL++ - * will release the memory after saving the test case. - * @return Size of the output buffer after processing + * @param[out] out_buf Pointer to the buffer storing the test case after + * processing. External library should allocate memory for out_buf. + * It can chose to alter buf in-place, if the space is large enough. + * @return Size of the output buffer. */ size_t (*afl_custom_pre_save)(void *data, u8 *buf, size_t buf_size, u8 **out_buf); @@ -660,9 +695,10 @@ struct custom_mutator { * @param data pointer returned in afl_custom_init for this fuzz case * @param buf Buffer containing the test case * @param buf_size Size of the test case - * @return The amount of possible iteration steps to trim the input + * @return The amount of possible iteration steps to trim the input. + * Negative on error. */ - u32 (*afl_custom_init_trim)(void *data, u8 *buf, size_t buf_size); + s32 (*afl_custom_init_trim)(void *data, u8 *buf, size_t buf_size); /** * This method is called for each trimming operation. It doesn't have any @@ -677,11 +713,11 @@ struct custom_mutator { * * @param data pointer returned in afl_custom_init for this fuzz case * @param[out] out_buf Pointer to the buffer containing the trimmed test case. - * External library should allocate memory for out_buf. AFL++ will release - * the memory after saving the test case. - * @param[out] out_buf_size Pointer to the size of the trimmed test case + * The library can reuse a buffer for each call + * and will have to free the buf (for example in deinit) + * @return the size of the trimmed test case */ - void (*afl_custom_trim)(void *data, u8 **out_buf, size_t *out_buf_size); + size_t (*afl_custom_trim)(void *data, u8 **out_buf); /** * This method is called after each trim operation to inform you if your @@ -693,9 +729,9 @@ struct custom_mutator { * @param data pointer returned in afl_custom_init for this fuzz case * @param success Indicates if the last trim operation was successful. * @return The next trim iteration index (from 0 to the maximum amount of - * steps returned in init_trim) + * steps returned in init_trim). Negative on error. */ - u32 (*afl_custom_post_trim)(void *data, u8 success); + s32 (*afl_custom_post_trim)(void *data, u8 success); /** * Perform a single custom mutation on a given input. @@ -703,16 +739,18 @@ struct custom_mutator { * * (Optional) * - * @param data pointer returned in afl_custom_init for this fuzz case - * @param[inout] buf Pointer to the input data to be mutated and the mutated + * @param[in] data pointer returned in afl_custom_init for this fuzz case + * @param[in] buf Pointer to the input data to be mutated and the mutated * output * @param[in] buf_size Size of input data + * @param[out] out_buf The new buffer. It's legal to reuse *buf if it's < + * buf_size. * @param[in] max_size Maximum size of the mutated output. The mutation must * not produce data larger than max_size. - * @return Size of the mutated output. + * @return Size of the mutated output (out_size). */ - size_t (*afl_custom_havoc_mutation)(void *data, u8 **buf, - size_t buf_size, size_t max_size); + size_t (*afl_custom_havoc_mutation)(void *data, u8 *buf, size_t buf_size, + u8 **out_buf, size_t max_size); /** * Return the probability (in percentage) that afl_custom_havoc_mutation @@ -748,9 +786,8 @@ struct custom_mutator { * @param filename_orig_queue File name of the original queue entry. This * argument can be NULL while initializing the fuzzer */ - void (*afl_custom_queue_new_entry)(void *data, - const u8 * filename_new_queue, - const u8 * filename_orig_queue); + void (*afl_custom_queue_new_entry)(void *data, const u8 *filename_new_queue, + const u8 *filename_orig_queue); /** * Deinitialize the custom mutator. * @@ -777,10 +814,10 @@ u8 trim_case_custom(afl_state_t *, struct queue_entry *q, u8 *in_buf); void finalize_py_module(void *); size_t pre_save_py(void *, u8 *, size_t, u8 **); -u32 init_trim_py(void *, u8 *, size_t); -u32 post_trim_py(void *, u8); -void trim_py(void *, u8 **, size_t *); -size_t havoc_mutation_py(void *, u8 **, size_t, size_t); +s32 init_trim_py(void *, u8 *, size_t); +s32 post_trim_py(void *, u8); +size_t trim_py(void *, u8 **); +size_t havoc_mutation_py(void *, u8 *, size_t, u8 **, size_t); u8 havoc_mutation_probability_py(void *); u8 queue_get_py(void *, const u8 *); void queue_new_entry_py(void *, const u8 *, const u8 *); @@ -898,13 +935,13 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len, static inline u32 rand_below(afl_state_t *afl, u32 limit) { #ifdef HAVE_ARC4RANDOM - if (afl->fixed_seed) { return random() % limit; } + if (unlikely(afl->fixed_seed)) { return random() % limit; } /* The boundary not being necessarily a power of 2, we need to ensure the result uniformity. */ return arc4random_uniform(limit); #else - if (!afl->fixed_seed && unlikely(!afl->rand_cnt--)) { + if (unlikely(!afl->rand_cnt--) && likely(!afl->fixed_seed)) { ck_read(afl->fsrv.dev_urandom_fd, &afl->rand_seed, sizeof(afl->rand_seed), "/dev/urandom"); @@ -920,7 +957,7 @@ static inline u32 rand_below(afl_state_t *afl, u32 limit) { static inline u32 get_rand_seed(afl_state_t *afl) { - if (afl->fixed_seed) return (u32)afl->init_seed; + if (unlikely(afl->fixed_seed)) return (u32)afl->init_seed; return afl->rand_seed[0]; } @@ -928,7 +965,7 @@ static inline u32 get_rand_seed(afl_state_t *afl) { /* Find first power of two greater or equal to val (assuming val under 2^63). */ -static u64 next_p2(u64 val) { +static inline u64 next_p2(u64 val) { u64 ret = 1; while (val > ret) diff --git a/include/afl-prealloc.h b/include/afl-prealloc.h index ab86f0d7..66e6aadf 100644 --- a/include/afl-prealloc.h +++ b/include/afl-prealloc.h @@ -44,9 +44,8 @@ typedef enum prealloc_status { /* Adds the entry used for prealloc bookkeeping to this struct */ -#define PREALLOCABLE \ - ; \ - pre_status_t pre_status; /* prealloc status of this instance */ +/* prealloc status of this instance */ +#define PREALLOCABLE pre_status_t pre_status /* allocate an element of type *el_ptr, to this variable. Uses (and reuses) the given prealloc_buf before hitting libc's malloc. diff --git a/include/alloc-inl.h b/include/alloc-inl.h index c8783d96..89889cc5 100644 --- a/include/alloc-inl.h +++ b/include/alloc-inl.h @@ -35,6 +35,9 @@ #include "types.h" #include "debug.h" +/* Initial size used for ck_maybe_grow */ +#define INITIAL_GROWTH_SIZE (64) + // Be careful! _WANT_ORIGINAL_AFL_ALLOC is not compatible with custom mutators #ifndef _WANT_ORIGINAL_AFL_ALLOC @@ -764,5 +767,99 @@ static inline void TRK_ck_free(void *ptr, const char *file, const char *func, #endif /* _WANT_ORIGINAL_AFL_ALLOC */ +/* This function calculates the next power of 2 greater or equal its argument. + @return The rounded up power of 2 (if no overflow) or 0 on overflow. +*/ +static inline size_t next_pow2(size_t in) { + + if (in == 0 || in > (size_t)-1) + return 0; /* avoid undefined behaviour under-/overflow */ + size_t out = in - 1; + out |= out >> 1; + out |= out >> 2; + out |= out >> 4; + out |= out >> 8; + out |= out >> 16; + return out + 1; + +} + +/* This function makes sure *size is > size_needed after call. + It will realloc *buf otherwise. + *size will grow exponentially as per: + https://blog.mozilla.org/nnethercote/2014/11/04/please-grow-your-buffers-exponentially/ + Will return NULL and free *buf if size_needed is <1 or realloc failed. + @return For convenience, this function returns *buf. + */ +static inline void *maybe_grow(void **buf, size_t *size, size_t size_needed) { + + /* No need to realloc */ + if (likely(size_needed && *size >= size_needed)) return *buf; + + /* No initial size was set */ + if (size_needed < INITIAL_GROWTH_SIZE) size_needed = INITIAL_GROWTH_SIZE; + + /* grow exponentially */ + size_t next_size = next_pow2(size_needed); + + /* handle overflow and zero size_needed */ + if (!next_size) { next_size = size_needed; } + + /* alloc */ + *buf = realloc(*buf, next_size); + *size = *buf ? next_size : 0; + + return *buf; + +} + +/* This function makes sure *size is > size_needed after call. + It will realloc *buf otherwise. + *size will grow exponentially as per: + https://blog.mozilla.org/nnethercote/2014/11/04/please-grow-your-buffers-exponentially/ + Will FATAL if size_needed is <1. + @return For convenience, this function returns *buf. + */ +static inline void *ck_maybe_grow(void **buf, size_t *size, + size_t size_needed) { + + /* Oops. found a bug? */ + if (unlikely(size_needed < 1)) FATAL("cannot grow to non-positive size"); + + /* No need to realloc */ + if (likely(*size >= size_needed)) return *buf; + + /* No initial size was set */ + if (size_needed < INITIAL_GROWTH_SIZE) size_needed = INITIAL_GROWTH_SIZE; + + /* grow exponentially */ + size_t next_size = next_pow2(size_needed); + + /* handle overflow */ + if (!next_size) { next_size = size_needed; } + + /* alloc */ + *buf = ck_realloc(*buf, next_size); + *size = next_size; + + return *buf; + +} + +/* Swaps buf1 ptr and buf2 ptr, as well as their sizes */ +static inline void swap_bufs(void **buf1, size_t *size1, void **buf2, + size_t *size2) { + + void * scratch_buf = *buf1; + size_t scratch_size = *size1; + *buf1 = *buf2; + *size1 = *size2; + *buf2 = scratch_buf; + *size2 = scratch_size; + +} + +#undef INITIAL_GROWTH_SIZE + #endif /* ! _HAVE_ALLOC_INL_H */ diff --git a/include/common.h b/include/common.h index 97076004..c9436e81 100644 --- a/include/common.h +++ b/include/common.h @@ -29,6 +29,7 @@ #include <stdio.h> #include <string.h> +#include <unistd.h> #include <sys/time.h> #include "types.h" #include "stdbool.h" @@ -47,349 +48,60 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv); char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv); char * get_afl_env(char *env); -/* Get unix time in milliseconds */ - -static u64 get_cur_time(void) { - - struct timeval tv; - struct timezone tz; - - gettimeofday(&tv, &tz); +extern u8 be_quiet; +extern u8 *doc_path; /* path to documentation dir */ - return (tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000); +/* Get unix time in milliseconds */ -} +u64 get_cur_time(void); /* Get unix time in microseconds */ -static u64 get_cur_time_us(void) { - - struct timeval tv; - struct timezone tz; - - gettimeofday(&tv, &tz); - - return (tv.tv_sec * 1000000ULL) + tv.tv_usec; - -} +u64 get_cur_time_us(void); /* Describe integer. The buf should be at least 6 bytes to fit all ints we randomly see. Will return buf for convenience. */ -static u8 *stringify_int(u8 *buf, size_t len, u64 val) { - -#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) \ - do { \ - \ - if (val < (_divisor) * (_limit_mult)) { \ - \ - snprintf(buf, len, _fmt, ((_cast)val) / (_divisor)); \ - return buf; \ - \ - } \ - \ - } while (0) - - /* 0-9999 */ - CHK_FORMAT(1, 10000, "%llu", u64); - - /* 10.0k - 99.9k */ - CHK_FORMAT(1000, 99.95, "%0.01fk", double); - - /* 100k - 999k */ - CHK_FORMAT(1000, 1000, "%lluk", u64); - - /* 1.00M - 9.99M */ - CHK_FORMAT(1000 * 1000, 9.995, "%0.02fM", double); - - /* 10.0M - 99.9M */ - CHK_FORMAT(1000 * 1000, 99.95, "%0.01fM", double); - - /* 100M - 999M */ - CHK_FORMAT(1000 * 1000, 1000, "%lluM", u64); - - /* 1.00G - 9.99G */ - CHK_FORMAT(1000LL * 1000 * 1000, 9.995, "%0.02fG", double); - - /* 10.0G - 99.9G */ - CHK_FORMAT(1000LL * 1000 * 1000, 99.95, "%0.01fG", double); - - /* 100G - 999G */ - CHK_FORMAT(1000LL * 1000 * 1000, 1000, "%lluG", u64); - - /* 1.00T - 9.99G */ - CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 9.995, "%0.02fT", double); - - /* 10.0T - 99.9T */ - CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 99.95, "%0.01fT", double); - - /* 100T+ */ - strncpy(buf, "infty", len); - buf[len - 1] = '\0'; - - return buf; - -} +u8 *stringify_int(u8 *buf, size_t len, u64 val); /* Describe float. Similar as int. */ -static u8 *stringify_float(u8 *buf, size_t len, double val) { - - if (val < 99.995) { - - snprintf(buf, len, "%0.02f", val); - - } else if (val < 999.95) { - - snprintf(buf, len, "%0.01f", val); - - } else { - - stringify_int(buf, len, (u64)val); - - } - - return buf; - -} +u8 *stringify_float(u8 *buf, size_t len, double val); /* Describe integer as memory size. */ -static u8 *stringify_mem_size(u8 *buf, size_t len, u64 val) { - - /* 0-9999 */ - CHK_FORMAT(1, 10000, "%llu B", u64); - - /* 10.0k - 99.9k */ - CHK_FORMAT(1024, 99.95, "%0.01f kB", double); - - /* 100k - 999k */ - CHK_FORMAT(1024, 1000, "%llu kB", u64); - - /* 1.00M - 9.99M */ - CHK_FORMAT(1024 * 1024, 9.995, "%0.02f MB", double); - - /* 10.0M - 99.9M */ - CHK_FORMAT(1024 * 1024, 99.95, "%0.01f MB", double); - - /* 100M - 999M */ - CHK_FORMAT(1024 * 1024, 1000, "%llu MB", u64); - - /* 1.00G - 9.99G */ - CHK_FORMAT(1024LL * 1024 * 1024, 9.995, "%0.02f GB", double); - - /* 10.0G - 99.9G */ - CHK_FORMAT(1024LL * 1024 * 1024, 99.95, "%0.01f GB", double); - - /* 100G - 999G */ - CHK_FORMAT(1024LL * 1024 * 1024, 1000, "%llu GB", u64); - - /* 1.00T - 9.99G */ - CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 9.995, "%0.02f TB", double); - - /* 10.0T - 99.9T */ - CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 99.95, "%0.01f TB", double); - -#undef CHK_FORMAT - - /* 100T+ */ - strncpy(buf, "infty", len - 1); - buf[len - 1] = '\0'; - - return buf; - -} +u8 *stringify_mem_size(u8 *buf, size_t len, u64 val); /* Describe time delta as string. Returns a pointer to buf for convenience. */ -static u8 *stringify_time_diff(u8 *buf, size_t len, u64 cur_ms, u64 event_ms) { - - u64 delta; - s32 t_d, t_h, t_m, t_s; - u8 val_buf[STRINGIFY_VAL_SIZE_MAX]; - - if (!event_ms) { - - snprintf(buf, len, "none seen yet"); - - } else { - - delta = cur_ms - event_ms; - - t_d = delta / 1000 / 60 / 60 / 24; - t_h = (delta / 1000 / 60 / 60) % 24; - t_m = (delta / 1000 / 60) % 60; - t_s = (delta / 1000) % 60; - - stringify_int(val_buf, sizeof(val_buf), t_d); - snprintf(buf, len, "%s days, %d hrs, %d min, %d sec", val_buf, t_h, t_m, - t_s); - - } - - return buf; - -} - +u8 *stringify_time_diff(u8 *buf, size_t len, u64 cur_ms, u64 event_ms); /* Unsafe Describe integer. The buf sizes are not checked. This is unsafe but fast. Will return buf for convenience. */ -static u8 *u_stringify_int(u8 *buf, u64 val) { - -#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) \ - do { \ - \ - if (val < (_divisor) * (_limit_mult)) { \ - \ - sprintf(buf, _fmt, ((_cast)val) / (_divisor)); \ - return buf; \ - \ - } \ - \ - } while (0) - - /* 0-9999 */ - CHK_FORMAT(1, 10000, "%llu", u64); - - /* 10.0k - 99.9k */ - CHK_FORMAT(1000, 99.95, "%0.01fk", double); - - /* 100k - 999k */ - CHK_FORMAT(1000, 1000, "%lluk", u64); - - /* 1.00M - 9.99M */ - CHK_FORMAT(1000 * 1000, 9.995, "%0.02fM", double); - - /* 10.0M - 99.9M */ - CHK_FORMAT(1000 * 1000, 99.95, "%0.01fM", double); - - /* 100M - 999M */ - CHK_FORMAT(1000 * 1000, 1000, "%lluM", u64); - - /* 1.00G - 9.99G */ - CHK_FORMAT(1000LL * 1000 * 1000, 9.995, "%0.02fG", double); - - /* 10.0G - 99.9G */ - CHK_FORMAT(1000LL * 1000 * 1000, 99.95, "%0.01fG", double); - - /* 100G - 999G */ - CHK_FORMAT(1000LL * 1000 * 1000, 1000, "%lluG", u64); - - /* 1.00T - 9.99G */ - CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 9.995, "%0.02fT", double); - - /* 10.0T - 99.9T */ - CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 99.95, "%0.01fT", double); - - /* 100T+ */ - strcpy(buf, "infty"); - - return buf; - -} +u8 *u_stringify_int(u8 *buf, u64 val); /* Unsafe describe float. Similar as unsafe int. */ -static u8 *u_stringify_float(u8 *buf, double val) { - - if (val < 99.995) { - - sprintf(buf, "%0.02f", val); - - } else if (val < 999.95) { - - sprintf(buf, "%0.01f", val); - - } else { - - return u_stringify_int(buf, (u64)val); - - } - - return buf; - -} +u8 *u_stringify_float(u8 *buf, double val); /* Unsafe describe integer as memory size. */ -static u8 *u_stringify_mem_size(u8 *buf, u64 val) { - - /* 0-9999 */ - CHK_FORMAT(1, 10000, "%llu B", u64); - - /* 10.0k - 99.9k */ - CHK_FORMAT(1024, 99.95, "%0.01f kB", double); - - /* 100k - 999k */ - CHK_FORMAT(1024, 1000, "%llu kB", u64); - - /* 1.00M - 9.99M */ - CHK_FORMAT(1024 * 1024, 9.995, "%0.02f MB", double); - - /* 10.0M - 99.9M */ - CHK_FORMAT(1024 * 1024, 99.95, "%0.01f MB", double); - - /* 100M - 999M */ - CHK_FORMAT(1024 * 1024, 1000, "%llu MB", u64); - - /* 1.00G - 9.99G */ - CHK_FORMAT(1024LL * 1024 * 1024, 9.995, "%0.02f GB", double); - - /* 10.0G - 99.9G */ - CHK_FORMAT(1024LL * 1024 * 1024, 99.95, "%0.01f GB", double); - - /* 100G - 999G */ - CHK_FORMAT(1024LL * 1024 * 1024, 1000, "%llu GB", u64); - - /* 1.00T - 9.99G */ - CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 9.995, "%0.02f TB", double); - - /* 10.0T - 99.9T */ - CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 99.95, "%0.01f TB", double); - -#undef CHK_FORMAT - - /* 100T+ */ - strcpy(buf, "infty"); - - return buf; - -} +u8 *u_stringify_mem_size(u8 *buf, u64 val); /* Unsafe describe time delta as string. Returns a pointer to buf for convenience. */ -static u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms) { - - u64 delta; - s32 t_d, t_h, t_m, t_s; - u8 val_buf[STRINGIFY_VAL_SIZE_MAX]; - - if (!event_ms) { - - sprintf(buf, "none seen yet"); - - } else { - - delta = cur_ms - event_ms; - - t_d = delta / 1000 / 60 / 60 / 24; - t_h = (delta / 1000 / 60 / 60) % 24; - t_m = (delta / 1000 / 60) % 60; - t_s = (delta / 1000) % 60; - - u_stringify_int(val_buf, t_d); - sprintf(buf, "%s days, %d hrs, %d min, %d sec", val_buf, t_h, t_m, t_s); - - } - - return buf; +u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms); -} +/* Wrapper for select() and read(), reading exactly len bytes. + Returns the time passed to read. + If the wait times out, returns timeout_ms + 1; + Returns 0 if an error occurred (fd closed, signal, ...); */ +u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms); #endif diff --git a/include/list.h b/include/list.h index 1190931f..e93b4e8f 100644 --- a/include/list.h +++ b/include/list.h @@ -34,8 +34,8 @@ #include "debug.h" #include "afl-prealloc.h" -#define LIST_PREALLOC_SIZE \ - (64) /* How many elements to allocate before malloc is needed */ +/* How many elements to allocate before malloc is needed */ +#define LIST_PREALLOC_SIZE (64) typedef struct list_element { @@ -56,17 +56,18 @@ typedef struct list { static inline element_t *get_head(list_t *list) { - return &list->element_prealloc_buf[0]; + /* The first element is the head */ + return list->element_prealloc_buf; } -static void list_free_el(list_t *list, element_t *el) { +static inline void list_free_el(list_t *list, element_t *el) { PRE_FREE(el, list->element_prealloc_count); } -static void list_append(list_t *list, void *el) { +static inline void list_append(list_t *list, void *el) { element_t *head = get_head(list); if (!head->next) { @@ -97,23 +98,23 @@ static void list_append(list_t *list, void *el) { A return from this block will return from calling func. */ -#define LIST_FOREACH(list, type, block) \ - do { \ - \ - list_t * li = (list); \ - element_t *head = get_head((li)); \ - element_t *el_box = (head)->next; \ - if (!el_box) FATAL("foreach over uninitialized list"); \ - while (el_box != head) { \ - \ - type *el = (type *)((el_box)->data); \ - /* get next so el_box can be unlinked */ \ - element_t *next = el_box->next; \ - {block}; \ - el_box = next; \ - \ - } \ - \ +#define LIST_FOREACH(list, type, block) \ + do { \ + \ + list_t * li = (list); \ + element_t *head = get_head((li)); \ + element_t *el_box = (head)->next; \ + if (!el_box) FATAL("foreach over uninitialized list"); \ + while (el_box != head) { \ + \ + __attribute__((unused)) type *el = (type *)((el_box)->data); \ + /* get next so el_box can be unlinked */ \ + element_t *next = el_box->next; \ + {block}; \ + el_box = next; \ + \ + } \ + \ } while (0); /* In foreach: remove the current el from the list */ @@ -143,7 +144,7 @@ static void list_append(list_t *list, void *el) { /* remove an item from the list */ -static void list_remove(list_t *list, void *remove_me) { +static inline void list_remove(list_t *list, void *remove_me) { LIST_FOREACH(list, void, { @@ -165,7 +166,7 @@ static void list_remove(list_t *list, void *remove_me) { /* Returns true if el is in list */ -static bool list_contains(list_t *list, void *contains_me) { +static inline bool list_contains(list_t *list, void *contains_me) { LIST_FOREACH(list, void, { diff --git a/include/types.h b/include/types.h index bd4bd05d..da95cb39 100644 --- a/include/types.h +++ b/include/types.h @@ -58,8 +58,22 @@ typedef int32_t s32; typedef int64_t s64; #ifndef MIN -#define MIN(_a, _b) ((_a) > (_b) ? (_b) : (_a)) -#define MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b)) +#define MIN(a, b) \ + ({ \ + \ + __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + _a < _b ? _a : _b; \ + \ + }) +#define MAX(a, b) \ + ({ \ + \ + __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + _a > _b ? _a : _b; \ + \ + }) #endif /* !MIN */ #define SWAP16(_x) \ @@ -120,9 +134,13 @@ typedef int64_t s64; #define likely(_x) (_x) #define unlikely(_x) (_x) #else +#ifndef likely #define likely(_x) __builtin_expect(!!(_x), 1) +#endif +#ifndef unlikely #define unlikely(_x) __builtin_expect(!!(_x), 0) #endif +#endif #endif /* ! _HAVE_TYPES_H */ |