fixed potential double free in custom trim (#881)

This commit is contained in:
Dominik Maier
2021-04-30 13:35:24 +02:00
parent 758bc770a8
commit e9d2f72382
4 changed files with 29 additions and 14 deletions

View File

@ -1003,7 +1003,7 @@ void read_afl_environment(afl_state_t *, char **);
/* Custom mutators */ /* Custom mutators */
void setup_custom_mutators(afl_state_t *); void setup_custom_mutators(afl_state_t *);
void destroy_custom_mutators(afl_state_t *); void destroy_custom_mutators(afl_state_t *);
u8 trim_case_custom(afl_state_t *, struct queue_entry *q, u8 *in_buf, u8 trim_case_custom(afl_state_t *, struct queue_entry *q, u8 **in_buf,
struct custom_mutator *mutator); struct custom_mutator *mutator);
/* Python */ /* Python */
@ -1093,7 +1093,7 @@ fsrv_run_result_t fuzz_run_target(afl_state_t *, afl_forkserver_t *fsrv, u32);
void write_to_testcase(afl_state_t *, void *, u32); void write_to_testcase(afl_state_t *, void *, u32);
u8 calibrate_case(afl_state_t *, struct queue_entry *, u8 *, u32, u8); u8 calibrate_case(afl_state_t *, struct queue_entry *, u8 *, u32, u8);
void sync_fuzzers(afl_state_t *); void sync_fuzzers(afl_state_t *);
u8 trim_case(afl_state_t *, struct queue_entry *, u8 *); u8 trim_case(afl_state_t *, struct queue_entry *, u8 **);
u8 common_fuzz_stuff(afl_state_t *, u8 *, u32); u8 common_fuzz_stuff(afl_state_t *, u8 *, u32);
/* Fuzz one */ /* Fuzz one */

View File

@ -305,9 +305,13 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
} }
u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf, // Custom testcase trimming.
u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 **in_buf_p,
struct custom_mutator *mutator) { struct custom_mutator *mutator) {
// We need to pass pointers around, as growing testcases may need to realloc.
u8 *in_buf = *in_buf_p;
u8 needs_write = 0, fault = 0; u8 needs_write = 0, fault = 0;
u32 trim_exec = 0; u32 trim_exec = 0;
u32 orig_len = q->len; u32 orig_len = q->len;
@ -397,15 +401,22 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf,
if (likely(retlen && cksum == q->exec_cksum)) { if (likely(retlen && cksum == q->exec_cksum)) {
if (afl_realloc((void **)&in_buf, retlen) == NULL) { // Check if we got a new retbuf and to memcpy our buf.
if (in_buf != retbuf) {
if (afl_realloc((void **)in_buf_p, retlen) == NULL) {
FATAL("can not allocate memory for trim"); FATAL("can not allocate memory for trim");
} }
in_buf = *in_buf_p;
memcpy(in_buf, retbuf, retlen); memcpy(in_buf, retbuf, retlen);
q->len = retlen; q->len = retlen;
}
/* Let's save a clean trace, which will be needed by /* Let's save a clean trace, which will be needed by
update_bitmap_score once we're done with the trimming stuff. */ update_bitmap_score once we're done with the trimming stuff. */

View File

@ -508,7 +508,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
u32 old_len = afl->queue_cur->len; u32 old_len = afl->queue_cur->len;
u8 res = trim_case(afl, afl->queue_cur, in_buf); u8 res = trim_case(afl, afl->queue_cur, &in_buf);
orig_in = in_buf = queue_testcase_get(afl, afl->queue_cur); orig_in = in_buf = queue_testcase_get(afl, afl->queue_cur);
if (unlikely(res == FSRV_RUN_ERROR)) { if (unlikely(res == FSRV_RUN_ERROR)) {
@ -3007,16 +3007,16 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
u32 old_len = afl->queue_cur->len; u32 old_len = afl->queue_cur->len;
u8 res = trim_case(afl, afl->queue_cur, in_buf); u8 res = trim_case(afl, afl->queue_cur, &in_buf);
orig_in = in_buf = queue_testcase_get(afl, afl->queue_cur); orig_in = in_buf = queue_testcase_get(afl, afl->queue_cur);
if (res == FSRV_RUN_ERROR) { if (unlikely(res == FSRV_RUN_ERROR)) {
FATAL("Unable to execute target application"); FATAL("Unable to execute target application");
} }
if (afl->stop_soon) { if (unlikely(afl->stop_soon)) {
++afl->cur_skipped_paths; ++afl->cur_skipped_paths;
goto abandon_entry; goto abandon_entry;

View File

@ -720,7 +720,10 @@ void sync_fuzzers(afl_state_t *afl) {
trimmer uses power-of-two increments somewhere between 1/16 and 1/1024 of trimmer uses power-of-two increments somewhere between 1/16 and 1/1024 of
file size, to keep the stage short and sweet. */ file size, to keep the stage short and sweet. */
u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 **in_buf_p) {
// We need to pass pointers around, as growing testcases may need to realloc.
u8 *in_buf = *in_buf_p;
u32 orig_len = q->len; u32 orig_len = q->len;
@ -734,7 +737,8 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
if (el->afl_custom_trim) { if (el->afl_custom_trim) {
trimmed_case = trim_case_custom(afl, q, in_buf, el); trimmed_case = trim_case_custom(afl, q, in_buf_p, el);
in_buf = *in_buf_p;
custom_trimmed = true; custom_trimmed = true;
} }