From 5218c0b187dfeb2c722c41e3e0b3180d671c85ca Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 29 Mar 2023 22:53:15 +0200 Subject: all mutation strategies --- src/afl-fuzz-one.c | 571 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 368 insertions(+), 203 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 070669c5..3eed2b70 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2118,39 +2118,17 @@ havoc_stage: /* We essentially just do several thousand runs (depending on perf_score) where we take the input file and make random stacked tweaks. */ -#define MAX_HAVOC_ENTRY 64 -#define MUTATE_ASCII_DICT 64 +#define MAX_HAVOC_ENTRY 31 +#define MUTATE_ASCII_DICT 0 u32 r_max, r; - r_max = (MAX_HAVOC_ENTRY + 1) + (afl->extras_cnt ? 4 : 0) + - (afl->a_extras_cnt - ? (unlikely(afl->cmplog_binary && afl->queue_cur->is_ascii) - ? MUTATE_ASCII_DICT - : 4) - : 0); - - if (unlikely(afl->expand_havoc && afl->ready_for_splicing_count > 1)) { - - /* add expensive havoc cases here, they are activated after a full - cycle without finds happened */ - - r_max += 4; - - } - - if (unlikely(get_cur_time() - afl->last_find_time > 5000 /* 5 seconds */ && - afl->ready_for_splicing_count > 1)) { - - /* add expensive havoc cases here if there is no findings in the last 5s */ - - r_max += 4; - - } + r_max = (MAX_HAVOC_ENTRY + 1) + (afl->extras_cnt ? 2 : 0) + + (afl->a_extras_cnt ? 2 : 0); for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) { - u32 use_stacking = 1 << (1 + rand_below(afl, afl->havoc_stack_pow2)); + u32 use_stacking = 2 + rand_below(afl, 15), item; afl->stage_cur_val = use_stacking; @@ -2198,146 +2176,157 @@ havoc_stage: switch ((r = rand_below(afl, r_max))) { - case 0 ... 3: { + case 0: { /* Flip a single bit somewhere. Spooky! */ + u8 bit = rand_below(afl, 8); + u32 off = rand_below(afl, temp_len); + out_buf[off] ^= 1 << bit; #ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), " FLIP_BIT1"); + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " FLIP-BIT_%u", bit); strcat(afl->mutation, afl->m_tmp); #endif - FLIP_BIT(out_buf, rand_below(afl, temp_len << 3)); break; } - case 4 ... 7: { + case 1: { /* Set byte to interesting value. */ + item = rand_below(afl, sizeof(interesting_8)); #ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING8"); + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING8_%u", item); strcat(afl->mutation, afl->m_tmp); #endif - out_buf[rand_below(afl, temp_len)] = - interesting_8[rand_below(afl, sizeof(interesting_8))]; + out_buf[rand_below(afl, temp_len)] = interesting_8[item]; break; } - case 8 ... 9: { + case 2: { /* Set word to interesting value, little endian. */ if (temp_len < 2) { break; } + item = rand_below(afl, sizeof(interesting_16) >> 1); #ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING16"); + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING16_%u", item); strcat(afl->mutation, afl->m_tmp); #endif + *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) = - interesting_16[rand_below(afl, sizeof(interesting_16) >> 1)]; + interesting_16[item]; break; } - case 10 ... 11: { + case 3: { /* Set word to interesting value, big endian. */ if (temp_len < 2) { break; } + item = rand_below(afl, sizeof(interesting_16) >> 1); #ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING16BE"); + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING16BE_%u", item); strcat(afl->mutation, afl->m_tmp); #endif - *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) = SWAP16( - interesting_16[rand_below(afl, sizeof(interesting_16) >> 1)]); + *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) = + SWAP16(interesting_16[item]); break; } - case 12 ... 13: { + case 4: { /* Set dword to interesting value, little endian. */ if (temp_len < 4) { break; } + item = rand_below(afl, sizeof(interesting_32) >> 2); #ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING32"); + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING32_%u", item); strcat(afl->mutation, afl->m_tmp); #endif + *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) = - interesting_32[rand_below(afl, sizeof(interesting_32) >> 2)]; + interesting_32[item]; break; } - case 14 ... 15: { + case 5: { /* Set dword to interesting value, big endian. */ if (temp_len < 4) { break; } + item = rand_below(afl, sizeof(interesting_32) >> 2); #ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING32BE"); + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING32BE_%u", item); strcat(afl->mutation, afl->m_tmp); #endif - *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) = SWAP32( - interesting_32[rand_below(afl, sizeof(interesting_32) >> 2)]); + *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) = + SWAP32(interesting_32[item]); break; } - case 16 ... 19: { + case 6: { /* Randomly subtract from byte. */ + item = 1 + rand_below(afl, ARITH_MAX); #ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH8_"); + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH8-_%u", item); strcat(afl->mutation, afl->m_tmp); #endif - out_buf[rand_below(afl, temp_len)] -= 1 + rand_below(afl, ARITH_MAX); + out_buf[rand_below(afl, temp_len)] -= item; break; } - case 20 ... 23: { + case 7: { /* Randomly add to byte. */ + item = 1 + rand_below(afl, ARITH_MAX); #ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH8+"); + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH8+_%u", item); strcat(afl->mutation, afl->m_tmp); #endif - out_buf[rand_below(afl, temp_len)] += 1 + rand_below(afl, ARITH_MAX); + out_buf[rand_below(afl, temp_len)] += item; break; } - case 24 ... 25: { + case 8: { /* Randomly subtract from word, little endian. */ if (temp_len < 2) { break; } u32 pos = rand_below(afl, temp_len - 1); + item = 1 + rand_below(afl, ARITH_MAX); #ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16_-%u", pos); + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16-_%u", item); strcat(afl->mutation, afl->m_tmp); #endif - *(u16 *)(out_buf + pos) -= 1 + rand_below(afl, ARITH_MAX); + *(u16 *)(out_buf + pos) -= item; break; } - case 26 ... 27: { + case 9: { /* Randomly subtract from word, big endian. */ @@ -2347,8 +2336,7 @@ havoc_stage: u16 num = 1 + rand_below(afl, ARITH_MAX); #ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16_BE-%u_%u", pos, - num); + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16BE-_%u", num); strcat(afl->mutation, afl->m_tmp); #endif *(u16 *)(out_buf + pos) = @@ -2358,25 +2346,26 @@ havoc_stage: } - case 28 ... 29: { + case 10: { /* Randomly add to word, little endian. */ if (temp_len < 2) { break; } u32 pos = rand_below(afl, temp_len - 1); + item = 1 + rand_below(afl, ARITH_MAX); #ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16+-%u", pos); + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16+_%u", item); strcat(afl->mutation, afl->m_tmp); #endif - *(u16 *)(out_buf + pos) += 1 + rand_below(afl, ARITH_MAX); + *(u16 *)(out_buf + pos) += item; break; } - case 30 ... 31: { + case 11: { /* Randomly add to word, big endian. */ @@ -2386,8 +2375,7 @@ havoc_stage: u16 num = 1 + rand_below(afl, ARITH_MAX); #ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16+BE-%u_%u", pos, - num); + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16BE+__%u", num); strcat(afl->mutation, afl->m_tmp); #endif *(u16 *)(out_buf + pos) = @@ -2397,25 +2385,26 @@ havoc_stage: } - case 32 ... 33: { + case 12: { /* Randomly subtract from dword, little endian. */ if (temp_len < 4) { break; } u32 pos = rand_below(afl, temp_len - 3); + item = 1 + rand_below(afl, ARITH_MAX); #ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32_-%u", pos); + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32-_%u", item); strcat(afl->mutation, afl->m_tmp); #endif - *(u32 *)(out_buf + pos) -= 1 + rand_below(afl, ARITH_MAX); + *(u32 *)(out_buf + pos) -= item; break; } - case 34 ... 35: { + case 13: { /* Randomly subtract from dword, big endian. */ @@ -2425,8 +2414,7 @@ havoc_stage: u32 num = 1 + rand_below(afl, ARITH_MAX); #ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32_BE-%u-%u", pos, - num); + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32BE-_%u", num); strcat(afl->mutation, afl->m_tmp); #endif *(u32 *)(out_buf + pos) = @@ -2436,25 +2424,26 @@ havoc_stage: } - case 36 ... 37: { + case 14: { /* Randomly add to dword, little endian. */ if (temp_len < 4) { break; } u32 pos = rand_below(afl, temp_len - 3); + item = 1 + rand_below(afl, ARITH_MAX); #ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32+-%u", pos); + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32+_%u", item); strcat(afl->mutation, afl->m_tmp); #endif - *(u32 *)(out_buf + pos) += 1 + rand_below(afl, ARITH_MAX); + *(u32 *)(out_buf + pos) += item; break; } - case 38 ... 39: { + case 15: { /* Randomly add to dword, big endian. */ @@ -2464,8 +2453,7 @@ havoc_stage: u32 num = 1 + rand_below(afl, ARITH_MAX); #ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32+BE-%u-%u", pos, - num); + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32BE+_%u", num); strcat(afl->mutation, afl->m_tmp); #endif *(u32 *)(out_buf + pos) = @@ -2475,22 +2463,25 @@ havoc_stage: } - case 40 ... 43: { + case 16: { /* Just set a random byte to a random value. Because, why not. We use XOR with 1-255 to eliminate the possibility of a no-op. */ + u32 pos = rand_below(afl, temp_len); + item = 1 + rand_below(afl, 255); #ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), " RAND8"); + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " RAND8_%u", + out_buf[pos] ^ item); strcat(afl->mutation, afl->m_tmp); #endif - out_buf[rand_below(afl, temp_len)] ^= 1 + rand_below(afl, 255); + out_buf[pos] ^= item; break; } - case 44 ... 46: { + case 17: { if (temp_len + HAVOC_BLK_XL < MAX_FILE) { @@ -2501,8 +2492,8 @@ havoc_stage: u32 clone_to = rand_below(afl, temp_len); #ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), " CLONE-%s-%u-%u-%u", - "clone", clone_from, clone_to, clone_len); + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " CLONE-%s_%u_%u_%u", + "overwrite", clone_from, clone_to, clone_len); strcat(afl->mutation, afl->m_tmp); #endif u8 *new_buf = @@ -2531,7 +2522,7 @@ havoc_stage: } - case 47: { + case 18: { if (temp_len + HAVOC_BLK_XL < MAX_FILE) { @@ -2539,10 +2530,13 @@ havoc_stage: u32 clone_len = choose_block_len(afl, HAVOC_BLK_XL); u32 clone_to = rand_below(afl, temp_len); + u32 strat = rand_below(afl, 2); + u32 clone_from = clone_to ? clone_to - 1 : 0; + item = strat ? rand_below(afl, 256) : out_buf[clone_from]; #ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), " CLONE-%s-%u-%u", - "insert", clone_to, clone_len); + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " CLONE-%s_%u_%u_%u", + "insert", strat, clone_to, clone_len); strcat(afl->mutation, afl->m_tmp); #endif u8 *new_buf = @@ -2555,10 +2549,7 @@ havoc_stage: /* Inserted part */ - memset(new_buf + clone_to, - rand_below(afl, 2) ? rand_below(afl, 256) - : out_buf[rand_below(afl, temp_len)], - clone_len); + memset(new_buf + clone_to, item, clone_len); /* Tail */ memcpy(new_buf + clone_to + clone_len, out_buf + clone_to, @@ -2574,7 +2565,7 @@ havoc_stage: } - case 48 ... 50: { + case 19: { /* Overwrite bytes with a randomly selected chunk bytes. */ @@ -2587,7 +2578,7 @@ havoc_stage: if (likely(copy_from != copy_to)) { #ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), " OVERWRITE_COPY-%u-%u-%u", + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " OVERWRITE-COPY_%u_%u_%u", copy_from, copy_to, copy_len); strcat(afl->mutation, afl->m_tmp); #endif @@ -2599,7 +2590,7 @@ havoc_stage: } - case 51: { + case 20: { /* Overwrite bytes with fixed bytes. */ @@ -2607,27 +2598,28 @@ havoc_stage: u32 copy_len = choose_block_len(afl, temp_len - 1); u32 copy_to = rand_below(afl, temp_len - copy_len + 1); + u32 strat = rand_below(afl, 2); + u32 copy_from = copy_to ? copy_to - 1 : 0; + item = strat ? rand_below(afl, 256) : out_buf[copy_from]; #ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), " OVERWRITE_FIXED-%u-%u", - copy_to, copy_len); + snprintf(afl->m_tmp, sizeof(afl->m_tmp), + " OVERWRITE-FIXED_%u_%u_%u-%u", strat, item, copy_to, + copy_len); strcat(afl->mutation, afl->m_tmp); #endif - memset(out_buf + copy_to, - rand_below(afl, 2) ? rand_below(afl, 256) - : out_buf[rand_below(afl, temp_len)], - copy_len); + memset(out_buf + copy_to, item, copy_len); break; } - case 52: { + case 21: { /* Increase byte by 1. */ #ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ADDBYTE_"); + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " BYTEADD_"); strcat(afl->mutation, afl->m_tmp); #endif out_buf[rand_below(afl, temp_len)]++; @@ -2635,12 +2627,12 @@ havoc_stage: } - case 53: { + case 22: { /* Decrease byte by 1. */ #ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), " SUBBYTE_"); + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " BYTESUB_"); strcat(afl->mutation, afl->m_tmp); #endif out_buf[rand_below(afl, temp_len)]--; @@ -2648,7 +2640,7 @@ havoc_stage: } - case 54: { + case 23: { /* Flip byte. */ @@ -2661,7 +2653,7 @@ havoc_stage: } - case 55 ... 56: { + case 24: { if (temp_len < 4) { break; } @@ -2690,7 +2682,7 @@ havoc_stage: switch_len = choose_block_len(afl, MIN(switch_len, to_end)); #ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), " SWITCH-%s-%u-%u-%u", + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " SWITCH-%s_%u_%u_%u", "switch", switch_from, switch_to, switch_len); strcat(afl->mutation, afl->m_tmp); #endif @@ -2714,7 +2706,7 @@ havoc_stage: } // MAX_HAVOC_ENTRY = 64 - case 57 ... MAX_HAVOC_ENTRY: { + case 25: { /* Delete bytes. */ @@ -2726,7 +2718,7 @@ havoc_stage: u32 del_from = rand_below(afl, temp_len - del_len + 1); #ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), " DEL-%u-%u", del_from, + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " DEL_%u_%u", del_from, del_len); strcat(afl->mutation, afl->m_tmp); #endif @@ -2739,13 +2731,274 @@ havoc_stage: } + case 26: { + + /* Shuffle bytes. */ + + if (temp_len < 4) { break; } + + u32 len = choose_block_len(afl, temp_len - 1); + u32 off = rand_below(afl, temp_len - len + 1); + +#ifdef INTROSPECTION + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " SHUFFLE_%u", len); + strcat(afl->mutation, afl->m_tmp); +#endif + + for (u32 i = len - 1; i > 0; i--) { + + u32 j; + do { + + j = rand_below(afl, i + 1); + + } while (i == j); + + unsigned char temp = out_buf[off + i]; + out_buf[off + i] = out_buf[off + j]; + out_buf[off + j] = temp; + + } + + break; + + } + + case 27: { + + /* Delete bytes. */ + + if (temp_len < 2) { break; } + + /* Don't delete too much. */ + + u32 del_len = 1; + u32 del_from = rand_below(afl, temp_len - del_len + 1); + +#ifdef INTROSPECTION + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " DELONE_%u", del_from); + strcat(afl->mutation, afl->m_tmp); +#endif + memmove(out_buf + del_from, out_buf + del_from + del_len, + temp_len - del_from - del_len); + + temp_len -= del_len; + + break; + + } + + case 28: { + + u32 clone_len = 1; + u32 clone_to = rand_below(afl, temp_len); + u32 strat = rand_below(afl, 2); + u32 clone_from = clone_to ? clone_to - 1 : 0; + item = strat ? rand_below(afl, 256) : out_buf[clone_from]; + +#ifdef INTROSPECTION + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INSERTONE_%u_%u", strat, + clone_to); + strcat(afl->mutation, afl->m_tmp); +#endif + u8 *new_buf = + afl_realloc(AFL_BUF_PARAM(out_scratch), temp_len + clone_len); + if (unlikely(!new_buf)) { PFATAL("alloc"); } + + /* Head */ + + memcpy(new_buf, out_buf, clone_to); + + /* Inserted part */ + + memset(new_buf + clone_to, item, clone_len); + + /* Tail */ + memcpy(new_buf + clone_to + clone_len, out_buf + clone_to, + temp_len - clone_to); + + out_buf = new_buf; + afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch)); + temp_len += clone_len; + + break; + + } + + case 29: { + + if (temp_len < 4) { break; } + + u32 off = rand_below(afl, temp_len), off2 = off, cnt = 0; + + while (off2 + cnt < temp_len && !isdigit(out_buf[off2 + cnt])) { + + ++cnt; + + } + + // none found, wrap + if (off2 + cnt == temp_len) { + + off2 = 0; + cnt = 0; + + while (cnt < off && !isdigit(out_buf[off2 + cnt])) { + + ++cnt; + + } + + if (cnt == off) { break; } + + } + + off = off2 + cnt; + off2 = off + 1; + + while (off2 < temp_len && isdigit(out_buf[off2])) { + + ++off2; + + } + + s64 val = out_buf[off] - '0'; + for (u32 i = off + 1; i < off2; ++i) { + + val = (val * 10) + out_buf[i] - '0'; + + } + + if (off && out_buf[off - 1] == '-') { val = -val; } + + u32 strat = rand_below(afl, 8); + switch (strat) { + + case 0: + val++; + break; + case 1: + val--; + break; + case 2: + val *= 2; + break; + case 3: + val /= 2; + break; + case 4: + if (val) { + + val = rand_next(afl) % (val * 10); + + } else { + + val = rand_below(afl, 256); + + } + + break; + case 5: + val += rand_below(afl, 256); + break; + case 6: + val -= rand_below(afl, 256); + break; + case 7: + val = ~(val); + break; + + } + +#ifdef INTROSPECTION + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ASCIINUM_%u_%u_%u", + afl->queue_cur->is_ascii, strat, off); + strcat(afl->mutation, afl->m_tmp); +#endif + // fprintf(stderr, "val: %u-%u = %ld\n", off, off2, val); + + char buf[20]; + snprintf(buf, sizeof(buf), "%ld", val); + + // fprintf(stderr, "BEFORE: %s\n", out_buf); + + u32 old_len = off2 - off; + u32 new_len = strlen(buf); + + if (old_len == new_len) { + + memcpy(out_buf + off, buf, new_len); + + } else { + + u8 *new_buf = afl_realloc(AFL_BUF_PARAM(out_scratch), + temp_len + new_len - old_len); + if (unlikely(!new_buf)) { PFATAL("alloc"); } + + /* Head */ + + memcpy(new_buf, out_buf, off); + + /* Inserted part */ + + memcpy(new_buf + off, buf, new_len); + + /* Tail */ + memcpy(new_buf + off + new_len, out_buf + off2, temp_len - off2); + + out_buf = new_buf; + afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch)); + temp_len += (new_len - old_len); + + } + + // fprintf(stderr, "AFTER : %s\n", out_buf); + break; + + } + + case 30: { + + /* Neg byte. */ + +#ifdef INTROSPECTION + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " NEG_"); + strcat(afl->mutation, afl->m_tmp); +#endif + item = rand_below(afl, temp_len); + + out_buf[item] = ~out_buf[item]; + break; + + } + + case 31: { + + u32 len = 1 + rand_below(afl, 8); + u32 pos = rand_below(afl, temp_len); + /* Insert ascii number. */ + if (temp_len < pos + len) { break; } + +#ifdef INTROSPECTION + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INSERTASCIINUM_"); + strcat(afl->mutation, afl->m_tmp); +#endif + u64 val = rand_next(afl); + char buf[20]; + snprintf(buf, sizeof(buf), "%llu", val); + memcpy(out_buf + pos, buf, len); + + break; + + } + default: r -= (MAX_HAVOC_ENTRY + 1); if (afl->extras_cnt) { - if (r < 2) { + if (r < 1) { /* Use the dictionary. */ @@ -2765,7 +3018,7 @@ havoc_stage: break; - } else if (r < 4) { + } else if (r < 2) { u32 use_extra = rand_below(afl, afl->extras_cnt); u32 extra_len = afl->extras[use_extra].len; @@ -2794,7 +3047,7 @@ havoc_stage: } else { - r -= 4; + r -= 2; } @@ -2802,15 +3055,7 @@ havoc_stage: if (afl->a_extras_cnt) { - u32 r_cmp = 2; - - if (unlikely(afl->cmplog_binary && afl->queue_cur->is_ascii)) { - - r_cmp = MUTATE_ASCII_DICT >> 1; - - } - - if (r < r_cmp) { + if (r < 1) { /* Use the dictionary. */ @@ -2830,7 +3075,7 @@ havoc_stage: break; - } else if (r < (r_cmp << 1)) { + } else if (r < 2) { u32 use_extra = rand_below(afl, afl->a_extras_cnt); u32 extra_len = afl->a_extras[use_extra].len; @@ -2859,92 +3104,12 @@ havoc_stage: } else { - r -= (r_cmp << 1); + r -= 2; } } - /* Splicing otherwise if we are still here. - Overwrite bytes with a randomly selected chunk from another - testcase or insert that chunk. */ - - /* Pick a random queue entry and seek to it. */ - - u32 tid; - do { - - tid = rand_below(afl, afl->queued_items); - - } while (tid == afl->current_entry || afl->queue_buf[tid]->len < 4); - - /* Get the testcase for splicing. */ - struct queue_entry *target = afl->queue_buf[tid]; - u32 new_len = target->len; - u8 *new_buf = queue_testcase_get(afl, target); - - if ((temp_len >= 2 && r % 2) || temp_len + HAVOC_BLK_XL >= MAX_FILE) { - - /* overwrite mode */ - - u32 copy_from, copy_to, copy_len; - - copy_len = choose_block_len(afl, new_len - 1); - if (copy_len > temp_len) copy_len = temp_len; - - copy_from = rand_below(afl, new_len - copy_len + 1); - copy_to = rand_below(afl, temp_len - copy_len + 1); - -#ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), - " SPLICE_OVERWRITE-%u-%u-%u-%s", copy_from, copy_to, - copy_len, target->fname); - strcat(afl->mutation, afl->m_tmp); -#endif - memmove(out_buf + copy_to, new_buf + copy_from, copy_len); - - } else { - - /* insert mode */ - - u32 clone_from, clone_to, clone_len; - - clone_len = choose_block_len(afl, new_len); - clone_from = rand_below(afl, new_len - clone_len + 1); - clone_to = rand_below(afl, temp_len + 1); - - u8 *temp_buf = afl_realloc(AFL_BUF_PARAM(out_scratch), - temp_len + clone_len + 1); - if (unlikely(!temp_buf)) { PFATAL("alloc"); } - -#ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), - " SPLICE_INSERT-%u-%u-%u-%s", clone_from, clone_to, - clone_len, target->fname); - strcat(afl->mutation, afl->m_tmp); -#endif - /* Head */ - - memcpy(temp_buf, out_buf, clone_to); - - /* Inserted part */ - - memcpy(temp_buf + clone_to, new_buf + clone_from, clone_len); - - /* Tail */ - memcpy(temp_buf + clone_to + clone_len, out_buf + clone_to, - temp_len - clone_to); - - out_buf = temp_buf; - afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch)); - temp_len += clone_len; - - } - - break; - - // end of default - } } -- cgit v1.2.3 From 7893347e13d99b7e39ec4ebb95fbb5356bdd7f2b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 29 Mar 2023 22:56:12 +0200 Subject: final touches --- src/afl-fuzz-one.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 3eed2b70..e3ec8267 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2133,8 +2133,8 @@ havoc_stage: afl->stage_cur_val = use_stacking; #ifdef INTROSPECTION - snprintf(afl->mutation, sizeof(afl->mutation), "%s HAVOC-%u", - afl->queue_cur->fname, use_stacking); + snprintf(afl->mutation, sizeof(afl->mutation), "%s HAVOC-%u-%u", + afl->queue_cur->fname, afl->queue_cur->is_ascii, use_stacking); #endif for (i = 0; i < use_stacking; ++i) { -- cgit v1.2.3 From 145748a7e0b85c34660d0fe72ef1d4499ace2933 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 30 Mar 2023 14:00:45 +0200 Subject: prepare new mutation strategies --- src/afl-fuzz-one.c | 178 ++++++++++++++++++++++++++++------------------------- 1 file changed, 94 insertions(+), 84 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index e3ec8267..b1c38572 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -28,6 +28,21 @@ #include #include "cmplog.h" +static u32 mutation_array_explore[] = { + + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; +// static u32 mutation_array_exploit[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, +// 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, +// 31 }; static u32 mutation_array_txt_explore[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, +// 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, +// 28, 29, 30, 31 }; static u32 mutation_array_txt_exploit[] = { 0, 1, 2, 3, 4, +// 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, +// 25, 26, 27, 28, 29, 30, 31 }; + +// what about more splicing? +// what about -x and cmplog learn? + /* MOpt */ static int select_algorithm(afl_state_t *afl, u32 max_algorithm) { @@ -2121,10 +2136,15 @@ havoc_stage: #define MAX_HAVOC_ENTRY 31 #define MUTATE_ASCII_DICT 0 - u32 r_max, r; + u32 r_max, mutation_array_len; + u32 **mutation_array; - r_max = (MAX_HAVOC_ENTRY + 1) + (afl->extras_cnt ? 2 : 0) + - (afl->a_extras_cnt ? 2 : 0); + // if ( ... ) + mutation_array = (u32 **)&mutation_array_explore; + mutation_array_len = sizeof(mutation_array_explore) + 1; + + r_max = mutation_array_len; + // + (afl->extras_cnt ? 2 : 0) + (afl->a_extras_cnt ? 2 : 0); for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) { @@ -2174,7 +2194,7 @@ havoc_stage: } - switch ((r = rand_below(afl, r_max))) { + switch (*mutation_array[rand_below(afl, r_max)]) { case 0: { @@ -2992,123 +3012,113 @@ havoc_stage: } - default: - - r -= (MAX_HAVOC_ENTRY + 1); - - if (afl->extras_cnt) { + case 32: { - if (r < 1) { + if (!afl->extras_cnt) { break; } - /* Use the dictionary. */ + /* Use the dictionary. */ - u32 use_extra = rand_below(afl, afl->extras_cnt); - u32 extra_len = afl->extras[use_extra].len; + u32 use_extra = rand_below(afl, afl->extras_cnt); + u32 extra_len = afl->extras[use_extra].len; - if (extra_len > temp_len) { break; } + if (extra_len > temp_len) { break; } - u32 insert_at = rand_below(afl, temp_len - extra_len + 1); + u32 insert_at = rand_below(afl, temp_len - extra_len + 1); #ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), " EXTRA_OVERWRITE-%u-%u", - insert_at, extra_len); - strcat(afl->mutation, afl->m_tmp); + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " EXTRA-OVERWRITE_%u_%u", + insert_at, extra_len); + strcat(afl->mutation, afl->m_tmp); #endif - memcpy(out_buf + insert_at, afl->extras[use_extra].data, - extra_len); + memcpy(out_buf + insert_at, afl->extras[use_extra].data, extra_len); - break; + break; - } else if (r < 2) { + } - u32 use_extra = rand_below(afl, afl->extras_cnt); - u32 extra_len = afl->extras[use_extra].len; - if (temp_len + extra_len >= MAX_FILE) { break; } + case 33: { - u8 *ptr = afl->extras[use_extra].data; - u32 insert_at = rand_below(afl, temp_len + 1); -#ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), " EXTRA_INSERT-%u-%u", - insert_at, extra_len); - strcat(afl->mutation, afl->m_tmp); -#endif + if (!afl->extras_cnt) { break; } - out_buf = afl_realloc(AFL_BUF_PARAM(out), temp_len + extra_len); - if (unlikely(!out_buf)) { PFATAL("alloc"); } + u32 use_extra = rand_below(afl, afl->extras_cnt); + u32 extra_len = afl->extras[use_extra].len; + if (temp_len + extra_len >= MAX_FILE) { break; } - /* Tail */ - memmove(out_buf + insert_at + extra_len, out_buf + insert_at, - temp_len - insert_at); + u8 *ptr = afl->extras[use_extra].data; + u32 insert_at = rand_below(afl, temp_len + 1); +#ifdef INTROSPECTION + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " EXTRA-INSERT_%u_%u", + insert_at, extra_len); + strcat(afl->mutation, afl->m_tmp); +#endif - /* Inserted part */ - memcpy(out_buf + insert_at, ptr, extra_len); - temp_len += extra_len; + out_buf = afl_realloc(AFL_BUF_PARAM(out), temp_len + extra_len); + if (unlikely(!out_buf)) { PFATAL("alloc"); } - break; - - } else { + /* Tail */ + memmove(out_buf + insert_at + extra_len, out_buf + insert_at, + temp_len - insert_at); - r -= 2; + /* Inserted part */ + memcpy(out_buf + insert_at, ptr, extra_len); + temp_len += extra_len; - } + break; - } + } - if (afl->a_extras_cnt) { + case 34: { - if (r < 1) { + if (!afl->a_extras_cnt) { break; } - /* Use the dictionary. */ + /* Use the dictionary. */ - u32 use_extra = rand_below(afl, afl->a_extras_cnt); - u32 extra_len = afl->a_extras[use_extra].len; + u32 use_extra = rand_below(afl, afl->a_extras_cnt); + u32 extra_len = afl->a_extras[use_extra].len; - if (extra_len > temp_len) { break; } + if (extra_len > temp_len) { break; } - u32 insert_at = rand_below(afl, temp_len - extra_len + 1); + u32 insert_at = rand_below(afl, temp_len - extra_len + 1); #ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), - " AUTO_EXTRA_OVERWRITE-%u-%u", insert_at, extra_len); - strcat(afl->mutation, afl->m_tmp); + snprintf(afl->m_tmp, sizeof(afl->m_tmp), + " AUTO-EXTRA-OVERWRITE_%u_%u", insert_at, extra_len); + strcat(afl->mutation, afl->m_tmp); #endif - memcpy(out_buf + insert_at, afl->a_extras[use_extra].data, - extra_len); + memcpy(out_buf + insert_at, afl->a_extras[use_extra].data, extra_len); - break; - - } else if (r < 2) { + break; - u32 use_extra = rand_below(afl, afl->a_extras_cnt); - u32 extra_len = afl->a_extras[use_extra].len; - if (temp_len + extra_len >= MAX_FILE) { break; } + } - u8 *ptr = afl->a_extras[use_extra].data; - u32 insert_at = rand_below(afl, temp_len + 1); -#ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), - " AUTO_EXTRA_INSERT-%u-%u", insert_at, extra_len); - strcat(afl->mutation, afl->m_tmp); -#endif + case 35: { - out_buf = afl_realloc(AFL_BUF_PARAM(out), temp_len + extra_len); - if (unlikely(!out_buf)) { PFATAL("alloc"); } + if (!afl->a_extras_cnt) { break; } - /* Tail */ - memmove(out_buf + insert_at + extra_len, out_buf + insert_at, - temp_len - insert_at); + u32 use_extra = rand_below(afl, afl->a_extras_cnt); + u32 extra_len = afl->a_extras[use_extra].len; + if (temp_len + extra_len >= MAX_FILE) { break; } - /* Inserted part */ - memcpy(out_buf + insert_at, ptr, extra_len); - temp_len += extra_len; + u8 *ptr = afl->a_extras[use_extra].data; + u32 insert_at = rand_below(afl, temp_len + 1); +#ifdef INTROSPECTION + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " AUTO-EXTRA-INSERT_%u_%u", + insert_at, extra_len); + strcat(afl->mutation, afl->m_tmp); +#endif - break; + out_buf = afl_realloc(AFL_BUF_PARAM(out), temp_len + extra_len); + if (unlikely(!out_buf)) { PFATAL("alloc"); } - } else { + /* Tail */ + memmove(out_buf + insert_at + extra_len, out_buf + insert_at, + temp_len - insert_at); - r -= 2; + /* Inserted part */ + memcpy(out_buf + insert_at, ptr, extra_len); + temp_len += extra_len; - } + break; - } + } } -- cgit v1.2.3 From 506f6b134987d47da6c1a2e172f50b47559e7b4f Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 30 Mar 2023 19:28:59 +0200 Subject: nits --- src/afl-fuzz-one.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++--- src/afl-fuzz-queue.c | 2 +- 2 files changed, 99 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index b1c38572..36259d9b 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -30,8 +30,8 @@ static u32 mutation_array_explore[] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37}; // static u32 mutation_array_exploit[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, // 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, // 31 }; static u32 mutation_array_txt_explore[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, @@ -2133,9 +2133,6 @@ havoc_stage: /* We essentially just do several thousand runs (depending on perf_score) where we take the input file and make random stacked tweaks. */ -#define MAX_HAVOC_ENTRY 31 -#define MUTATE_ASCII_DICT 0 - u32 r_max, mutation_array_len; u32 **mutation_array; @@ -2725,7 +2722,6 @@ havoc_stage: } - // MAX_HAVOC_ENTRY = 64 case 25: { /* Delete bytes. */ @@ -3120,6 +3116,102 @@ havoc_stage: } + case 36: { + + if (afl->ready_for_splicing_count <= 1) { break; } + + /* Pick a random queue entry and seek to it. */ + + u32 tid; + do { + + tid = rand_below(afl, afl->queued_items); + + } while (tid == afl->current_entry || afl->queue_buf[tid]->len < 4); + + /* Get the testcase for splicing. */ + struct queue_entry *target = afl->queue_buf[tid]; + u32 new_len = target->len; + u8 *new_buf = queue_testcase_get(afl, target); + + /* overwrite mode */ + + u32 copy_from, copy_to, copy_len; + + copy_len = choose_block_len(afl, new_len - 1); + if (copy_len > temp_len) copy_len = temp_len; + + copy_from = rand_below(afl, new_len - copy_len + 1); + copy_to = rand_below(afl, temp_len - copy_len + 1); + +#ifdef INTROSPECTION + snprintf(afl->m_tmp, sizeof(afl->m_tmp), + " SPLICE-OVERWRITE_%u_%u_%u_%s", copy_from, copy_to, + copy_len, target->fname); + strcat(afl->mutation, afl->m_tmp); +#endif + memmove(out_buf + copy_to, new_buf + copy_from, copy_len); + + break; + + } + + case 37: { + + if (afl->ready_for_splicing_count <= 1) { break; } + if (temp_len + HAVOC_BLK_XL >= MAX_FILE) { break; } + + /* Pick a random queue entry and seek to it. */ + + u32 tid; + do { + + tid = rand_below(afl, afl->queued_items); + + } while (tid == afl->current_entry || afl->queue_buf[tid]->len < 4); + + /* Get the testcase for splicing. */ + struct queue_entry *target = afl->queue_buf[tid]; + u32 new_len = target->len; + u8 *new_buf = queue_testcase_get(afl, target); + + /* insert mode */ + + u32 clone_from, clone_to, clone_len; + + clone_len = choose_block_len(afl, new_len); + clone_from = rand_below(afl, new_len - clone_len + 1); + clone_to = rand_below(afl, temp_len + 1); + + u8 *temp_buf = + afl_realloc(AFL_BUF_PARAM(out_scratch), temp_len + clone_len + 1); + if (unlikely(!temp_buf)) { PFATAL("alloc"); } + +#ifdef INTROSPECTION + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " SPLICE-INSERT_%u_%u_%u_%s", + clone_from, clone_to, clone_len, target->fname); + strcat(afl->mutation, afl->m_tmp); +#endif + /* Head */ + + memcpy(temp_buf, out_buf, clone_to); + + /* Inserted part */ + + memcpy(temp_buf + clone_to, new_buf + clone_from, clone_len); + + /* Tail */ + memcpy(temp_buf + clone_to + clone_len, out_buf + clone_to, + temp_len - clone_to); + + out_buf = temp_buf; + afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch)); + temp_len += clone_len; + + break; + + } + } } diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 40184645..fff8db03 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -563,7 +563,7 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { } - if (likely(q->len > 4)) afl->ready_for_splicing_count++; + if (likely(q->len > 4)) { ++afl->ready_for_splicing_count; } ++afl->queued_items; ++afl->active_items; -- cgit v1.2.3 From 74baebd93e6ad65de297e812d53f06592166ef9a Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 30 Mar 2023 20:02:59 +0200 Subject: fix --- src/afl-fuzz-one.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 36259d9b..fc37d493 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2134,11 +2134,11 @@ havoc_stage: where we take the input file and make random stacked tweaks. */ u32 r_max, mutation_array_len; - u32 **mutation_array; + u32 *mutation_array; // if ( ... ) mutation_array = (u32 **)&mutation_array_explore; - mutation_array_len = sizeof(mutation_array_explore) + 1; + mutation_array_len = sizeof(mutation_array_explore) / 4; r_max = mutation_array_len; // + (afl->extras_cnt ? 2 : 0) + (afl->a_extras_cnt ? 2 : 0); @@ -2191,7 +2191,8 @@ havoc_stage: } - switch (*mutation_array[rand_below(afl, r_max)]) { + u32 r = rand_below(afl, r_max); + switch (mutation_array[r]) { case 0: { -- cgit v1.2.3 From 8f17c816919301b870b9c7dad84e475370c87381 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 30 Mar 2023 22:41:02 +0200 Subject: less mutation --- src/afl-fuzz-one.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index fc37d493..b01814a3 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2145,7 +2145,7 @@ havoc_stage: for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) { - u32 use_stacking = 2 + rand_below(afl, 15), item; + u32 use_stacking = 1 + rand_below(afl, 8), item; afl->stage_cur_val = use_stacking; -- cgit v1.2.3 From 9eed60d1055ada484798d6de51101043ecaf462d Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 31 Mar 2023 08:12:32 +0200 Subject: nit --- src/afl-fuzz-one.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index b01814a3..1a120733 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2137,7 +2137,7 @@ havoc_stage: u32 *mutation_array; // if ( ... ) - mutation_array = (u32 **)&mutation_array_explore; + mutation_array = (u32 *)&mutation_array_explore; mutation_array_len = sizeof(mutation_array_explore) / 4; r_max = mutation_array_len; @@ -2192,6 +2192,7 @@ havoc_stage: } u32 r = rand_below(afl, r_max); + switch (mutation_array[r]) { case 0: { -- cgit v1.2.3 From 21203c2ea6b0586d3c63f9d33190dfd364677b1a Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 2 Apr 2023 12:39:02 +0200 Subject: fix --- src/afl-fuzz-one.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 1a120733..c550fbc2 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2905,7 +2905,7 @@ havoc_stage: val /= 2; break; case 4: - if (val) { + if (val && val < 0xfffffff) { val = rand_next(afl) % (val * 10); -- cgit v1.2.3 From 71e2aa5d2bb99bd7edc2efcebd52eee5736c35fd Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 2 Apr 2023 13:42:08 +0200 Subject: more fix --- src/afl-fuzz-one.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index c550fbc2..a52fb4c6 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2133,7 +2133,7 @@ havoc_stage: /* We essentially just do several thousand runs (depending on perf_score) where we take the input file and make random stacked tweaks. */ - u32 r_max, mutation_array_len; + u32 r_max, mutation_array_len; u32 *mutation_array; // if ( ... ) @@ -2905,9 +2905,9 @@ havoc_stage: val /= 2; break; case 4: - if (val && val < 0xfffffff) { + if (val && (u64)val < 0x19999999) { - val = rand_next(afl) % (val * 10); + val = (u64)rand_next(afl) % (u64)((u64)val * 10); } else { -- cgit v1.2.3 From 635da39bd135b7db3529a4b3b059b85260ce14a5 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 3 Apr 2023 14:41:52 +0200 Subject: preparation for mutation arrays --- src/afl-fuzz-one.c | 176 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 131 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index a52fb4c6..1636c323 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2133,19 +2133,35 @@ havoc_stage: /* We essentially just do several thousand runs (depending on perf_score) where we take the input file and make random stacked tweaks. */ - u32 r_max, mutation_array_len; u32 *mutation_array; + u32 stack_max; // if ( ... ) mutation_array = (u32 *)&mutation_array_explore; - mutation_array_len = sizeof(mutation_array_explore) / 4; - r_max = mutation_array_len; + if (temp_len < 64) { + + stack_max = 4; + + } else if (temp_len < 512) { + + stack_max = 8; + + } else if (temp_len < 8096) { + + stack_max = 16; + + } else { + + stack_max = 32; + + } + // + (afl->extras_cnt ? 2 : 0) + (afl->a_extras_cnt ? 2 : 0); for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) { - u32 use_stacking = 1 + rand_below(afl, 8), item; + u32 use_stacking = 1 + rand_below(afl, stack_max); afl->stage_cur_val = use_stacking; @@ -2191,7 +2207,8 @@ havoc_stage: } - u32 r = rand_below(afl, r_max); + retry_havoc_step: + u32 r = rand_below(afl, 256), item; switch (mutation_array[r]) { @@ -2228,7 +2245,7 @@ havoc_stage: /* Set word to interesting value, little endian. */ - if (temp_len < 2) { break; } + if (unlikely(temp_len < 2)) { break; } // no retry item = rand_below(afl, sizeof(interesting_16) >> 1); #ifdef INTROSPECTION @@ -2247,7 +2264,7 @@ havoc_stage: /* Set word to interesting value, big endian. */ - if (temp_len < 2) { break; } + if (unlikely(temp_len < 2)) { break; } // no retry item = rand_below(afl, sizeof(interesting_16) >> 1); #ifdef INTROSPECTION @@ -2265,7 +2282,7 @@ havoc_stage: /* Set dword to interesting value, little endian. */ - if (temp_len < 4) { break; } + if (unlikely(temp_len < 4)) { break; } // no retry item = rand_below(afl, sizeof(interesting_32) >> 2); #ifdef INTROSPECTION @@ -2284,7 +2301,7 @@ havoc_stage: /* Set dword to interesting value, big endian. */ - if (temp_len < 4) { break; } + if (unlikely(temp_len < 4)) { break; } // no retry item = rand_below(afl, sizeof(interesting_32) >> 2); #ifdef INTROSPECTION @@ -2330,7 +2347,7 @@ havoc_stage: /* Randomly subtract from word, little endian. */ - if (temp_len < 2) { break; } + if (unlikely(temp_len < 2)) { break; } // no retry u32 pos = rand_below(afl, temp_len - 1); item = 1 + rand_below(afl, ARITH_MAX); @@ -2349,7 +2366,7 @@ havoc_stage: /* Randomly subtract from word, big endian. */ - if (temp_len < 2) { break; } + if (unlikely(temp_len < 2)) { break; } // no retry u32 pos = rand_below(afl, temp_len - 1); u16 num = 1 + rand_below(afl, ARITH_MAX); @@ -2369,7 +2386,7 @@ havoc_stage: /* Randomly add to word, little endian. */ - if (temp_len < 2) { break; } + if (unlikely(temp_len < 2)) { break; } // no retry u32 pos = rand_below(afl, temp_len - 1); item = 1 + rand_below(afl, ARITH_MAX); @@ -2388,7 +2405,7 @@ havoc_stage: /* Randomly add to word, big endian. */ - if (temp_len < 2) { break; } + if (unlikely(temp_len < 2)) { break; } // no retry u32 pos = rand_below(afl, temp_len - 1); u16 num = 1 + rand_below(afl, ARITH_MAX); @@ -2408,7 +2425,7 @@ havoc_stage: /* Randomly subtract from dword, little endian. */ - if (temp_len < 4) { break; } + if (unlikely(temp_len < 4)) { break; } // no retry u32 pos = rand_below(afl, temp_len - 3); item = 1 + rand_below(afl, ARITH_MAX); @@ -2427,7 +2444,7 @@ havoc_stage: /* Randomly subtract from dword, big endian. */ - if (temp_len < 4) { break; } + if (unlikely(temp_len < 4)) { break; } // no retry u32 pos = rand_below(afl, temp_len - 3); u32 num = 1 + rand_below(afl, ARITH_MAX); @@ -2447,7 +2464,7 @@ havoc_stage: /* Randomly add to dword, little endian. */ - if (temp_len < 4) { break; } + if (unlikely(temp_len < 4)) { break; } // no retry u32 pos = rand_below(afl, temp_len - 3); item = 1 + rand_below(afl, ARITH_MAX); @@ -2466,7 +2483,7 @@ havoc_stage: /* Randomly add to dword, big endian. */ - if (temp_len < 4) { break; } + if (unlikely(temp_len < 4)) { break; } // no retry u32 pos = rand_below(afl, temp_len - 3); u32 num = 1 + rand_below(afl, ARITH_MAX); @@ -2502,7 +2519,7 @@ havoc_stage: case 17: { - if (temp_len + HAVOC_BLK_XL < MAX_FILE) { + if (likely(temp_len + HAVOC_BLK_XL < MAX_FILE)) { /* Clone bytes. */ @@ -2535,6 +2552,14 @@ havoc_stage: afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch)); temp_len += clone_len; + } else if (unlikely(temp_len < 8)) { + + break; + + } else { + + goto retry_havoc_step; + } break; @@ -2543,7 +2568,7 @@ havoc_stage: case 18: { - if (temp_len + HAVOC_BLK_XL < MAX_FILE) { + if (likely(temp_len + HAVOC_BLK_XL < MAX_FILE)) { /* Insert a block of constant bytes (25%). */ @@ -2578,6 +2603,14 @@ havoc_stage: afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch)); temp_len += clone_len; + } else if (unlikely(temp_len < 8)) { + + break; + + } else { + + goto retry_havoc_step; + } break; @@ -2588,7 +2621,7 @@ havoc_stage: /* Overwrite bytes with a randomly selected chunk bytes. */ - if (temp_len < 2) { break; } + if (unlikely(temp_len < 2)) { break; } // no retry u32 copy_len = choose_block_len(afl, temp_len - 1); u32 copy_from = rand_below(afl, temp_len - copy_len + 1); @@ -2613,7 +2646,7 @@ havoc_stage: /* Overwrite bytes with fixed bytes. */ - if (temp_len < 2) { break; } + if (unlikely(temp_len < 2)) { break; } // no retry u32 copy_len = choose_block_len(afl, temp_len - 1); u32 copy_to = rand_below(afl, temp_len - copy_len + 1); @@ -2674,7 +2707,7 @@ havoc_stage: case 24: { - if (temp_len < 4) { break; } + if (unlikely(temp_len < 4)) { break; } // no retry /* Switch bytes. */ @@ -2684,7 +2717,7 @@ havoc_stage: switch_to = rand_below(afl, temp_len); - } while (switch_from == switch_to); + } while (unlikely(switch_from == switch_to)); if (switch_from < switch_to) { @@ -2728,7 +2761,7 @@ havoc_stage: /* Delete bytes. */ - if (temp_len < 2) { break; } + if (unlikely(temp_len < 2)) { break; } // no retry /* Don't delete too much. */ @@ -2753,7 +2786,7 @@ havoc_stage: /* Shuffle bytes. */ - if (temp_len < 4) { break; } + if (unlikely(temp_len < 4)) { break; } // no retry u32 len = choose_block_len(afl, temp_len - 1); u32 off = rand_below(afl, temp_len - len + 1); @@ -2770,7 +2803,7 @@ havoc_stage: j = rand_below(afl, i + 1); - } while (i == j); + } while (unlikely(i == j)); unsigned char temp = out_buf[off + i]; out_buf[off + i] = out_buf[off + j]; @@ -2786,7 +2819,7 @@ havoc_stage: /* Delete bytes. */ - if (temp_len < 2) { break; } + if (unlikely(temp_len < 2)) { break; } // no retry /* Don't delete too much. */ @@ -2808,6 +2841,8 @@ havoc_stage: case 28: { + if (unlikely(temp_len < 2)) { break; } // no retry + u32 clone_len = 1; u32 clone_to = rand_below(afl, temp_len); u32 strat = rand_below(afl, 2); @@ -2845,7 +2880,7 @@ havoc_stage: case 29: { - if (temp_len < 4) { break; } + if (unlikely(temp_len < 4)) { break; } // no retry u32 off = rand_below(afl, temp_len), off2 = off, cnt = 0; @@ -2867,7 +2902,19 @@ havoc_stage: } - if (cnt == off) { break; } + if (cnt == off) { + + if (temp_len < 8) { + + break; + + } else { + + goto retry_havoc_step; + + } + + } } @@ -2905,7 +2952,7 @@ havoc_stage: val /= 2; break; case 4: - if (val && (u64)val < 0x19999999) { + if (likely(val && (u64)val < 0x19999999)) { val = (u64)rand_next(afl) % (u64)((u64)val * 10); @@ -2995,7 +3042,19 @@ havoc_stage: u32 len = 1 + rand_below(afl, 8); u32 pos = rand_below(afl, temp_len); /* Insert ascii number. */ - if (temp_len < pos + len) { break; } + if (unlikely(temp_len < pos + len)) { + + if (unlikely(temp_len < 8)) { + + break; + + } else { + + goto retry_havoc_step; + + } + + } #ifdef INTROSPECTION snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INSERTASCIINUM_"); @@ -3012,14 +3071,14 @@ havoc_stage: case 32: { - if (!afl->extras_cnt) { break; } + if (unlikely(!afl->extras_cnt)) { goto retry_havoc_step; } /* Use the dictionary. */ u32 use_extra = rand_below(afl, afl->extras_cnt); u32 extra_len = afl->extras[use_extra].len; - if (extra_len > temp_len) { break; } + if (unlikely(extra_len > temp_len)) { goto retry_havoc_step; } u32 insert_at = rand_below(afl, temp_len - extra_len + 1); #ifdef INTROSPECTION @@ -3035,11 +3094,15 @@ havoc_stage: case 33: { - if (!afl->extras_cnt) { break; } + if (unlikely(!afl->extras_cnt)) { goto retry_havoc_step; } u32 use_extra = rand_below(afl, afl->extras_cnt); u32 extra_len = afl->extras[use_extra].len; - if (temp_len + extra_len >= MAX_FILE) { break; } + if (unlikely(temp_len + extra_len >= MAX_FILE)) { + + goto retry_havoc_step; + + } u8 *ptr = afl->extras[use_extra].data; u32 insert_at = rand_below(afl, temp_len + 1); @@ -3066,14 +3129,14 @@ havoc_stage: case 34: { - if (!afl->a_extras_cnt) { break; } + if (unlikely(!afl->a_extras_cnt)) { goto retry_havoc_step; } /* Use the dictionary. */ u32 use_extra = rand_below(afl, afl->a_extras_cnt); u32 extra_len = afl->a_extras[use_extra].len; - if (extra_len > temp_len) { break; } + if (unlikely(extra_len > temp_len)) { goto retry_havoc_step; } u32 insert_at = rand_below(afl, temp_len - extra_len + 1); #ifdef INTROSPECTION @@ -3089,11 +3152,15 @@ havoc_stage: case 35: { - if (!afl->a_extras_cnt) { break; } + if (unlikely(!afl->a_extras_cnt)) { goto retry_havoc_step; } u32 use_extra = rand_below(afl, afl->a_extras_cnt); u32 extra_len = afl->a_extras[use_extra].len; - if (temp_len + extra_len >= MAX_FILE) { break; } + if (unlikely(temp_len + extra_len >= MAX_FILE)) { + + goto retry_havoc_step; + + } u8 *ptr = afl->a_extras[use_extra].data; u32 insert_at = rand_below(afl, temp_len + 1); @@ -3120,7 +3187,11 @@ havoc_stage: case 36: { - if (afl->ready_for_splicing_count <= 1) { break; } + if (unlikely(afl->ready_for_splicing_count <= 1)) { + + goto retry_havoc_step; + + } /* Pick a random queue entry and seek to it. */ @@ -3129,7 +3200,9 @@ havoc_stage: tid = rand_below(afl, afl->queued_items); - } while (tid == afl->current_entry || afl->queue_buf[tid]->len < 4); + } while (unlikely(tid == afl->current_entry || + + afl->queue_buf[tid]->len < 4)); /* Get the testcase for splicing. */ struct queue_entry *target = afl->queue_buf[tid]; @@ -3160,8 +3233,17 @@ havoc_stage: case 37: { - if (afl->ready_for_splicing_count <= 1) { break; } - if (temp_len + HAVOC_BLK_XL >= MAX_FILE) { break; } + if (unlikely(afl->ready_for_splicing_count <= 1)) { + + goto retry_havoc_step; + + } + + if (unlikely(temp_len + HAVOC_BLK_XL >= MAX_FILE)) { + + goto retry_havoc_step; + + } /* Pick a random queue entry and seek to it. */ @@ -3170,7 +3252,9 @@ havoc_stage: tid = rand_below(afl, afl->queued_items); - } while (tid == afl->current_entry || afl->queue_buf[tid]->len < 4); + } while (unlikely(tid == afl->current_entry || + + afl->queue_buf[tid]->len < 4)); /* Get the testcase for splicing. */ struct queue_entry *target = afl->queue_buf[tid]; @@ -3303,7 +3387,9 @@ retry_splicing: tid = rand_below(afl, afl->queued_items); - } while (tid == afl->current_entry || afl->queue_buf[tid]->len < 4); + } while ( + + unlikely(tid == afl->current_entry || afl->queue_buf[tid]->len < 4)); /* Get the testcase */ afl->splicing_with = tid; -- cgit v1.2.3 From fcd21256780fd21c55e72e9338b3992c60db22dc Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 4 Apr 2023 15:47:53 +0200 Subject: prepare for strategies --- src/afl-fuzz-one.c | 165 +++++++++++++++++++++-------------------------------- 1 file changed, 65 insertions(+), 100 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 1636c323..226fb40e 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -27,21 +27,7 @@ #include #include #include "cmplog.h" - -static u32 mutation_array_explore[] = { - - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37}; -// static u32 mutation_array_exploit[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, -// 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, -// 31 }; static u32 mutation_array_txt_explore[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, -// 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, -// 28, 29, 30, 31 }; static u32 mutation_array_txt_exploit[] = { 0, 1, 2, 3, 4, -// 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, -// 25, 26, 27, 28, 29, 30, 31 }; - -// what about more splicing? -// what about -x and cmplog learn? +#include "afl-mutations.h" /* MOpt */ @@ -85,50 +71,6 @@ static int select_algorithm(afl_state_t *afl, u32 max_algorithm) { } -/* Helper to choose random block len for block operations in fuzz_one(). - Doesn't return zero, provided that max_len is > 0. */ - -static inline u32 choose_block_len(afl_state_t *afl, u32 limit) { - - u32 min_value, max_value; - u32 rlim = MIN(afl->queue_cycle, (u32)3); - - if (unlikely(!afl->run_over10m)) { rlim = 1; } - - switch (rand_below(afl, rlim)) { - - case 0: - min_value = 1; - max_value = HAVOC_BLK_SMALL; - break; - - case 1: - min_value = HAVOC_BLK_SMALL; - max_value = HAVOC_BLK_MEDIUM; - break; - - default: - - if (likely(rand_below(afl, 10))) { - - min_value = HAVOC_BLK_MEDIUM; - max_value = HAVOC_BLK_LARGE; - - } else { - - min_value = HAVOC_BLK_LARGE; - max_value = HAVOC_BLK_XL; - - } - - } - - if (min_value >= limit) { min_value = 1; } - - return min_value + rand_below(afl, MIN(max_value, limit) - min_value + 1); - -} - /* Helper function to see if a particular change (xor_val = old ^ new) could be a product of deterministic bit flips with the lengths and stepovers attempted by afl-fuzz. This is used to avoid dupes in some of the @@ -2136,8 +2078,31 @@ havoc_stage: u32 *mutation_array; u32 stack_max; - // if ( ... ) - mutation_array = (u32 *)&mutation_array_explore; + if (afl->queue_cur->is_ascii) { // is text? + + if (1) { // is exploration? + + mutation_array = (unsigned int *)&mutation_strategy_exploration_text; + + } else { // is exploitation! + + mutation_array = (unsigned int *)&mutation_strategy_exploitation_text; + + } + + } else { // is binary! + + if (1) { // is exploration? + + mutation_array = (unsigned int *)&mutation_strategy_exploration_binary; + + } else { // is exploitation! + + mutation_array = (unsigned int *)&mutation_strategy_exploitation_binary; + + } + + } if (temp_len < 64) { @@ -2208,11 +2173,11 @@ havoc_stage: } retry_havoc_step: - u32 r = rand_below(afl, 256), item; + u32 r = rand_below(afl, MUT_STRATEGY_ARRAY_SIZE), item; switch (mutation_array[r]) { - case 0: { + case MUT_FLIPBIT: { /* Flip a single bit somewhere. Spooky! */ u8 bit = rand_below(afl, 8); @@ -2227,7 +2192,7 @@ havoc_stage: } - case 1: { + case MUT_INTERESTING8: { /* Set byte to interesting value. */ @@ -2241,7 +2206,7 @@ havoc_stage: } - case 2: { + case MUT_INTERESTING16: { /* Set word to interesting value, little endian. */ @@ -2260,7 +2225,7 @@ havoc_stage: } - case 3: { + case MUT_INTERESTING16BE: { /* Set word to interesting value, big endian. */ @@ -2278,7 +2243,7 @@ havoc_stage: } - case 4: { + case MUT_INTERESTING32: { /* Set dword to interesting value, little endian. */ @@ -2297,7 +2262,7 @@ havoc_stage: } - case 5: { + case MUT_INTERESTING32BE: { /* Set dword to interesting value, big endian. */ @@ -2315,7 +2280,7 @@ havoc_stage: } - case 6: { + case MUT_ARITH8_: { /* Randomly subtract from byte. */ @@ -2329,7 +2294,7 @@ havoc_stage: } - case 7: { + case MUT_ARITH8: { /* Randomly add to byte. */ @@ -2343,7 +2308,7 @@ havoc_stage: } - case 8: { + case MUT_ARITH16_: { /* Randomly subtract from word, little endian. */ @@ -2362,7 +2327,7 @@ havoc_stage: } - case 9: { + case MUT_ARITH16BE_: { /* Randomly subtract from word, big endian. */ @@ -2382,7 +2347,7 @@ havoc_stage: } - case 10: { + case MUT_ARITH16: { /* Randomly add to word, little endian. */ @@ -2401,7 +2366,7 @@ havoc_stage: } - case 11: { + case MUT_ARITH16BE: { /* Randomly add to word, big endian. */ @@ -2421,7 +2386,7 @@ havoc_stage: } - case 12: { + case MUT_ARITH32_: { /* Randomly subtract from dword, little endian. */ @@ -2440,7 +2405,7 @@ havoc_stage: } - case 13: { + case MUT_ARITH32BE_: { /* Randomly subtract from dword, big endian. */ @@ -2460,7 +2425,7 @@ havoc_stage: } - case 14: { + case MUT_ARITH32: { /* Randomly add to dword, little endian. */ @@ -2479,7 +2444,7 @@ havoc_stage: } - case 15: { + case MUT_ARITH32BE: { /* Randomly add to dword, big endian. */ @@ -2499,7 +2464,7 @@ havoc_stage: } - case 16: { + case MUT_RAND8: { /* Just set a random byte to a random value. Because, why not. We use XOR with 1-255 to eliminate the @@ -2517,7 +2482,7 @@ havoc_stage: } - case 17: { + case MUT_CLONE_OVERWRITE: { if (likely(temp_len + HAVOC_BLK_XL < MAX_FILE)) { @@ -2566,7 +2531,7 @@ havoc_stage: } - case 18: { + case MUT_CLONE_INSERT: { if (likely(temp_len + HAVOC_BLK_XL < MAX_FILE)) { @@ -2617,7 +2582,7 @@ havoc_stage: } - case 19: { + case MUT_OVERWRITE_COPY: { /* Overwrite bytes with a randomly selected chunk bytes. */ @@ -2642,7 +2607,7 @@ havoc_stage: } - case 20: { + case MUT_OVERWRITE_FIXED: { /* Overwrite bytes with fixed bytes. */ @@ -2666,7 +2631,7 @@ havoc_stage: } - case 21: { + case MUT_BYTEADD: { /* Increase byte by 1. */ @@ -2679,7 +2644,7 @@ havoc_stage: } - case 22: { + case MUT_BYTESUB: { /* Decrease byte by 1. */ @@ -2692,7 +2657,7 @@ havoc_stage: } - case 23: { + case MUT_FLIP8: { /* Flip byte. */ @@ -2705,7 +2670,7 @@ havoc_stage: } - case 24: { + case MUT_SWITCH: { if (unlikely(temp_len < 4)) { break; } // no retry @@ -2757,7 +2722,7 @@ havoc_stage: } - case 25: { + case MUT_DEL: { /* Delete bytes. */ @@ -2782,7 +2747,7 @@ havoc_stage: } - case 26: { + case MUT_SHUFFLE: { /* Shuffle bytes. */ @@ -2815,7 +2780,7 @@ havoc_stage: } - case 27: { + case MUT_DELONE: { /* Delete bytes. */ @@ -2839,7 +2804,7 @@ havoc_stage: } - case 28: { + case MUT_INSERTONE: { if (unlikely(temp_len < 2)) { break; } // no retry @@ -2878,7 +2843,7 @@ havoc_stage: } - case 29: { + case MUT_ASCIINUM: { if (unlikely(temp_len < 4)) { break; } // no retry @@ -3022,7 +2987,7 @@ havoc_stage: } - case 30: { + case MUT_NEG: { /* Neg byte. */ @@ -3037,7 +3002,7 @@ havoc_stage: } - case 31: { + case MUT_INSERTASCIINUM: { u32 len = 1 + rand_below(afl, 8); u32 pos = rand_below(afl, temp_len); @@ -3069,7 +3034,7 @@ havoc_stage: } - case 32: { + case MUT_EXTRA_OVERWRITE: { if (unlikely(!afl->extras_cnt)) { goto retry_havoc_step; } @@ -3092,7 +3057,7 @@ havoc_stage: } - case 33: { + case MUT_EXTRA_INSERT: { if (unlikely(!afl->extras_cnt)) { goto retry_havoc_step; } @@ -3127,7 +3092,7 @@ havoc_stage: } - case 34: { + case MUT_AUTO_EXTRA_OVERWRITE: { if (unlikely(!afl->a_extras_cnt)) { goto retry_havoc_step; } @@ -3150,7 +3115,7 @@ havoc_stage: } - case 35: { + case MUT_AUTO_EXTRA_INSERT: { if (unlikely(!afl->a_extras_cnt)) { goto retry_havoc_step; } @@ -3185,7 +3150,7 @@ havoc_stage: } - case 36: { + case MUT_SPLICE_OVERWRITE: { if (unlikely(afl->ready_for_splicing_count <= 1)) { @@ -3231,7 +3196,7 @@ havoc_stage: } - case 37: { + case MUT_SPLICE_INSERT: { if (unlikely(afl->ready_for_splicing_count <= 1)) { -- cgit v1.2.3 From 3ab18d286142e2e19e37850c051e0b07b9d7b296 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 4 Apr 2023 19:44:12 +0200 Subject: mode switch --- src/afl-fuzz-one.c | 6 +++--- src/afl-fuzz-state.c | 1 + src/afl-fuzz-stats.c | 5 ++++- src/afl-fuzz.c | 51 +++++++++++++++++++++++++++++++++++++++++++++------ 4 files changed, 53 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 226fb40e..e6b58713 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2078,9 +2078,9 @@ havoc_stage: u32 *mutation_array; u32 stack_max; - if (afl->queue_cur->is_ascii) { // is text? + if (unlikely(afl->text_input || afl->queue_cur->is_ascii)) { // is text? - if (1) { // is exploration? + if (likely(afl->fuzz_mode == 0)) { // is exploration? mutation_array = (unsigned int *)&mutation_strategy_exploration_text; @@ -2092,7 +2092,7 @@ havoc_stage: } else { // is binary! - if (1) { // is exploration? + if (likely(afl->fuzz_mode == 0)) { // is exploration? mutation_array = (unsigned int *)&mutation_strategy_exploration_binary; diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index f9aa5cfe..907861e9 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -108,6 +108,7 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) { afl->cmplog_lvl = 2; afl->min_length = 1; afl->max_length = MAX_FILE; + afl->switch_fuzz_mode = STRATEGY_SWITCH_TIME; #ifndef NO_SPLICING afl->use_splicing = 1; #endif diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 25ebe987..de48e10a 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -1282,7 +1282,10 @@ void show_stats_normal(afl_state_t *afl) { } /* Last line */ - SAYF(SET_G1 "\n" bSTG bLB bH30 bH20 bH2 bRB bSTOP cRST RESET_G1); + + SAYF(SET_G1 "\n" bSTG bLB bH cCYA bSTOP + " strategy:%s %s " bSTG bH20 bH10 bH2 bRB bSTOP cRST RESET_G1, + cPIN, afl->fuzz_mode == 0 ? "explore" : "exploit"); #undef IB diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 3380fd90..315107d7 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -128,6 +128,13 @@ static void usage(u8 *argv0, int more_help) { " -o dir - output directory for fuzzer findings\n\n" "Execution control settings:\n" + " -P strategy - set fix mutation strategy: explore (focus on new " + "coverage),\n" + " exploit (focus on triggering crashes). You can also " + "set a\n" + " number of seconds after without any finds it switches " + "to\n" + " exploit mode, and back on new coverage (default: %u)\n" " -p schedule - power schedules compute a seed's performance score:\n" " fast(default), explore, exploit, seek, rare, mmopt, " "coe, lin\n" @@ -156,6 +163,7 @@ static void usage(u8 *argv0, int more_help) { "\n" "Mutator settings:\n" + " -a - target expects ascii text input\n" " -g minlength - set min length of generated fuzz input (default: 1)\n" " -G maxlength - set max length of generated fuzz input (default: " "%lu)\n" @@ -212,7 +220,8 @@ static void usage(u8 *argv0, int more_help) { " -e ext - file extension for the fuzz test input file (if " "needed)\n" "\n", - argv0, EXEC_TIMEOUT, MEM_LIMIT, MAX_FILE, FOREIGN_SYNCS_MAX); + argv0, STRATEGY_SWITCH_TIME, EXEC_TIMEOUT, MEM_LIMIT, MAX_FILE, + FOREIGN_SYNCS_MAX); if (more_help > 1) { @@ -553,14 +562,44 @@ int main(int argc, char **argv_orig, char **envp) { afl->shmem_testcase_mode = 1; // we always try to perform shmem fuzzing - while ( - (opt = getopt( - argc, argv, - "+Ab:B:c:CdDe:E:hi:I:f:F:g:G:l:L:m:M:nNOo:p:RQs:S:t:T:UV:WXx:YZ")) > - 0) { + // still available: aHjJkKPqruvwz + while ((opt = getopt(argc, argv, + "+aAb:B:c:CdDe:E:f:F:g:G:hi:I:l:L:m:M:nNo:Op:P:QRs:S:t:" + "T:UV:WXx:YZ")) > 0) { switch (opt) { + case 'a': + afl->text_input = 1; + break; + + case 'P': + if (!stricmp(optarg, "explore") || !stricmp(optarg, "exploration")) { + + afl->fuzz_mode = 0; + afl->switch_fuzz_mode = 1; + + } else if (!stricmp(optarg, "exploit") || + + !stricmp(optarg, "exploitation")) { + + afl->fuzz_mode = 1; + afl->switch_fuzz_mode = 0; + + } else { + + if ((s32)(afl->switch_fuzz_mode = (u32)atoi(optarg)) < 1) { + + FATAL( + "Parameter for option -P must be \"explore\", \"exploit\" or a " + "number!"); + + } + + } + + break; + case 'g': afl->min_length = atoi(optarg); break; -- cgit v1.2.3 From 53b70ef104a334424fd5226c7504130b3bd45625 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 5 Apr 2023 09:33:09 +0200 Subject: mut changes --- src/afl-fuzz-one.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index e6b58713..bc267b15 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2659,7 +2659,7 @@ havoc_stage: case MUT_FLIP8: { - /* Flip byte. */ + /* Flip byte with a XOR 0xff. This is the same as NEG. */ #ifdef INTROSPECTION snprintf(afl->m_tmp, sizeof(afl->m_tmp), " FLIP8_"); @@ -2987,21 +2987,6 @@ havoc_stage: } - case MUT_NEG: { - - /* Neg byte. */ - -#ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), " NEG_"); - strcat(afl->mutation, afl->m_tmp); -#endif - item = rand_below(afl, temp_len); - - out_buf[item] = ~out_buf[item]; - break; - - } - case MUT_INSERTASCIINUM: { u32 len = 1 + rand_below(afl, 8); -- cgit v1.2.3 From 1fc0731604c1ea1abb38ab345d9046a6f1e9b7de Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 5 Apr 2023 09:42:27 +0200 Subject: stack pow --- src/afl-fuzz-one.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index bc267b15..48aa6eb0 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2076,7 +2076,7 @@ havoc_stage: where we take the input file and make random stacked tweaks. */ u32 *mutation_array; - u32 stack_max; + u32 stack_max, stack_max_pow = afl->havoc_stack_pow2; if (unlikely(afl->text_input || afl->queue_cur->is_ascii)) { // is text? @@ -2106,22 +2106,20 @@ havoc_stage: if (temp_len < 64) { - stack_max = 4; + --stack_max_pow; - } else if (temp_len < 512) { + } else if (temp_len <= 8096) { - stack_max = 8; - - } else if (temp_len < 8096) { - - stack_max = 16; + ++stack_max_pow; } else { - stack_max = 32; + ++stack_max_pow; } + stack_max = 1 << stack_max_pow; + // + (afl->extras_cnt ? 2 : 0) + (afl->a_extras_cnt ? 2 : 0); for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) { -- cgit v1.2.3 From e313180e4d3f7ba44b773e43af40d4af21088576 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 5 Apr 2023 10:32:37 +0200 Subject: fix for clang --- src/afl-fuzz-one.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 48aa6eb0..e6ff1d1a 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2139,8 +2139,8 @@ havoc_stage: LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { - if (el->stacked_custom && - rand_below(afl, 100) < el->stacked_custom_prob) { + if (unlikely(el->stacked_custom && + rand_below(afl, 100) < el->stacked_custom_prob)) { u8 *custom_havoc_buf = NULL; size_t new_len = el->afl_custom_havoc_mutation( @@ -2170,7 +2170,8 @@ havoc_stage: } - retry_havoc_step: + retry_havoc_step : { + u32 r = rand_below(afl, MUT_STRATEGY_ARRAY_SIZE), item; switch (mutation_array[r]) { @@ -3250,6 +3251,8 @@ havoc_stage: } + } + if (common_fuzz_stuff(afl, out_buf, temp_len)) { goto abandon_entry; } /* out_buf might have been mangled a bit, so let's restore it to its -- cgit v1.2.3 From a74561b0e7434282ad214ca634b5c19c2f345e8e Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 5 Apr 2023 12:12:05 +0200 Subject: implement switch mode --- src/afl-fuzz-bitmap.c | 12 ++++++++++++ src/afl-fuzz-state.c | 2 +- src/afl-fuzz.c | 30 ++++++++++++++++++++++++++---- 3 files changed, 39 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index d9c792d1..a937c96d 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -529,6 +529,18 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { close(fd); add_to_queue(afl, queue_fn, len, 0); + if (unlikely(afl->fuzz_mode) && likely(afl->switch_fuzz_mode)) { + + if (afl->afl_env.afl_no_ui) { + + ACTF("New coverage found, switching back to exploration mode."); + + } + + afl->fuzz_mode = 0; + + } + #ifdef INTROSPECTION if (afl->custom_mutators_count && afl->current_custom_fuzz) { diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 907861e9..9dc258b1 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -108,7 +108,7 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) { afl->cmplog_lvl = 2; afl->min_length = 1; afl->max_length = MAX_FILE; - afl->switch_fuzz_mode = STRATEGY_SWITCH_TIME; + afl->switch_fuzz_mode = STRATEGY_SWITCH_TIME * 1000; #ifndef NO_SPLICING afl->use_splicing = 1; #endif diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 315107d7..c50b271b 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -577,7 +577,7 @@ int main(int argc, char **argv_orig, char **envp) { if (!stricmp(optarg, "explore") || !stricmp(optarg, "exploration")) { afl->fuzz_mode = 0; - afl->switch_fuzz_mode = 1; + afl->switch_fuzz_mode = 0; } else if (!stricmp(optarg, "exploit") || @@ -588,12 +588,16 @@ int main(int argc, char **argv_orig, char **envp) { } else { - if ((s32)(afl->switch_fuzz_mode = (u32)atoi(optarg)) < 1) { + if ((afl->switch_fuzz_mode = (u32)atoi(optarg)) > INT_MAX) { FATAL( "Parameter for option -P must be \"explore\", \"exploit\" or a " "number!"); + } else { + + afl->switch_fuzz_mode *= 1000; + } } @@ -2689,13 +2693,31 @@ int main(int argc, char **argv_orig, char **envp) { } while (skipped_fuzz && afl->queue_cur && !afl->stop_soon); + u64 cur_time = get_cur_time(); + + if (likely(afl->switch_fuzz_mode && afl->fuzz_mode == 0) && + unlikely(cur_time > afl->last_find_time + afl->switch_fuzz_mode)) { + + if (afl->afl_env.afl_no_ui) { + + ACTF( + "No new coverage found for %llu seconds, switching to exploitation " + "strategy.", + afl->switch_fuzz_mode / 1000); + + } + + afl->fuzz_mode = 1; + + } + if (likely(!afl->stop_soon && afl->sync_id)) { if (likely(afl->skip_deterministic)) { if (unlikely(afl->is_main_node)) { - if (unlikely(get_cur_time() > + if (unlikely(cur_time > (afl->sync_time >> 1) + afl->last_sync_time)) { if (!(sync_interval_cnt++ % (SYNC_INTERVAL / 3))) { @@ -2708,7 +2730,7 @@ int main(int argc, char **argv_orig, char **envp) { } else { - if (unlikely(get_cur_time() > afl->sync_time + afl->last_sync_time)) { + if (unlikely(cur_time > afl->sync_time + afl->last_sync_time)) { if (!(sync_interval_cnt++ % SYNC_INTERVAL)) { sync_fuzzers(afl); } -- cgit v1.2.3 From fcb5eda5d0eb38b1a9678ee75890f2fccf936bd9 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 5 Apr 2023 16:34:08 +0200 Subject: nit --- src/afl-fuzz.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index c50b271b..bc44367a 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -562,7 +562,7 @@ int main(int argc, char **argv_orig, char **envp) { afl->shmem_testcase_mode = 1; // we always try to perform shmem fuzzing - // still available: aHjJkKPqruvwz + // still available: HjJkKqruvwz while ((opt = getopt(argc, argv, "+aAb:B:c:CdDe:E:f:F:g:G:hi:I:l:L:m:M:nNo:Op:P:QRs:S:t:" "T:UV:WXx:YZ")) > 0) { -- cgit v1.2.3 From 400c5e92cb5ed304a2c14a79597100850cf9f82c Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 7 Apr 2023 09:41:22 +0200 Subject: renaming --- src/afl-fuzz-one.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index e6ff1d1a..f5ddea0e 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2481,7 +2481,7 @@ havoc_stage: } - case MUT_CLONE_OVERWRITE: { + case MUT_CLONE_COPY: { if (likely(temp_len + HAVOC_BLK_XL < MAX_FILE)) { @@ -2493,7 +2493,7 @@ havoc_stage: #ifdef INTROSPECTION snprintf(afl->m_tmp, sizeof(afl->m_tmp), " CLONE-%s_%u_%u_%u", - "overwrite", clone_from, clone_to, clone_len); + "COPY", clone_from, clone_to, clone_len); strcat(afl->mutation, afl->m_tmp); #endif u8 *new_buf = @@ -2530,7 +2530,7 @@ havoc_stage: } - case MUT_CLONE_INSERT: { + case MUT_CLONE_FIXED: { if (likely(temp_len + HAVOC_BLK_XL < MAX_FILE)) { @@ -2544,7 +2544,7 @@ havoc_stage: #ifdef INTROSPECTION snprintf(afl->m_tmp, sizeof(afl->m_tmp), " CLONE-%s_%u_%u_%u", - "insert", strat, clone_to, clone_len); + "FIXED", strat, clone_to, clone_len); strcat(afl->mutation, afl->m_tmp); #endif u8 *new_buf = @@ -2587,20 +2587,22 @@ havoc_stage: if (unlikely(temp_len < 2)) { break; } // no retry - u32 copy_len = choose_block_len(afl, temp_len - 1); - u32 copy_from = rand_below(afl, temp_len - copy_len + 1); - u32 copy_to = rand_below(afl, temp_len - copy_len + 1); + u32 copy_from, copy_to, + copy_len = choose_block_len(afl, temp_len - 1); + + do { - if (likely(copy_from != copy_to)) { + copy_from = rand_below(afl, temp_len - copy_len + 1); + copy_to = rand_below(afl, temp_len - copy_len + 1); + + } while (unlikely(copy_from == copy_to)); #ifdef INTROSPECTION - snprintf(afl->m_tmp, sizeof(afl->m_tmp), " OVERWRITE-COPY_%u_%u_%u", - copy_from, copy_to, copy_len); - strcat(afl->mutation, afl->m_tmp); + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " OVERWRITE-COPY_%u_%u_%u", + copy_from, copy_to, copy_len); + strcat(afl->mutation, afl->m_tmp); #endif - memmove(out_buf + copy_to, out_buf + copy_from, copy_len); - - } + memmove(out_buf + copy_to, out_buf + copy_from, copy_len); break; -- cgit v1.2.3 From 3e84d6a2ae7df5f6b9073a91ccc6acef50b45aab Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 27 Apr 2023 11:49:00 +0200 Subject: afl++ -> AFL++ --- src/afl-cc.c | 2 +- src/afl-forkserver.c | 6 +++--- src/afl-fuzz.c | 10 +++++----- src/afl-ld-lto.c | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index d1001187..99ce39d4 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -642,7 +642,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { } //#if LLVM_MAJOR >= 13 - // // Use the old pass manager in LLVM 14 which the afl++ passes still + // // Use the old pass manager in LLVM 14 which the AFL++ passes still // use. cc_params[cc_par_cnt++] = "-flegacy-pass-manager"; //#endif diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index aa8c8622..30c8901c 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -489,7 +489,7 @@ static void report_error_and_exit(int error) { break; case FS_ERROR_OLD_CMPLOG: FATAL( - "the -c cmplog target was instrumented with an too old afl++ " + "the -c cmplog target was instrumented with an too old AFL++ " "version, you need to recompile it."); break; case FS_ERROR_OLD_CMPLOG_QEMU: @@ -987,7 +987,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if ((status & FS_OPT_ENABLED) == FS_OPT_ENABLED) { - // workaround for recent afl++ versions + // workaround for recent AFL++ versions if ((status & FS_OPT_OLD_AFLPP_WORKAROUND) == FS_OPT_OLD_AFLPP_WORKAROUND) status = (status & 0xf0ffffff); @@ -1059,7 +1059,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, FATAL( "Target's coverage map size of %u is larger than the one this " - "afl++ is set with (%u). Either set AFL_MAP_SIZE=%u and restart " + "AFL++ is set with (%u). Either set AFL_MAP_SIZE=%u and restart " " afl-fuzz, or change MAP_SIZE_POW2 in config.h and recompile " "afl-fuzz", tmp_map_size, fsrv->map_size, tmp_map_size); diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 71d2afd8..646dc50b 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1280,16 +1280,16 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->fsrv.mem_limit && afl->shm.cmplog_mode) afl->fsrv.mem_limit += 260; - OKF("afl++ is maintained by Marc \"van Hauser\" Heuse, Heiko \"hexcoder\" " - "Eißfeldt, Andrea Fioraldi and Dominik Maier"); - OKF("afl++ is open source, get it at " + OKF("AFL++ is maintained by Marc \"van Hauser\" Heuse, Dominik Maier, Andrea " + "Fioraldi and Heiko \"hexcoder\" Eißfeldt"); + OKF("AFL++ is open source, get it at " "https://github.com/AFLplusplus/AFLplusplus"); - OKF("NOTE: afl++ >= v3 has changed defaults and behaviours - see README.md"); + OKF("NOTE: AFL++ >= v3 has changed defaults and behaviours - see README.md"); #ifdef __linux__ if (afl->fsrv.nyx_mode) { - OKF("afl++ Nyx mode is enabled (developed and mainted by Sergej Schumilo)"); + OKF("AFL++ Nyx mode is enabled (developed and mainted by Sergej Schumilo)"); OKF("Nyx is open source, get it at https://github.com/Nyx-Fuzz"); } diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c index 5438bd9f..420dd817 100644 --- a/src/afl-ld-lto.c +++ b/src/afl-ld-lto.c @@ -2,7 +2,7 @@ american fuzzy lop++ - wrapper for llvm 11+ lld ----------------------------------------------- - Written by Marc Heuse for afl++ + Written by Marc Heuse for AFL++ Maintained by Marc Heuse , Heiko Eißfeldt @@ -210,7 +210,7 @@ static void edit_params(int argc, char **argv) { if (strcmp(argv[i], "--afl") == 0) { - if (!be_quiet) OKF("afl++ test command line flag detected, exiting."); + if (!be_quiet) OKF("AFL++ test command line flag detected, exiting."); exit(0); } -- cgit v1.2.3 From e983e2e9cfb9e4c8489dc35f28bca502ec241c27 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 27 Apr 2023 16:24:43 +0200 Subject: more debug --- src/afl-fuzz-init.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index bd591c8f..baf56a5f 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -716,6 +716,8 @@ void read_testcases(afl_state_t *afl, u8 *directory) { } + // if (getenv("MYTEST")) afl->in_place_resume = 1; + if (nl_cnt) { u32 done = 0; @@ -827,6 +829,8 @@ void read_testcases(afl_state_t *afl, u8 *directory) { } + // if (getenv("MYTEST")) afl->in_place_resume = 0; + free(nl); /* not tracked */ if (!afl->queued_items && directory == NULL) { @@ -908,8 +912,10 @@ void perform_dry_run(afl_state_t *afl) { if (res == afl->crash_mode || res == FSRV_RUN_NOBITS) { - SAYF(cGRA " len = %u, map size = %u, exec speed = %llu us\n" cRST, - q->len, q->bitmap_size, q->exec_us); + SAYF(cGRA + " len = %u, map size = %u, exec speed = %llu us, hash = " + "%016llx\n" cRST, + q->len, q->bitmap_size, q->exec_us, q->exec_cksum); } @@ -1164,14 +1170,14 @@ void perform_dry_run(afl_state_t *afl) { u32 duplicates = 0, i; - for (idx = 0; idx < afl->queued_items; idx++) { + for (idx = 0; idx < afl->queued_items - 1; idx++) { q = afl->queue_buf[idx]; if (!q || q->disabled || q->cal_failed || !q->exec_cksum) { continue; } - u32 done = 0; + for (i = idx + 1; - i < afl->queued_items && !done && likely(afl->queue_buf[i]); i++) { + likely(i < afl->queued_items && afl->queue_buf[i] && !done); ++i) { struct queue_entry *p = afl->queue_buf[i]; if (p->disabled || p->cal_failed || !p->exec_cksum) { continue; } @@ -1194,6 +1200,13 @@ void perform_dry_run(afl_state_t *afl) { p->disabled = 1; p->perf_score = 0; + if (afl->debug) { + + WARNF("Same coverage - %s is kept active, %s is disabled.", + q->fname, p->fname); + + } + } else { if (!q->was_fuzzed) { @@ -1207,7 +1220,14 @@ void perform_dry_run(afl_state_t *afl) { q->disabled = 1; q->perf_score = 0; - done = 1; + if (afl->debug) { + + WARNF("Same coverage - %s is kept active, %s is disabled.", + p->fname, q->fname); + + } + + done = 1; // end inner loop because outer loop entry is disabled now } -- cgit v1.2.3 From a2daef29f9c323c0a6a7a64013aadb79ffd3e534 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Thu, 27 Apr 2023 17:57:22 +0200 Subject: slightly different weighting algo (#1719) * better seed selection * slightly different weighting calculation * remove unnecessary memset --- src/afl-fuzz-queue.c | 92 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 63 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 8ad7cd97..b10bf749 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -49,11 +49,13 @@ inline u32 select_next_queue_entry(afl_state_t *afl) { u32 s = rand_below(afl, afl->queued_items); double p = rand_next_percent(afl); + /* fprintf(stderr, "select: p=%f s=%u ... p < prob[s]=%f ? s=%u : alias[%u]=%u" " ==> %u\n", p, s, afl->alias_probability[s], s, s, afl->alias_table[s], p < afl->alias_probability[s] ? s : afl->alias_table[s]); */ + return (p < afl->alias_probability[s] ? s : afl->alias_table[s]); } @@ -87,25 +89,28 @@ double compute_weight(afl_state_t *afl, struct queue_entry *q, void create_alias_table(afl_state_t *afl) { - u32 n = afl->queued_items, i = 0, a, g; + u32 n = afl->queued_items, i = 0, nSmall = 0, nLarge = n - 1; double sum = 0; + double *P = (double *)afl_realloc(AFL_BUF_PARAM(out), n * sizeof(double)); + u32 *Small = (int *)afl_realloc(AFL_BUF_PARAM(out_scratch), n * sizeof(u32)); + u32 *Large = (int *)afl_realloc(AFL_BUF_PARAM(in_scratch), n * sizeof(u32)); + afl->alias_table = (u32 *)afl_realloc((void **)&afl->alias_table, n * sizeof(u32)); afl->alias_probability = (double *)afl_realloc( (void **)&afl->alias_probability, n * sizeof(double)); - double *P = (double *)afl_realloc(AFL_BUF_PARAM(out), n * sizeof(double)); - int *S = (int *)afl_realloc(AFL_BUF_PARAM(out_scratch), n * sizeof(u32)); - int *L = (int *)afl_realloc(AFL_BUF_PARAM(in_scratch), n * sizeof(u32)); - if (!P || !S || !L || !afl->alias_table || !afl->alias_probability) { + if (!P || !Small || !Large || !afl->alias_table || !afl->alias_probability) { FATAL("could not acquire memory for alias table"); } - memset((void *)afl->alias_table, 0, n * sizeof(u32)); memset((void *)afl->alias_probability, 0, n * sizeof(double)); + memset((void *)afl->alias_table, 0, n * sizeof(u32)); + memset((void *)Small, 0, n * sizeof(u32)); + memset((void *)Large, 0, n * sizeof(u32)); if (likely(afl->schedule < RARE)) { @@ -166,7 +171,15 @@ void create_alias_table(afl_state_t *afl) { for (i = 0; i < n; i++) { // weight is always 0 for disabled entries - P[i] = (afl->queue_buf[i]->weight * n) / sum; + if (unlikely(afl->queue_buf[i]->disabled)) { + + P[i] = 0; + + } else { + + P[i] = (afl->queue_buf[i]->weight * n) / sum; + + } } @@ -176,60 +189,81 @@ void create_alias_table(afl_state_t *afl) { struct queue_entry *q = afl->queue_buf[i]; - if (likely(!q->disabled)) { q->perf_score = calculate_score(afl, q); } + if (likely(!q->disabled)) { + + q->perf_score = calculate_score(afl, q); + sum += q->perf_score; - sum += q->perf_score; + } } for (i = 0; i < n; i++) { // perf_score is always 0 for disabled entries - P[i] = (afl->queue_buf[i]->perf_score * n) / sum; + if (unlikely(afl->queue_buf[i]->disabled)) { + + P[i] = 0; + + } else { + + P[i] = (afl->queue_buf[i]->perf_score * n) / sum; + + } } } - int nS = 0, nL = 0, s; - for (s = (s32)n - 1; s >= 0; --s) { + // Done collecting weightings in P, now create the arrays. + + for (s32 j = (s32)(n - 1); j >= 0; j--) { - if (P[s] < 1) { + if (P[j] < 1) { - S[nS++] = s; + Small[nSmall++] = (u32)j; } else { - L[nL++] = s; + Large[nLarge--] = (u32)j; } } - while (nS && nL) { + while (nSmall && nLarge != n - 1) { + + u32 small = Small[--nSmall]; + u32 large = Large[++nLarge]; + + afl->alias_probability[small] = P[small]; + afl->alias_table[small] = large; - a = S[--nS]; - g = L[--nL]; - afl->alias_probability[a] = P[a]; - afl->alias_table[a] = g; - P[g] = P[g] + P[a] - 1; - if (P[g] < 1) { + P[large] = P[large] - (1 - P[small]); - S[nS++] = g; + if (P[large] < 1) { + + Small[nSmall++] = large; } else { - L[nL++] = g; + Large[nLarge--] = large; } } - while (nL) - afl->alias_probability[L[--nL]] = 1; + while (nSmall) { + + afl->alias_probability[Small[--nSmall]] = 1; + + } - while (nS) - afl->alias_probability[S[--nS]] = 1; + while (nLarge != n - 1) { + + afl->alias_probability[Large[++nLarge]] = 1; + + } afl->reinit_table = 0; @@ -264,7 +298,7 @@ void create_alias_table(afl_state_t *afl) { */ /* fprintf(stderr, " entry alias probability perf_score weight - filename\n"); for (u32 i = 0; i < n; ++i) fprintf(stderr, " %5u %5u %11u + filename\n"); for (i = 0; i < n; ++i) fprintf(stderr, " %5u %5u %11u %0.9f %0.9f %s\n", i, afl->alias_table[i], afl->alias_probability[i], afl->queue_buf[i]->perf_score, afl->queue_buf[i]->weight, afl->queue_buf[i]->fname); -- cgit v1.2.3 From 6cad585bdc5c335cc2894c97e9aaf6d5fff88e1f Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 27 Apr 2023 18:57:28 +0200 Subject: nits --- src/afl-showmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-showmap.c b/src/afl-showmap.c index d0e01cb1..f60acb2d 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -1287,7 +1287,7 @@ int main(int argc, char **argv_orig, char **envp) { break; - case 'Y': // fallthough + case 'Y': // fallthrough #ifdef __linux__ case 'X': /* NYX mode */ -- cgit v1.2.3 From 41b0fe7280372031753fc5f11b9a03b214189155 Mon Sep 17 00:00:00 2001 From: Nick Potenski Date: Thu, 27 Apr 2023 11:57:55 -0500 Subject: afl-showmap: Start a only a single fork server (#1718) A forkserver is started by afl_fsrv_get_mapsize() when dynamically finding the map size. When an input directory option is specified a second fork server was also started. This commit re-arranges the inits for several forkserver struct members so that we can re-use the server started by the get_mapsize() call when not in coresight/qemu/unicorn modes and just start the server otherwise. --- src/afl-showmap.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/afl-showmap.c b/src/afl-showmap.c index f60acb2d..9c029035 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -1421,6 +1421,14 @@ int main(int argc, char **argv_orig, char **envp) { // If @@ are in the target args, replace them and also set use_stdin=false. detect_file_args(argv + optind, stdin_file, &fsrv->use_stdin); + fsrv->dev_null_fd = open("/dev/null", O_RDWR); + if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); } + + fsrv->out_file = stdin_file; + fsrv->out_fd = + open(stdin_file, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION); + if (fsrv->out_fd < 0) { PFATAL("Unable to create '%s'", stdin_file); } + } else { // If @@ are in the target args, replace them and also set use_stdin=false. @@ -1588,6 +1596,14 @@ int main(int argc, char **argv_orig, char **envp) { fsrv->map_size = map_size; + } else { + + afl_fsrv_start(fsrv, use_argv, &stop_soon, + (get_afl_env("AFL_DEBUG_CHILD") || + get_afl_env("AFL_DEBUG_CHILD_OUTPUT")) + ? 1 + : 0); + } if (in_dir || in_filelist) { @@ -1617,9 +1633,6 @@ int main(int argc, char **argv_orig, char **envp) { if (getenv("AFL_DEBUG_GDB")) wait_for_gdb = true; - fsrv->dev_null_fd = open("/dev/null", O_RDWR); - if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); } - if (in_filelist) { if (!be_quiet) ACTF("Reading from file list '%s'...", in_filelist); @@ -1666,10 +1679,6 @@ int main(int argc, char **argv_orig, char **envp) { } atexit(at_exit_handler); - fsrv->out_file = stdin_file; - fsrv->out_fd = - open(stdin_file, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION); - if (fsrv->out_fd < 0) { PFATAL("Unable to create '%s'", out_file); } if (get_afl_env("AFL_DEBUG")) { @@ -1685,12 +1694,6 @@ int main(int argc, char **argv_orig, char **envp) { } - afl_fsrv_start(fsrv, use_argv, &stop_soon, - (get_afl_env("AFL_DEBUG_CHILD") || - get_afl_env("AFL_DEBUG_CHILD_OUTPUT")) - ? 1 - : 0); - map_size = fsrv->map_size; if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz) -- cgit v1.2.3 From e956f23a77b776a5c11344889503c833adbf1052 Mon Sep 17 00:00:00 2001 From: "Christian Holler (:decoder)" Date: Fri, 28 Apr 2023 11:35:22 +0200 Subject: Source Code Coverage support for Nyx (Part 1) (#1720) * Additional source code reformatting in afl-compiler-rt * Add source code coverage support to afl-compiler-rt (for use with Nyx) --- src/afl-cc.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 99ce39d4..b11a041d 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -76,6 +76,7 @@ enum { INSTRUMENT_OPT_NGRAM = 16, INSTRUMENT_OPT_CALLER = 32, INSTRUMENT_OPT_CTX_K = 64, + INSTRUMENT_OPT_CODECOV = 128, }; @@ -751,7 +752,15 @@ static void edit_params(u32 argc, char **argv, char **envp) { } else if (instrument_mode == INSTRUMENT_LLVMNATIVE) { #if LLVM_MAJOR >= 4 - cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; + if (instrument_opt_mode & INSTRUMENT_OPT_CODECOV) { + #if LLVM_MAJOR >= 6 + cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table"; + #else + FATAL("pcguard instrumentation with pc-table requires llvm 6.0.1+"); + #endif + } else { + cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; + } #else FATAL("pcguard instrumentation requires llvm 4.0.1+"); #endif @@ -1682,6 +1691,18 @@ int main(int argc, char **argv, char **envp) { } + if (strncasecmp(ptr2, "llvmcodecov", strlen("llvmcodecov")) == 0 || + strncasecmp(ptr2, "llvm-codecov", strlen("llvm-codecov")) == 0) { + + if (!instrument_mode || instrument_mode == INSTRUMENT_LLVMNATIVE) { + instrument_mode = INSTRUMENT_LLVMNATIVE; + instrument_opt_mode |= INSTRUMENT_OPT_CODECOV; + } else + FATAL("main instrumentation mode already set with %s", + instrument_mode_string[instrument_mode]); + + } + if (strncasecmp(ptr2, "cfg", strlen("cfg")) == 0 || strncasecmp(ptr2, "instrim", strlen("instrim")) == 0) { @@ -2241,7 +2262,8 @@ int main(int argc, char **argv, char **envp) { "(requires LLVM 11 or higher)"); #endif - if (instrument_opt_mode && instrument_mode != INSTRUMENT_CLASSIC) + if (instrument_opt_mode && instrument_opt_mode != INSTRUMENT_OPT_CODECOV && + instrument_mode != INSTRUMENT_CLASSIC) FATAL( "CALLER, CTX and NGRAM instrumentation options can only be used with " "the LLVM CLASSIC instrumentation mode."); -- cgit v1.2.3 From 5813a4319c88848b2a1c47c12fe27f5e14dcad44 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 28 Apr 2023 11:42:21 +0200 Subject: doc, code format --- src/afl-cc.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index b11a041d..19314555 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -752,15 +752,21 @@ static void edit_params(u32 argc, char **argv, char **envp) { } else if (instrument_mode == INSTRUMENT_LLVMNATIVE) { #if LLVM_MAJOR >= 4 - if (instrument_opt_mode & INSTRUMENT_OPT_CODECOV) { + if (instrument_opt_mode & INSTRUMENT_OPT_CODECOV) { + #if LLVM_MAJOR >= 6 - cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table"; + cc_params[cc_par_cnt++] = + "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table"; #else FATAL("pcguard instrumentation with pc-table requires llvm 6.0.1+"); #endif - } else { + + } else { + cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; - } + + } + #else FATAL("pcguard instrumentation requires llvm 4.0.1+"); #endif @@ -1660,13 +1666,17 @@ int main(int argc, char **argv, char **envp) { instrument_mode = INSTRUMENT_CLASSIC; lto_mode = 1; - } else if (!instrument_mode || instrument_mode == INSTRUMENT_AFL) + } else if (!instrument_mode || instrument_mode == INSTRUMENT_AFL) { instrument_mode = INSTRUMENT_AFL; - else + + } else { + FATAL("main instrumentation mode already set with %s", instrument_mode_string[instrument_mode]); + } + } if (strncasecmp(ptr2, "pc-guard", strlen("pc-guard")) == 0 || @@ -1695,12 +1705,17 @@ int main(int argc, char **argv, char **envp) { strncasecmp(ptr2, "llvm-codecov", strlen("llvm-codecov")) == 0) { if (!instrument_mode || instrument_mode == INSTRUMENT_LLVMNATIVE) { + instrument_mode = INSTRUMENT_LLVMNATIVE; - instrument_opt_mode |= INSTRUMENT_OPT_CODECOV; - } else + instrument_opt_mode |= INSTRUMENT_OPT_CODECOV; + + } else { + FATAL("main instrumentation mode already set with %s", instrument_mode_string[instrument_mode]); + } + } if (strncasecmp(ptr2, "cfg", strlen("cfg")) == 0 || -- cgit v1.2.3 From 9065d4ba86ecdafeade50e5235ee1e99f4179692 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 1 May 2023 08:38:13 +0200 Subject: fix effector map --- src/afl-fuzz-one.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index ee562f96..442240a9 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -842,6 +842,7 @@ u8 fuzz_one_original(afl_state_t *afl) { eff_map = afl_realloc(AFL_BUF_PARAM(eff), EFF_ALEN(len)); if (unlikely(!eff_map)) { PFATAL("alloc"); } + memset(eff_map, 0, sizeof(len)); eff_map[0] = 1; if (EFF_APOS(len - 1) != 0) { @@ -3570,6 +3571,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { eff_map = afl_realloc(AFL_BUF_PARAM(eff), EFF_ALEN(len)); if (unlikely(!eff_map)) { PFATAL("alloc"); } + memset(eff_map, 0, sizeof(len)); eff_map[0] = 1; if (EFF_APOS(len - 1) != 0) { -- cgit v1.2.3 From 2cd07abca9c7b843bbd2085e0e4d852d41169092 Mon Sep 17 00:00:00 2001 From: lazymio Date: Mon, 1 May 2023 13:12:05 +0200 Subject: Should memset EFF_ALEN(len) of eff_map (#1722) --- src/afl-fuzz-one.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 442240a9..a9902087 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -842,7 +842,7 @@ u8 fuzz_one_original(afl_state_t *afl) { eff_map = afl_realloc(AFL_BUF_PARAM(eff), EFF_ALEN(len)); if (unlikely(!eff_map)) { PFATAL("alloc"); } - memset(eff_map, 0, sizeof(len)); + memset(eff_map, 0, EFF_ALEN(len)); eff_map[0] = 1; if (EFF_APOS(len - 1) != 0) { @@ -3571,7 +3571,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { eff_map = afl_realloc(AFL_BUF_PARAM(eff), EFF_ALEN(len)); if (unlikely(!eff_map)) { PFATAL("alloc"); } - memset(eff_map, 0, sizeof(len)); + memset(eff_map, 0, EFF_ALEN(len)); eff_map[0] = 1; if (EFF_APOS(len - 1) != 0) { -- cgit v1.2.3 From 22db79aefafb48fed48199a86a39babdee795870 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 1 May 2023 15:07:49 +0200 Subject: fix reallocs --- src/afl-fuzz.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 646dc50b..c02479cf 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1979,6 +1979,7 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->non_instrumented_mode || afl->fsrv.qemu_mode || afl->fsrv.frida_mode || afl->fsrv.cs_mode || afl->unicorn_mode) { + u32 old_map_size = map_size; map_size = afl->fsrv.real_map_size = afl->fsrv.map_size = MAP_SIZE; afl->virgin_bits = ck_realloc(afl->virgin_bits, map_size); afl->virgin_tmout = ck_realloc(afl->virgin_tmout, map_size); @@ -1990,6 +1991,18 @@ int main(int argc, char **argv_orig, char **envp) { afl->first_trace = ck_realloc(afl->first_trace, map_size); afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, map_size); + if (old_map_size < map_size) { + + memset(afl->var_bytes + old_map_size, 0, map_size - old_map_size); + memset(afl->top_rated + old_map_size, 0, map_size - old_map_size); + memset(afl->clean_trace + old_map_size, 0, map_size - old_map_size); + memset(afl->clean_trace_custom + old_map_size, 0, + map_size - old_map_size); + memset(afl->first_trace + old_map_size, 0, map_size - old_map_size); + memset(afl->map_tmp_buf + old_map_size, 0, map_size - old_map_size); + + } + } afl->argv = use_argv; @@ -2017,6 +2030,7 @@ int main(int argc, char **argv_orig, char **envp) { OKF("Re-initializing maps to %u bytes", new_map_size); + u32 old_map_size = map_size; afl->virgin_bits = ck_realloc(afl->virgin_bits, new_map_size); afl->virgin_tmout = ck_realloc(afl->virgin_tmout, new_map_size); afl->virgin_crash = ck_realloc(afl->virgin_crash, new_map_size); @@ -2029,6 +2043,18 @@ int main(int argc, char **argv_orig, char **envp) { afl->first_trace = ck_realloc(afl->first_trace, new_map_size); afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, new_map_size); + if (old_map_size < new_map_size) { + + memset(afl->var_bytes + old_map_size, 0, new_map_size - old_map_size); + memset(afl->top_rated + old_map_size, 0, new_map_size - old_map_size); + memset(afl->clean_trace + old_map_size, 0, new_map_size - old_map_size); + memset(afl->clean_trace_custom + old_map_size, 0, + new_map_size - old_map_size); + memset(afl->first_trace + old_map_size, 0, new_map_size - old_map_size); + memset(afl->map_tmp_buf + old_map_size, 0, new_map_size - old_map_size); + + } + afl_fsrv_kill(&afl->fsrv); afl_shm_deinit(&afl->shm); afl->fsrv.map_size = new_map_size; @@ -2079,6 +2105,7 @@ int main(int argc, char **argv_orig, char **envp) { OKF("Re-initializing maps to %u bytes due cmplog", new_map_size); + u32 old_map_size = map_size; afl->virgin_bits = ck_realloc(afl->virgin_bits, new_map_size); afl->virgin_tmout = ck_realloc(afl->virgin_tmout, new_map_size); afl->virgin_crash = ck_realloc(afl->virgin_crash, new_map_size); @@ -2091,6 +2118,18 @@ int main(int argc, char **argv_orig, char **envp) { afl->first_trace = ck_realloc(afl->first_trace, new_map_size); afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, new_map_size); + if (old_map_size < new_map_size) { + + memset(afl->var_bytes + old_map_size, 0, new_map_size - old_map_size); + memset(afl->top_rated + old_map_size, 0, new_map_size - old_map_size); + memset(afl->clean_trace + old_map_size, 0, new_map_size - old_map_size); + memset(afl->clean_trace_custom + old_map_size, 0, + new_map_size - old_map_size); + memset(afl->first_trace + old_map_size, 0, new_map_size - old_map_size); + memset(afl->map_tmp_buf + old_map_size, 0, new_map_size - old_map_size); + + } + afl_fsrv_kill(&afl->fsrv); afl_fsrv_kill(&afl->cmplog_fsrv); afl_shm_deinit(&afl->shm); -- cgit v1.2.3 From f516926f006545d45162eaef723d786a427721f8 Mon Sep 17 00:00:00 2001 From: Moshe Kaplan Date: Thu, 4 May 2023 11:23:30 -0400 Subject: afl-fuzz.c: Document -i - in --help (#1725) afl-fuzz.c: Document `-i -` in `--help`, to write that `-i` can be passed '-' to resume the prior fuzzing job. Also reference AFL_AUTORESUME so users know they can set that parameter to sidestep the issue entirely. --- src/afl-fuzz.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index c02479cf..c5206282 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -124,7 +124,7 @@ static void usage(u8 *argv0, int more_help) { "\n%s [ options ] -- /path/to/fuzzed_app [ ... ]\n\n" "Required parameters:\n" - " -i dir - input directory with test cases\n" + " -i dir - input directory with test cases (or '-' to resume, also see AFL_AUTORESUME)\n" " -o dir - output directory for fuzzer findings\n\n" "Execution control settings:\n" -- cgit v1.2.3 From 396157dedae2049f830c49eb81ef9617275333ee Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 5 May 2023 13:52:54 +0200 Subject: tritondse custom mutator attempt --- src/afl-fuzz-one.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index a9902087..c6e9a295 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2048,20 +2048,22 @@ custom_mutator_stage: afl->queue_cur->stats_mutated += afl->stage_max; #endif - if (likely(afl->custom_only)) { + /**************** + * RANDOM HAVOC * + ****************/ + +havoc_stage: + + if (unlikely(afl->custom_only)) { + /* Force UI update */ + show_stats(afl); /* Skip other stages */ ret_val = 0; goto abandon_entry; } - /**************** - * RANDOM HAVOC * - ****************/ - -havoc_stage: - afl->stage_cur_byte = -1; /* The havoc stage mutation code is also invoked when splicing files; if the -- cgit v1.2.3 From c97caa6e1095a4bce8f0c32108e6e33f7ac240e4 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 9 May 2023 14:17:09 +0200 Subject: fix makefile --- src/afl-fuzz.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index c5206282..f982258f 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -124,7 +124,8 @@ static void usage(u8 *argv0, int more_help) { "\n%s [ options ] -- /path/to/fuzzed_app [ ... ]\n\n" "Required parameters:\n" - " -i dir - input directory with test cases (or '-' to resume, also see AFL_AUTORESUME)\n" + " -i dir - input directory with test cases (or '-' to resume, " + "also see AFL_AUTORESUME)\n" " -o dir - output directory for fuzzer findings\n\n" "Execution control settings:\n" -- cgit v1.2.3 From 70da0c2e405102dc044cb4bed0f4f1e847c90d0b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 10 May 2023 16:09:18 +0200 Subject: better tritondse support --- src/afl-fuzz.c | 91 +++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 68 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index f982258f..4339ddd2 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1530,29 +1530,6 @@ int main(int argc, char **argv_orig, char **envp) { } - if (afl->limit_time_sig > 0 && afl->custom_mutators_count) { - - if (afl->custom_only) { - - FATAL("Custom mutators are incompatible with MOpt (-L)"); - - } - - u32 custom_fuzz = 0; - LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { - - if (el->afl_custom_fuzz) { custom_fuzz = 1; } - - }); - - if (custom_fuzz) { - - WARNF("afl_custom_fuzz is incompatible with MOpt (-L)"); - - } - - } - if (afl->afl_env.afl_max_det_extras) { s32 max_det_extras = atoi(afl->afl_env.afl_max_det_extras); @@ -1827,8 +1804,76 @@ int main(int argc, char **argv_orig, char **envp) { printf("DEBUG: rand %06d is %u\n", counter, rand_below(afl, 65536)); #endif + if (!getenv("AFL_CUSTOM_INFO_PROGRAM")) { + + setenv("AFL_CUSTOM_INFO_PROGRAM", argv[optind], 1); + + } + + if (!getenv("AFL_CUSTOM_INFO_PROGRAM_INPUT") && afl->fsrv.out_file) { + + setenv("AFL_CUSTOM_INFO_PROGRAM_INPUT", afl->fsrv.out_file, 1); + + } + + { + + u8 envbuf[8096] = "", tmpbuf[8096] = ""; + for (s32 i = optind + 1; i < argc; ++i) { + + strcpy(tmpbuf, envbuf); + if (strchr(argv[i], ' ') && !strchr(argv[i], '"') && + !strchr(argv[i], '\'')) { + + if (!strchr(argv[i], '\'')) { + + snprintf(envbuf, sizeof(tmpbuf), "%s '%s'", tmpbuf, argv[i]); + + } else { + + snprintf(envbuf, sizeof(tmpbuf), "%s \"%s\"", tmpbuf, argv[i]); + + } + + } else { + + snprintf(envbuf, sizeof(tmpbuf), "%s %s", tmpbuf, argv[i]); + + } + + } + + setenv("AFL_CUSTOM_INFO_PROGRAM_ARGV", envbuf + 1, 1); + + } + + setenv("AFL_CUSTOM_INFO_OUT", afl->out_dir, 1); // same as __AFL_OUT_DIR + setup_custom_mutators(afl); + if (afl->limit_time_sig > 0 && afl->custom_mutators_count) { + + if (afl->custom_only) { + + FATAL("Custom mutators are incompatible with MOpt (-L)"); + + } + + u32 custom_fuzz = 0; + LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { + + if (el->afl_custom_fuzz) { custom_fuzz = 1; } + + }); + + if (custom_fuzz) { + + WARNF("afl_custom_fuzz is incompatible with MOpt (-L)"); + + } + + } + write_setup_file(afl, argc, argv); setup_cmdline_file(afl, argv + optind); -- cgit v1.2.3 From 93c821aaa3df0cf20f892ce72447ff022161c8ab Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 12 May 2023 08:39:11 +0200 Subject: afl-clang-lto incomptable with -flto=thin --- src/afl-cc.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 19314555..13ca751e 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -853,6 +853,15 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (cur[0] != '-') { non_dash = 1; } if (!strncmp(cur, "--afl", 5)) continue; + + if (lto_mode && !strncmp(cur, "-flto=thin", 10)) { + + FATAL( + "afl-clang-lto cannot work with -flto=thin. Switch to -flto=full or " + "use afl-clang-fast!"); + + } + if (lto_mode && !strncmp(cur, "-fuse-ld=", 9)) continue; if (lto_mode && !strncmp(cur, "--ld-path=", 10)) continue; if (!strncmp(cur, "-fno-unroll", 11)) continue; -- cgit v1.2.3 From 7f636dbfc247fbe75910fa8fb681ea55d230ba79 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 12 May 2023 15:58:20 +0200 Subject: add @responsefile support for afl-cc --- src/afl-cc.c | 460 ++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 299 insertions(+), 161 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 13ca751e..972ac8cd 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include #if (LLVM_MAJOR - 0 == 0) #undef LLVM_MAJOR @@ -376,15 +378,304 @@ void parse_fsanitize(char *string) { } +static u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0, + shared_linking = 0, preprocessor_only = 0, have_unroll = 0, + have_o = 0, have_pic = 0, have_c = 0, partial_linking = 0, + non_dash = 0; + +static void process_params(u32 argc, char **argv) { + + if (cc_par_cnt + argc >= 1024) { FATAL("Too many command line parameters"); } + + if (lto_mode && argc > 1) { + + u32 idx; + for (idx = 1; idx < argc; idx++) { + + if (!strncasecmp(argv[idx], "-fpic", 5)) have_pic = 1; + + } + + } + + // for (u32 x = 0; x < argc; ++x) fprintf(stderr, "[%u] %s\n", x, argv[x]); + + /* Process the argument list. */ + + u8 skip_next = 0; + while (--argc) { + + u8 *cur = *(++argv); + + if (skip_next) { + + skip_next = 0; + continue; + + } + + if (cur[0] != '-') { non_dash = 1; } + if (!strncmp(cur, "--afl", 5)) continue; + + if (lto_mode && !strncmp(cur, "-flto=thin", 10)) { + + FATAL( + "afl-clang-lto cannot work with -flto=thin. Switch to -flto=full or " + "use afl-clang-fast!"); + + } + + if (lto_mode && !strncmp(cur, "-fuse-ld=", 9)) continue; + if (lto_mode && !strncmp(cur, "--ld-path=", 10)) continue; + if (!strncmp(cur, "-fno-unroll", 11)) continue; + if (strstr(cur, "afl-compiler-rt") || strstr(cur, "afl-llvm-rt")) continue; + if (!strcmp(cur, "-Wl,-z,defs") || !strcmp(cur, "-Wl,--no-undefined") || + !strcmp(cur, "--no-undefined")) { + + continue; + + } + + if (compiler_mode == GCC_PLUGIN && !strcmp(cur, "-pipe")) { continue; } + + if (!strcmp(cur, "-z") || !strcmp(cur, "-Wl,-z")) { + + u8 *param = *(argv + 1); + if (!strcmp(param, "defs") || !strcmp(param, "-Wl,defs")) { + + skip_next = 1; + continue; + + } + + } + + if ((compiler_mode == GCC || compiler_mode == GCC_PLUGIN) && + !strncmp(cur, "-stdlib=", 8)) { + + if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); } + continue; + + } + + if (!strncmp(cur, "-fsanitize-coverage-", 20) && strstr(cur, "list=")) { + + have_instr_list = 1; + + } + + if (!strncmp(cur, "-fsanitize=", strlen("-fsanitize=")) && + strchr(cur, ',')) { + + parse_fsanitize(cur); + if (!cur || strlen(cur) <= strlen("-fsanitize=")) { continue; } + + } else if ((!strncmp(cur, "-fsanitize=fuzzer-", + + strlen("-fsanitize=fuzzer-")) || + !strncmp(cur, "-fsanitize-coverage", + strlen("-fsanitize-coverage"))) && + (strncmp(cur, "sanitize-coverage-allow", + strlen("sanitize-coverage-allow")) && + strncmp(cur, "sanitize-coverage-deny", + strlen("sanitize-coverage-deny")) && + instrument_mode != INSTRUMENT_LLVMNATIVE)) { + + if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); } + continue; + + } + + if (need_aflpplib || !strcmp(cur, "-fsanitize=fuzzer")) { + + u8 *afllib = find_object("libAFLDriver.a", argv[0]); + + if (!be_quiet) { + + OKF("Found '-fsanitize=fuzzer', replacing with libAFLDriver.a"); + + } + + if (!afllib) { + + if (!be_quiet) { + + WARNF( + "Cannot find 'libAFLDriver.a' to replace '-fsanitize=fuzzer' in " + "the flags - this will fail!"); + + } + + } else { + + cc_params[cc_par_cnt++] = afllib; + +#ifdef __APPLE__ + cc_params[cc_par_cnt++] = "-undefined"; + cc_params[cc_par_cnt++] = "dynamic_lookup"; +#endif + + } + + if (need_aflpplib) { + + need_aflpplib = 0; + + } else { + + continue; + + } + + } + + if (!strcmp(cur, "-m32")) bit_mode = 32; + if (!strcmp(cur, "armv7a-linux-androideabi")) bit_mode = 32; + if (!strcmp(cur, "-m64")) bit_mode = 64; + + if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory")) + asan_set = 1; + + if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1; + + if (!strcmp(cur, "-x")) x_set = 1; + if (!strcmp(cur, "-E")) preprocessor_only = 1; + if (!strcmp(cur, "-shared")) shared_linking = 1; + if (!strcmp(cur, "-dynamiclib")) shared_linking = 1; + if (!strcmp(cur, "--target=wasm32-wasi")) passthrough = 1; + if (!strcmp(cur, "-Wl,-r")) partial_linking = 1; + if (!strcmp(cur, "-Wl,-i")) partial_linking = 1; + if (!strcmp(cur, "-Wl,--relocatable")) partial_linking = 1; + if (!strcmp(cur, "-r")) partial_linking = 1; + if (!strcmp(cur, "--relocatable")) partial_linking = 1; + if (!strcmp(cur, "-c")) have_c = 1; + + if (!strncmp(cur, "-O", 2)) have_o = 1; + if (!strncmp(cur, "-funroll-loop", 13)) have_unroll = 1; + + if (*cur == '@') { + + // response file support. + // we have two choices - move everything to the command line or + // rewrite the response files to temporary files and delete them + // afterwards. We choose the first for easiness. + // We do *not* support quotes in the rsp files to cope with spaces in + // filenames etc! If you need that then send a patch! + u8 *filename = cur + 1; + if (debug) { DEBUGF("response file=%s\n", filename); } + FILE *f = fopen(filename, "r"); + struct stat st; + + // Check not found or empty? let the compiler complain if so. + if (!f || fstat(fileno(f), &st) < 0 || st.st_size < 1) { + + cc_params[cc_par_cnt++] = cur; + continue; + + } + + u8 *tmpbuf = malloc(st.st_size + 1), *ptr; + char **args = malloc(sizeof(char *) * (st.st_size >> 1)); + int count = 1, cont = 0, cont_act = 0; + + while (fgets(tmpbuf, st.st_size, f)) { + + ptr = tmpbuf; + // no leading whitespace + while (isspace(*ptr)) { + + ++ptr; + cont_act = 0; + + } + + // no comments, no empty lines + if (*ptr == '#' || *ptr == '\n' || !*ptr) { continue; } + // remove LF + if (ptr[strlen(ptr) - 1] == '\n') { ptr[strlen(ptr) - 1] = 0; } + // remove CR + if (*ptr && ptr[strlen(ptr) - 1] == '\r') { ptr[strlen(ptr) - 1] = 0; } + // handle \ at end of line + if (*ptr && ptr[strlen(ptr) - 1] == '\\') { + + cont = 1; + ptr[strlen(ptr) - 1] = 0; + + } + + // remove whitespace at end + while (*ptr && isspace(ptr[strlen(ptr) - 1])) { + + ptr[strlen(ptr) - 1] = 0; + cont = 0; + + } + + if (*ptr) { + + do { + + u8 *value = ptr; + while (*ptr && !isspace(*ptr)) { + + ++ptr; + + } + + while (*ptr && isspace(*ptr)) { + + *ptr++ = 0; + + } + + if (cont_act) { + + u32 len = strlen(args[count - 1]) + strlen(value) + 1; + u8 *tmp = malloc(len); + snprintf(tmp, len, "%s%s", args[count - 1], value); + free(args[count - 1]); + args[count - 1] = tmp; + cont_act = 0; + + } else { + + args[count++] = strdup(value); + + } + + } while (*ptr); + + } + + if (cont) { + + cont_act = 1; + cont = 0; + + } + + } + + if (count) { process_params(count, args); } + + // we cannot free args[] + free(tmpbuf); + + continue; + + } + + cc_params[cc_par_cnt++] = cur; + + } + +} + /* Copy argv to cc_params, making the necessary edits. */ static void edit_params(u32 argc, char **argv, char **envp) { - u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0, shared_linking = 0, - preprocessor_only = 0, have_unroll = 0, have_o = 0, have_pic = 0, - have_c = 0, partial_linking = 0; - - cc_params = ck_alloc((argc + 128) * sizeof(u8 *)); + cc_params = ck_alloc(1024 * sizeof(u8 *)); if (lto_mode) { @@ -831,168 +1122,15 @@ static void edit_params(u32 argc, char **argv, char **envp) { } - if (!have_pic) cc_params[cc_par_cnt++] = "-fPIC"; - } } - /* Detect stray -v calls from ./configure scripts. */ - - u8 skip_next = 0, non_dash = 0; - while (--argc) { - - u8 *cur = *(++argv); - - if (skip_next) { - - skip_next = 0; - continue; - - } - - if (cur[0] != '-') { non_dash = 1; } - if (!strncmp(cur, "--afl", 5)) continue; - - if (lto_mode && !strncmp(cur, "-flto=thin", 10)) { - - FATAL( - "afl-clang-lto cannot work with -flto=thin. Switch to -flto=full or " - "use afl-clang-fast!"); - - } - - if (lto_mode && !strncmp(cur, "-fuse-ld=", 9)) continue; - if (lto_mode && !strncmp(cur, "--ld-path=", 10)) continue; - if (!strncmp(cur, "-fno-unroll", 11)) continue; - if (strstr(cur, "afl-compiler-rt") || strstr(cur, "afl-llvm-rt")) continue; - if (!strcmp(cur, "-Wl,-z,defs") || !strcmp(cur, "-Wl,--no-undefined") || - !strcmp(cur, "--no-undefined")) { - - continue; - - } + /* Inspect the command line parameters. */ - if (compiler_mode == GCC_PLUGIN && !strcmp(cur, "-pipe")) { continue; } - - if (!strcmp(cur, "-z") || !strcmp(cur, "-Wl,-z")) { + process_params(argc, argv); - u8 *param = *(argv + 1); - if (!strcmp(param, "defs") || !strcmp(param, "-Wl,defs")) { - - skip_next = 1; - continue; - - } - - } - - if ((compiler_mode == GCC || compiler_mode == GCC_PLUGIN) && - !strncmp(cur, "-stdlib=", 8)) { - - if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); } - continue; - - } - - if (!strncmp(cur, "-fsanitize-coverage-", 20) && strstr(cur, "list=")) { - - have_instr_list = 1; - - } - - if (!strncmp(cur, "-fsanitize=", strlen("-fsanitize=")) && - strchr(cur, ',')) { - - parse_fsanitize(cur); - if (!cur || strlen(cur) <= strlen("-fsanitize=")) { continue; } - - } else if ((!strncmp(cur, "-fsanitize=fuzzer-", - - strlen("-fsanitize=fuzzer-")) || - !strncmp(cur, "-fsanitize-coverage", - strlen("-fsanitize-coverage"))) && - (strncmp(cur, "sanitize-coverage-allow", - strlen("sanitize-coverage-allow")) && - strncmp(cur, "sanitize-coverage-deny", - strlen("sanitize-coverage-deny")) && - instrument_mode != INSTRUMENT_LLVMNATIVE)) { - - if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); } - continue; - - } - - if (need_aflpplib || !strcmp(cur, "-fsanitize=fuzzer")) { - - u8 *afllib = find_object("libAFLDriver.a", argv[0]); - - if (!be_quiet) { - - OKF("Found '-fsanitize=fuzzer', replacing with libAFLDriver.a"); - - } - - if (!afllib) { - - if (!be_quiet) { - - WARNF( - "Cannot find 'libAFLDriver.a' to replace '-fsanitize=fuzzer' in " - "the flags - this will fail!"); - - } - - } else { - - cc_params[cc_par_cnt++] = afllib; - -#ifdef __APPLE__ - cc_params[cc_par_cnt++] = "-undefined"; - cc_params[cc_par_cnt++] = "dynamic_lookup"; -#endif - - } - - if (need_aflpplib) { - - need_aflpplib = 0; - - } else { - - continue; - - } - - } - - if (!strcmp(cur, "-m32")) bit_mode = 32; - if (!strcmp(cur, "armv7a-linux-androideabi")) bit_mode = 32; - if (!strcmp(cur, "-m64")) bit_mode = 64; - - if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory")) - asan_set = 1; - - if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1; - - if (!strcmp(cur, "-x")) x_set = 1; - if (!strcmp(cur, "-E")) preprocessor_only = 1; - if (!strcmp(cur, "-shared")) shared_linking = 1; - if (!strcmp(cur, "-dynamiclib")) shared_linking = 1; - if (!strcmp(cur, "--target=wasm32-wasi")) passthrough = 1; - if (!strcmp(cur, "-Wl,-r")) partial_linking = 1; - if (!strcmp(cur, "-Wl,-i")) partial_linking = 1; - if (!strcmp(cur, "-Wl,--relocatable")) partial_linking = 1; - if (!strcmp(cur, "-r")) partial_linking = 1; - if (!strcmp(cur, "--relocatable")) partial_linking = 1; - if (!strcmp(cur, "-c")) have_c = 1; - - if (!strncmp(cur, "-O", 2)) have_o = 1; - if (!strncmp(cur, "-funroll-loop", 13)) have_unroll = 1; - - cc_params[cc_par_cnt++] = cur; - - } + if (!have_pic) { cc_params[cc_par_cnt++] = "-fPIC"; } // in case LLVM is installed not via a package manager or "make install" // e.g. compiled download or compiled from github then its ./lib directory -- cgit v1.2.3 From abd6eace9d767e4db6019e8eb69080d2352015c9 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 18 May 2023 10:32:15 +0200 Subject: improved symqemu custom mutator --- src/afl-fuzz-one.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index c6e9a295..5c71fc59 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -1912,6 +1912,7 @@ custom_mutator_stage: afl->stage_name = "custom mutator"; afl->stage_short = "custom"; + afl->stage_cur = 0; afl->stage_val_type = STAGE_VAL_NONE; bool has_custom_fuzz = false; u32 shift = unlikely(afl->custom_only) ? 7 : 8; -- cgit v1.2.3 From 401d7617efbd2f38d9132eabfd1b1152abceda52 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 18 May 2023 10:50:10 +0200 Subject: symqemu mutator options --- src/afl-common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-common.c b/src/afl-common.c index a5c48e80..84ddefd8 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -949,7 +949,7 @@ void read_bitmap(u8 *fname, u8 *map, size_t len) { /* Get unix time in milliseconds */ -u64 get_cur_time(void) { +inline u64 get_cur_time(void) { struct timeval tv; struct timezone tz; -- cgit v1.2.3 From 53a869b757287e8bebdfcbc96b8abe1729955171 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 18 May 2023 14:45:45 +0200 Subject: act on invalid AFL_CUSTOM_MUTATOR_ONLY usage --- src/afl-fuzz.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 4339ddd2..e2d8dea5 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1748,6 +1748,23 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->afl_env.afl_custom_mutator_only) { + if (!afl->custom_mutators_count) { + + if (afl->shm.cmplog_mode) { + + WARNF( + "No custom mutator loaded, using AFL_CUSTOM_MUTATOR_ONLY is " + "pointless and only allowed now to allow experiments with CMPLOG."); + + } else { + + FATAL( + "No custom mutator loaded but AFL_CUSTOM_MUTATOR_ONLY specified."); + + } + + } + /* This ensures we don't proceed to havoc/splice */ afl->custom_only = 1; -- cgit v1.2.3 From 9a6c0ec0c0af42d33e4350ee2958b58fef1c39dd Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 21 May 2023 13:04:17 +0200 Subject: make AFL_CUSTOM_INFO overridable --- src/afl-fuzz.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index e2d8dea5..a61718a7 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1833,7 +1833,7 @@ int main(int argc, char **argv_orig, char **envp) { } - { + if (!getenv("AFL_CUSTOM_INFO_PROGRAM_ARGV")) { u8 envbuf[8096] = "", tmpbuf[8096] = ""; for (s32 i = optind + 1; i < argc; ++i) { @@ -1864,7 +1864,11 @@ int main(int argc, char **argv_orig, char **envp) { } - setenv("AFL_CUSTOM_INFO_OUT", afl->out_dir, 1); // same as __AFL_OUT_DIR + if (!getenv("AFL_CUSTOM_INFO_OUT") { + + setenv("AFL_CUSTOM_INFO_OUT", afl->out_dir, 1); // same as __AFL_OUT_DIR + + } setup_custom_mutators(afl); -- cgit v1.2.3 From d4085314c1c1d4e8bbe4159216f8cb83e0804ea7 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 21 May 2023 13:44:07 +0200 Subject: fix --- src/afl-fuzz.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index a61718a7..559a7326 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1864,7 +1864,7 @@ int main(int argc, char **argv_orig, char **envp) { } - if (!getenv("AFL_CUSTOM_INFO_OUT") { + if (!getenv("AFL_CUSTOM_INFO_OUT")) { setenv("AFL_CUSTOM_INFO_OUT", afl->out_dir, 1); // same as __AFL_OUT_DIR -- cgit v1.2.3 From 029e039cbcbf9e30f35eb255162679b8d609d25d Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 21 May 2023 17:49:14 +0200 Subject: code format --- src/afl-cc.c | 8 ++++---- src/afl-fuzz-redqueen.c | 32 ++++++++++++++++---------------- 2 files changed, 20 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 972ac8cd..e3cc04dd 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -933,10 +933,10 @@ static void edit_params(u32 argc, char **argv, char **envp) { } - //#if LLVM_MAJOR >= 13 - // // Use the old pass manager in LLVM 14 which the AFL++ passes still - // use. cc_params[cc_par_cnt++] = "-flegacy-pass-manager"; - //#endif + // #if LLVM_MAJOR >= 13 + // // Use the old pass manager in LLVM 14 which the AFL++ passes still + // use. cc_params[cc_par_cnt++] = "-flegacy-pass-manager"; + // #endif if (lto_mode && !have_c) { diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 6e4a655b..d9dc50df 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -28,8 +28,8 @@ #include "afl-fuzz.h" #include "cmplog.h" -//#define _DEBUG -//#define CMPLOG_INTROSPECTION +// #define _DEBUG +// #define CMPLOG_INTROSPECTION // CMP attribute enum enum { @@ -571,7 +571,7 @@ static u8 its_fuzz(afl_state_t *afl, u8 *buf, u32 len, u8 *status) { } -//#ifdef CMPLOG_SOLVE_TRANSFORM +// #ifdef CMPLOG_SOLVE_TRANSFORM static int strntoll(const char *str, size_t sz, char **end, int base, long long *out) { @@ -771,7 +771,7 @@ static void to_base64(u8 *src, u8 *dst, u32 dst_len) { #endif -//#endif +// #endif static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, u64 pattern, u64 repl, u64 o_pattern, @@ -803,8 +803,8 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, // o_pattern, pattern, repl, changed_val, idx, taint_len, // hshape, attr); - //#ifdef CMPLOG_SOLVE_TRANSFORM - // reverse atoi()/strnu?toll() is expensive, so we only to it in lvl 3 + // #ifdef CMPLOG_SOLVE_TRANSFORM + // reverse atoi()/strnu?toll() is expensive, so we only to it in lvl 3 if (afl->cmplog_enable_transform && (lvl & LVL3)) { u8 *endptr; @@ -1120,7 +1120,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, } - //#endif + // #endif // we only allow this for ascii2integer (above) so leave if this is the case if (unlikely(pattern == o_pattern)) { return 0; } @@ -1275,7 +1275,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, // 16 = modified float, 32 = modified integer (modified = wont match // in original buffer) - //#ifdef CMPLOG_SOLVE_ARITHMETIC + // #ifdef CMPLOG_SOLVE_ARITHMETIC if (!afl->cmplog_enable_arith || lvl < LVL3 || attr == IS_TRANSFORM) { return 0; @@ -1440,8 +1440,8 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, } - //#endif /* - // CMPLOG_SOLVE_ARITHMETIC + // #endif /* + // CMPLOG_SOLVE_ARITHMETIC return 0; @@ -1948,9 +1948,9 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, #ifndef CMPLOG_COMBINE (void)(cbuf); #endif - //#ifndef CMPLOG_SOLVE_TRANSFORM - // (void)(changed_val); - //#endif + // #ifndef CMPLOG_SOLVE_TRANSFORM + // (void)(changed_val); + // #endif if (afl->fsrv.total_execs - last_update > screen_update) { @@ -2418,7 +2418,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, } - //#endif + // #endif return 0; @@ -2818,9 +2818,9 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) { } else if ((lvl & LVL1) - //#ifdef CMPLOG_SOLVE_TRANSFORM + // #ifdef CMPLOG_SOLVE_TRANSFORM || ((lvl & LVL3) && afl->cmplog_enable_transform) - //#endif + // #endif ) { if (unlikely(rtn_fuzz(afl, k, orig_buf, buf, cbuf, len, lvl, taint))) { -- cgit v1.2.3 From d5e3223f0340181e74d352db3def2c98cf14d628 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 23 May 2023 09:01:49 +0200 Subject: fix custom mutator only check --- src/afl-fuzz.c | 54 +++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 559a7326..4134b99e 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1746,33 +1746,6 @@ int main(int argc, char **argv_orig, char **envp) { check_if_tty(afl); if (afl->afl_env.afl_force_ui) { afl->not_on_tty = 0; } - if (afl->afl_env.afl_custom_mutator_only) { - - if (!afl->custom_mutators_count) { - - if (afl->shm.cmplog_mode) { - - WARNF( - "No custom mutator loaded, using AFL_CUSTOM_MUTATOR_ONLY is " - "pointless and only allowed now to allow experiments with CMPLOG."); - - } else { - - FATAL( - "No custom mutator loaded but AFL_CUSTOM_MUTATOR_ONLY specified."); - - } - - } - - /* This ensures we don't proceed to havoc/splice */ - afl->custom_only = 1; - - /* Ensure we also skip all deterministic steps */ - afl->skip_deterministic = 1; - - } - get_core_count(afl); atexit(at_exit); @@ -1872,6 +1845,33 @@ int main(int argc, char **argv_orig, char **envp) { setup_custom_mutators(afl); + if (afl->afl_env.afl_custom_mutator_only) { + + if (!afl->custom_mutators_count) { + + if (afl->shm.cmplog_mode) { + + WARNF( + "No custom mutator loaded, using AFL_CUSTOM_MUTATOR_ONLY is " + "pointless and only allowed now to allow experiments with CMPLOG."); + + } else { + + FATAL( + "No custom mutator loaded but AFL_CUSTOM_MUTATOR_ONLY specified."); + + } + + } + + /* This ensures we don't proceed to havoc/splice */ + afl->custom_only = 1; + + /* Ensure we also skip all deterministic steps */ + afl->skip_deterministic = 1; + + } + if (afl->limit_time_sig > 0 && afl->custom_mutators_count) { if (afl->custom_only) { -- cgit v1.2.3 From dd736126dc9da78d6828cdf76f7eb8b389af7ed3 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 23 May 2023 09:06:29 +0200 Subject: allow llvm_instrument native --- src/afl-cc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index e3cc04dd..64c0ce66 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1838,7 +1838,8 @@ int main(int argc, char **argv, char **envp) { } if (strncasecmp(ptr2, "llvmnative", strlen("llvmnative")) == 0 || - strncasecmp(ptr2, "llvm-native", strlen("llvm-native")) == 0) { + strncasecmp(ptr2, "llvm-native", strlen("llvm-native")) == 0 || + strncasecmp(ptr2, "native", strlen("native")) == 0) { if (!instrument_mode || instrument_mode == INSTRUMENT_LLVMNATIVE) instrument_mode = INSTRUMENT_LLVMNATIVE; -- cgit v1.2.3 From 22837b5ad2d1cc6313c706ac9cb7fcd005cd3c2c Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 23 May 2023 12:14:58 +0200 Subject: response file fix --- src/afl-cc.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 64c0ce66..84fe70ec 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -574,14 +574,15 @@ static void process_params(u32 argc, char **argv) { } - u8 *tmpbuf = malloc(st.st_size + 1), *ptr; + u8 *tmpbuf = malloc(st.st_size + 2), *ptr; char **args = malloc(sizeof(char *) * (st.st_size >> 1)); int count = 1, cont = 0, cont_act = 0; - while (fgets(tmpbuf, st.st_size, f)) { + while (fgets(tmpbuf, st.st_size + 1, f)) { ptr = tmpbuf; - // no leading whitespace + // fprintf(stderr, "1: %s\n", ptr); + // no leading whitespace while (isspace(*ptr)) { ++ptr; @@ -603,6 +604,8 @@ static void process_params(u32 argc, char **argv) { } + // fprintf(stderr, "2: %s\n", ptr); + // remove whitespace at end while (*ptr && isspace(ptr[strlen(ptr) - 1])) { @@ -611,6 +614,7 @@ static void process_params(u32 argc, char **argv) { } + // fprintf(stderr, "3: %s\n", ptr); if (*ptr) { do { -- cgit v1.2.3 From eeed38c5f8335b5a2b69d85b950aa33682a2c079 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 23 May 2023 18:31:34 +0200 Subject: fix gnumakefile for non-gcc --- src/afl-fuzz-redqueen.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index d9dc50df..7f42db3f 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -379,7 +379,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, } - if (++afl->stage_cur % screen_update == 0) { show_stats(afl); }; + if (unlikely(++afl->stage_cur % screen_update == 0)) { show_stats(afl); }; } @@ -790,7 +790,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, u32 its_len = MIN(len - idx, taint_len); - if (afl->fsrv.total_execs - last_update > screen_update) { + if (unlikely(afl->fsrv.total_execs - last_update > screen_update)) { show_stats(afl); last_update = afl->fsrv.total_execs; @@ -1455,7 +1455,7 @@ static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h, u32 taint_len, u8 *orig_buf, u8 *buf, u8 *cbuf, u32 len, u8 do_reverse, u8 lvl, u8 *status) { - if (afl->fsrv.total_execs - last_update > screen_update) { + if (unlikely(afl->fsrv.total_execs - last_update > screen_update)) { show_stats(afl); last_update = afl->fsrv.total_execs; @@ -1952,7 +1952,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, // (void)(changed_val); // #endif - if (afl->fsrv.total_execs - last_update > screen_update) { + if (unlikely(afl->fsrv.total_execs - last_update > screen_update)) { show_stats(afl); last_update = afl->fsrv.total_execs; @@ -2002,10 +2002,10 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, } - u8 lmax = MAX(l0, ol0); + u8 lmin = MIN(l0, ol0); u8 save[40]; u32 saved_idx = idx, pre, from = 0, to = 0, i, j; - u32 its_len = MIN(MIN(lmax, hshape), len - idx); + u32 its_len = MIN(MIN(lmin, hshape), len - idx); its_len = MIN(its_len, taint_len); u32 saved_its_len = its_len; -- cgit v1.2.3 From c323e0dc63e97299da4a2f775f6f1639d5e13bf0 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 23 May 2023 19:46:35 +0200 Subject: revert fix --- src/afl-fuzz-redqueen.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 7f42db3f..41644cb9 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -2002,10 +2002,10 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, } - u8 lmin = MIN(l0, ol0); + u8 lmax = MAX(l0, ol0); u8 save[40]; u32 saved_idx = idx, pre, from = 0, to = 0, i, j; - u32 its_len = MIN(MIN(lmin, hshape), len - idx); + u32 its_len = MIN(MIN(lmax, hshape), len - idx); its_len = MIN(its_len, taint_len); u32 saved_its_len = its_len; -- cgit v1.2.3 From ad8f7d6eb3be245202ace23d4d1dd9152647a775 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 31 May 2023 11:40:48 +0200 Subject: switch user mailinglist reference to discord --- src/afl-forkserver.c | 8 ++++---- src/afl-fuzz-init.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 30c8901c..7322f1ad 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -1226,7 +1226,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, " - Less likely, there is a horrible bug in the fuzzer. If other " "options\n" - " fail, poke for troubleshooting " + " fail, poke the Awesome Fuzzing Discord for troubleshooting " "tips.\n"); } else { @@ -1271,7 +1271,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, " - Less likely, there is a horrible bug in the fuzzer. If other " "options\n" - " fail, poke for troubleshooting " + " fail, poke the Awesome Fuzzing Discord for troubleshooting " "tips.\n", stringify_mem_size(val_buf, sizeof(val_buf), fsrv->mem_limit << 20), fsrv->mem_limit - 1); @@ -1321,7 +1321,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, " Retry with setting AFL_MAP_SIZE=10000000.\n\n" "Otherwise there is a horrible bug in the fuzzer.\n" - "Poke for troubleshooting tips.\n"); + "Poke the Awesome Fuzzing Discord for troubleshooting tips.\n"); } else { @@ -1370,7 +1370,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, " - Less likely, there is a horrible bug in the fuzzer. If other " "options\n" - " fail, poke for troubleshooting " + " fail, poke the Awesome Fuzzing Discord for troubleshooting " "tips.\n", getenv(DEFER_ENV_VAR) ? " - You are using deferred forkserver, but __AFL_INIT() is " diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index baf56a5f..13802f40 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1012,7 +1012,7 @@ void perform_dry_run(afl_state_t *afl) { " - Least likely, there is a horrible bug in the fuzzer. If " "other options\n" - " fail, poke for " + " fail, poke the Awesome Fuzzing Discord for " "troubleshooting tips.\n", stringify_mem_size(val_buf, sizeof(val_buf), afl->fsrv.mem_limit << 20), @@ -1041,7 +1041,7 @@ void perform_dry_run(afl_state_t *afl) { " - Least likely, there is a horrible bug in the fuzzer. If " "other options\n" - " fail, poke for " + " fail, poke the Awesome Fuzzing Discord for " "troubleshooting tips.\n"); } -- cgit v1.2.3 From 9324f3f6289c62451e2add1f7553a7eda0d7d642 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 1 Jun 2023 12:19:45 +0200 Subject: rewrote PCGUARD --- src/afl-cc.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 84fe70ec..9e56828c 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -997,7 +997,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (instrument_mode == INSTRUMENT_PCGUARD) { -#if LLVM_MAJOR >= 11 +#if LLVM_MAJOR >= 13 #if defined __ANDROID__ || ANDROID cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; instrument_mode = INSTRUMENT_LLVMNATIVE; @@ -1014,7 +1014,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { } else { - #if LLVM_MAJOR >= 11 /* use new pass manager */ + #if LLVM_MAJOR >= 13 /* use new pass manager */ #if LLVM_MAJOR < 16 cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; #endif @@ -1035,12 +1035,12 @@ static void edit_params(u32 argc, char **argv, char **envp) { #if LLVM_MAJOR >= 4 if (!be_quiet) SAYF( - "Using unoptimized trace-pc-guard, upgrade to llvm 10.0.1+ for " + "Using unoptimized trace-pc-guard, upgrade to LLVM 13+ for " "enhanced version.\n"); cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; instrument_mode = INSTRUMENT_LLVMNATIVE; #else - FATAL("pcguard instrumentation requires llvm 4.0.1+"); + FATAL("pcguard instrumentation requires LLVM 4.0.1+"); #endif #endif @@ -1053,7 +1053,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table"; #else - FATAL("pcguard instrumentation with pc-table requires llvm 6.0.1+"); + FATAL("pcguard instrumentation with pc-table requires LLVM 6.0.1+"); #endif } else { @@ -1063,7 +1063,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { } #else - FATAL("pcguard instrumentation requires llvm 4.0.1+"); + FATAL("pcguard instrumentation requires LLVM 4.0.1+"); #endif } else { @@ -2031,7 +2031,7 @@ int main(int argc, char **argv, char **envp) { if (!compiler_mode) { // lto is not a default because outside of afl-cc RANLIB and AR have to - // be set to llvm versions so this would work + // be set to LLVM versions so this would work if (have_llvm) compiler_mode = LLVM; else if (have_gcc_plugin) @@ -2050,6 +2050,17 @@ int main(int argc, char **argv, char **envp) { } + /* if our PCGUARD implementation is not available then silently switch to + native LLVM PCGUARD */ + if (compiler_mode == CLANG && + (instrument_mode == INSTRUMENT_DEFAULT || + instrument_mode == INSTRUMENT_PCGUARD) && + find_object("SanitizerCoveragePCGUARD.so", argv[0]) == NULL) { + + instrument_mode = INSTRUMENT_LLVMNATIVE; + + } + if (compiler_mode == GCC) { if (clang_mode) { @@ -2096,12 +2107,12 @@ int main(int argc, char **argv, char **envp) { "-------------|\n" "MODES: NCC PERSIST DICT LAF " "CMPLOG SELECT\n" - " [LTO] llvm LTO: %s%s\n" + " [LTO] LLVM LTO: %s%s\n" " PCGUARD DEFAULT yes yes yes yes yes " " yes\n" " CLASSIC yes yes yes yes yes " " yes\n" - " [LLVM] llvm: %s%s\n" + " [LLVM] LLVM: %s%s\n" " PCGUARD %s yes yes module yes yes " "yes\n" " CLASSIC %s no yes module yes yes " @@ -2171,7 +2182,7 @@ int main(int argc, char **argv, char **envp) { " (instrumentation/README.lto.md)\n" " PERSIST: persistent mode support [code] (huge speed increase!)\n" " (instrumentation/README.persistent_mode.md)\n" - " DICT: dictionary in the target [yes=automatic or llvm module " + " DICT: dictionary in the target [yes=automatic or LLVM module " "pass]\n" " (instrumentation/README.lto.md + " "instrumentation/README.llvm.md)\n" -- cgit v1.2.3 From 8de7f6131d48e27d53e894b65bd11e0dc3817639 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 6 Jun 2023 13:12:31 +0200 Subject: add current mutation strategy to include --- src/afl-fuzz-one.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index f5ddea0e..312e180d 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2076,7 +2076,7 @@ havoc_stage: where we take the input file and make random stacked tweaks. */ u32 *mutation_array; - u32 stack_max, stack_max_pow = afl->havoc_stack_pow2; + u32 stack_max; // stack_max_pow = afl->havoc_stack_pow2; if (unlikely(afl->text_input || afl->queue_cur->is_ascii)) { // is text? @@ -2104,6 +2104,7 @@ havoc_stage: } + /* if (temp_len < 64) { --stack_max_pow; @@ -2118,7 +2119,9 @@ havoc_stage: } - stack_max = 1 << stack_max_pow; + */ + + stack_max = 1 << (1 + rand_below(afl, afl->havoc_stack_pow2)); // + (afl->extras_cnt ? 2 : 0) + (afl->a_extras_cnt ? 2 : 0); -- cgit v1.2.3 From 14e25340fb7b9e13357a9059dd1c128a2d7d9d5b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 6 Jun 2023 16:55:32 +0200 Subject: comparison --- src/afl-fuzz-one.c | 43 +++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index ec348a95..9d4b366e 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2081,33 +2081,48 @@ havoc_stage: where we take the input file and make random stacked tweaks. */ u32 *mutation_array; - u32 stack_max; // stack_max_pow = afl->havoc_stack_pow2; + u32 stack_max, rand_max; // stack_max_pow = afl->havoc_stack_pow2; - if (unlikely(afl->text_input || afl->queue_cur->is_ascii)) { // is text? + if (unlikely(afl->expand_havoc && afl->ready_for_splicing_count > 1)) { - if (likely(afl->fuzz_mode == 0)) { // is exploration? + mutation_array = full_splice_array; + rand_max = MUT_SPLICE_ARRAY_SIZE; - mutation_array = (unsigned int *)&mutation_strategy_exploration_text; + } else { - } else { // is exploitation! + mutation_array = normal_splice_array; + rand_max = MUT_NORMAL_ARRAY_SIZE; - mutation_array = (unsigned int *)&mutation_strategy_exploitation_text; + } - } + /* + if (unlikely(afl->text_input || afl->queue_cur->is_ascii)) { // is text? + + if (likely(afl->fuzz_mode == 0)) { // is exploration? + + mutation_array = (unsigned int *)&mutation_strategy_exploration_text; + + } else { // is exploitation! - } else { // is binary! + mutation_array = (unsigned int *)&mutation_strategy_exploitation_text; - if (likely(afl->fuzz_mode == 0)) { // is exploration? + } + + } else { // is binary! - mutation_array = (unsigned int *)&mutation_strategy_exploration_binary; + if (likely(afl->fuzz_mode == 0)) { // is exploration? - } else { // is exploitation! + mutation_array = (unsigned int *)&mutation_strategy_exploration_binary; - mutation_array = (unsigned int *)&mutation_strategy_exploitation_binary; + } else { // is exploitation! + + mutation_array = (unsigned int *)&mutation_strategy_exploitation_binary; + + } } - } + */ /* if (temp_len < 64) { @@ -2180,7 +2195,7 @@ havoc_stage: retry_havoc_step : { - u32 r = rand_below(afl, MUT_STRATEGY_ARRAY_SIZE), item; + u32 r = rand_below(afl, rand_max), item; switch (mutation_array[r]) { -- cgit v1.2.3 From c7c6ad1a94810fc4c24fbf05bcdd7f9cf806646e Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 6 Jun 2023 17:04:31 +0200 Subject: no_ui mode --- src/afl-fuzz-one.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index ec348a95..9685885b 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -402,10 +402,11 @@ u8 fuzz_one_original(afl_state_t *afl) { if (unlikely(afl->not_on_tty)) { ACTF( - "Fuzzing test case #%u (%u total, %llu crashes saved, " + "Fuzzing test case #%u (%u total, %llu crashes saved, mode=%s, " "perf_score=%0.0f, weight=%0.0f, favorite=%u, was_fuzzed=%u, " "exec_us=%llu, hits=%u, map=%u, ascii=%u)...", afl->current_entry, afl->queued_items, afl->saved_crashes, + afl->fuzz_mode ? "exploit" : "explore", afl->queue_cur->perf_score, afl->queue_cur->weight, afl->queue_cur->favored, afl->queue_cur->was_fuzzed, afl->queue_cur->exec_us, -- cgit v1.2.3 From c28779adc543ffd3c68696867eef0f719ecee9d4 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 8 Jun 2023 12:32:51 +0200 Subject: show fuzzing state --- src/afl-fuzz-one.c | 5 +++-- src/afl-fuzz-stats.c | 46 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 46 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 9685885b..af5e57a0 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -402,11 +402,12 @@ u8 fuzz_one_original(afl_state_t *afl) { if (unlikely(afl->not_on_tty)) { ACTF( - "Fuzzing test case #%u (%u total, %llu crashes saved, mode=%s, " + "Fuzzing test case #%u (%u total, %llu crashes saved, state: %s, " + "mode=%s, " "perf_score=%0.0f, weight=%0.0f, favorite=%u, was_fuzzed=%u, " "exec_us=%llu, hits=%u, map=%u, ascii=%u)...", afl->current_entry, afl->queued_items, afl->saved_crashes, - afl->fuzz_mode ? "exploit" : "explore", + get_fuzzing_state(afl), afl->fuzz_mode ? "exploit" : "explore", afl->queue_cur->perf_score, afl->queue_cur->weight, afl->queue_cur->favored, afl->queue_cur->was_fuzzed, afl->queue_cur->exec_us, diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 4ffb2536..9a60fd47 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -27,6 +27,45 @@ #include "envs.h" #include +static char fuzzing_state[4][12] = {"started :-)", "in progress", "final phase", + "finished..."}; + +char *get_fuzzing_state(afl_state_t *afl) { + + u64 cur_ms = get_cur_time(); + u64 last_find = cur_ms - afl->last_find_time; + u64 cur_run_time = cur_ms - afl->start_time; + u64 cur_total_run_time = afl->prev_run_time + cur_run_time; + + if (unlikely(cur_run_time < 60 * 3 * 1000 || + cur_total_run_time < 60 * 5 * 1000)) { + + return fuzzing_state[0]; + + } else { + + u64 last_find_100 = 100 * last_find; + u64 percent_cur = last_find_100 / cur_run_time; + u64 percent_total = last_find_100 / cur_total_run_time; + + if (unlikely(percent_cur >= 90 && percent_total >= 90)) { + + return fuzzing_state[3]; + + } else if (unlikely(percent_cur >= 75 && percent_total >= 75)) { + + return fuzzing_state[2]; + + } else { + + return fuzzing_state[1]; + + } + + } + +} + /* Write fuzzer setup file */ void write_setup_file(afl_state_t *afl, u32 argc, char **argv) { @@ -1283,9 +1322,10 @@ void show_stats_normal(afl_state_t *afl) { /* Last line */ - SAYF(SET_G1 "\n" bSTG bLB bH cCYA bSTOP - " strategy:%s %s " bSTG bH20 bH10 bH2 bRB bSTOP cRST RESET_G1, - cPIN, afl->fuzz_mode == 0 ? "explore" : "exploit"); + SAYF(SET_G1 "\n" bSTG bLB bH cCYA bSTOP " strategy:" cPIN + " %s " bSTG bH10 cCYA bSTOP " state:" cPIN + " %s " bSTG bH2 bRB bSTOP cRST RESET_G1, + afl->fuzz_mode == 0 ? "explore" : "exploit", get_fuzzing_state(afl)); #undef IB -- cgit v1.2.3 From 6ec70fc0847a0624692e868743080bf4e6935523 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 9 Jun 2023 09:33:33 +0200 Subject: binary mutations --- src/afl-fuzz-one.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index e722f0c6..816384fd 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2085,6 +2085,8 @@ havoc_stage: u32 *mutation_array; u32 stack_max, rand_max; // stack_max_pow = afl->havoc_stack_pow2; + /* + if (unlikely(afl->expand_havoc && afl->ready_for_splicing_count > 1)) { mutation_array = full_splice_array; @@ -2097,6 +2099,8 @@ havoc_stage: } + */ + /* if (unlikely(afl->text_input || afl->queue_cur->is_ascii)) { // is text? @@ -2112,15 +2116,21 @@ havoc_stage: } else { // is binary! - if (likely(afl->fuzz_mode == 0)) { // is exploration? + */ - mutation_array = (unsigned int *)&mutation_strategy_exploration_binary; + rand_max = MUT_STRATEGY_ARRAY_SIZE; - } else { // is exploitation! + if (likely(afl->fuzz_mode == 0)) { // is exploration? - mutation_array = (unsigned int *)&mutation_strategy_exploitation_binary; + mutation_array = (unsigned int *)&mutation_strategy_exploration_binary; - } + } else { // is exploitation! + + mutation_array = (unsigned int *)&mutation_strategy_exploitation_binary; + + } + + /* } -- cgit v1.2.3 From 25eba95bbaf58539c65088fc8bc143ed30ad82b9 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 12 Jun 2023 08:43:30 +0200 Subject: update new feature config --- src/afl-fuzz-stats.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 9a60fd47..1499a7e4 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -48,11 +48,11 @@ char *get_fuzzing_state(afl_state_t *afl) { u64 percent_cur = last_find_100 / cur_run_time; u64 percent_total = last_find_100 / cur_total_run_time; - if (unlikely(percent_cur >= 90 && percent_total >= 90)) { + if (unlikely(percent_cur >= 80 && percent_total >= 80)) { return fuzzing_state[3]; - } else if (unlikely(percent_cur >= 75 && percent_total >= 75)) { + } else if (unlikely(percent_cur >= 55 && percent_total >= 55)) { return fuzzing_state[2]; -- cgit v1.2.3 From ed97dbacef98c379d7028514a43c799c86050584 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 12 Jun 2023 09:13:24 +0200 Subject: enable text mode --- src/afl-fuzz-one.c | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 816384fd..4efc661e 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2101,40 +2101,33 @@ havoc_stage: */ - /* - if (unlikely(afl->text_input || afl->queue_cur->is_ascii)) { // is text? - - if (likely(afl->fuzz_mode == 0)) { // is exploration? + rand_max = MUT_STRATEGY_ARRAY_SIZE; - mutation_array = (unsigned int *)&mutation_strategy_exploration_text; + if (unlikely(afl->text_input /*|| afl->queue_cur->is_ascii*/)) { // is text? - } else { // is exploitation! + if (likely(afl->fuzz_mode == 0)) { // is exploration? - mutation_array = (unsigned int *)&mutation_strategy_exploitation_text; + mutation_array = (unsigned int *)&mutation_strategy_exploration_text; - } + } else { // is exploitation! - } else { // is binary! + mutation_array = (unsigned int *)&mutation_strategy_exploitation_text; - */ - - rand_max = MUT_STRATEGY_ARRAY_SIZE; - - if (likely(afl->fuzz_mode == 0)) { // is exploration? + } - mutation_array = (unsigned int *)&mutation_strategy_exploration_binary; + } else { // is binary! - } else { // is exploitation! + if (likely(afl->fuzz_mode == 0)) { // is exploration? - mutation_array = (unsigned int *)&mutation_strategy_exploitation_binary; + mutation_array = (unsigned int *)&mutation_strategy_exploration_binary; - } + } else { // is exploitation! - /* + mutation_array = (unsigned int *)&mutation_strategy_exploitation_binary; } - */ + } /* if (temp_len < 64) { -- cgit v1.2.3 From a36034424779d8c9769819ee525b321bfd64a26c Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 14 Jun 2023 13:11:44 +0200 Subject: minor cmplog bugfix --- src/afl-fuzz-redqueen.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 41644cb9..73e188e7 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -1988,10 +1988,10 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, if (l0 >= 0x80 || ol0 >= 0x80) { - l0 -= 0x80; - l1 -= 0x80; - ol0 -= 0x80; - ol1 -= 0x80; + if (l0 >= 0x80) { l0 -= 0x80; } + if (l1 >= 0x80) { l1 -= 0x80; } + if (ol0 >= 0x80) { ol0 -= 0x80; } + if (ol1 >= 0x80) { ol1 -= 0x80; } } @@ -2059,7 +2059,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, for (i = 0; i < its_len; ++i) { - if ((pattern[i] != buf[idx + i] && o_pattern[i] != orig_buf[idx + i]) || + if ((pattern[i] != buf[idx + i] || o_pattern[i] != orig_buf[idx + i]) || *status == 1) { break; @@ -2592,6 +2592,8 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, // shape_len), check_if_text_buf((u8 *)&o->v1, shape_len), v0_len, // o->v0, v1_len, o->v1); + // Note that this check differs from the line 1901, for RTN we are more + // opportunistic for adding to the dictionary than cmps if (!memcmp(o->v0, orig_o->v0, v0_len) || (!found_one || check_if_text_buf((u8 *)&o->v0, v0_len) == v0_len)) maybe_add_auto(afl, o->v0, v0_len); -- cgit v1.2.3 From 7b29f2cd244424c5385605d1302b68be44e432bc Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 20 Jun 2023 19:58:08 +0200 Subject: fix timeout for sessions restart and + usage --- src/afl-fuzz-stats.c | 14 ++++++-------- src/afl-fuzz.c | 1 + 2 files changed, 7 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 1499a7e4..389b82fc 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -2303,7 +2303,12 @@ void show_init_stats(afl_state_t *afl) { stringify_int(IB(0), min_us), stringify_int(IB(1), max_us), stringify_int(IB(2), avg_us)); - if (afl->timeout_given != 1) { + if (afl->timeout_given == 3) { + + ACTF("Applying timeout settings from resumed session (%u ms).", + afl->fsrv.exec_tmout); + + } else if (afl->timeout_given != 1) { /* Figure out the appropriate timeout. The basic idea is: 5x average or 1x max, rounded up to EXEC_TM_ROUND ms and capped at 1 second. @@ -2345,13 +2350,6 @@ void show_init_stats(afl_state_t *afl) { afl->timeout_given = 1; - } else if (afl->timeout_given == 3) { - - ACTF("Applying timeout settings from resumed session (%u ms).", - afl->fsrv.exec_tmout); - - } else { - ACTF("-t option specified. We'll use an exec timeout of %u ms.", afl->fsrv.exec_tmout); diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index d727fff5..9eabfae1 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2362,6 +2362,7 @@ int main(int argc, char **argv_orig, char **envp) { max_ms = afl->queue_buf[entry]->exec_us; afl->fsrv.exec_tmout = max_ms; + afl->timeout_given = 1; } -- cgit v1.2.3 From 2366c00235692c9ae11921cf38e9f6fe3fb30142 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 21 Jun 2023 09:38:21 +0200 Subject: switch back to normal mutations --- src/afl-fuzz-one.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 4efc661e..32c05182 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2103,11 +2103,21 @@ havoc_stage: rand_max = MUT_STRATEGY_ARRAY_SIZE; - if (unlikely(afl->text_input /*|| afl->queue_cur->is_ascii*/)) { // is text? + if (unlikely(afl->text_input)) { // is text? if (likely(afl->fuzz_mode == 0)) { // is exploration? - mutation_array = (unsigned int *)&mutation_strategy_exploration_text; + if (unlikely(afl->expand_havoc && afl->ready_for_splicing_count > 1)) { + + mutation_array = full_splice_array; + rand_max = MUT_SPLICE_ARRAY_SIZE; + + } else { + + mutation_array = normal_splice_array; + rand_max = MUT_NORMAL_ARRAY_SIZE; + + } } else { // is exploitation! @@ -2119,7 +2129,17 @@ havoc_stage: if (likely(afl->fuzz_mode == 0)) { // is exploration? - mutation_array = (unsigned int *)&mutation_strategy_exploration_binary; + if (unlikely(afl->expand_havoc && afl->ready_for_splicing_count > 1)) { + + mutation_array = full_splice_array; + rand_max = MUT_SPLICE_ARRAY_SIZE; + + } else { + + mutation_array = normal_splice_array; + rand_max = MUT_NORMAL_ARRAY_SIZE; + + } } else { // is exploitation! -- cgit v1.2.3 From 936b6dcb5d7a93d2aa211d0812fd26ba0b2c7d3c Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 21 Jun 2023 09:57:24 +0200 Subject: nits --- src/afl-fuzz-stats.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 389b82fc..4013370d 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -2350,6 +2350,8 @@ void show_init_stats(afl_state_t *afl) { afl->timeout_given = 1; + } else { + ACTF("-t option specified. We'll use an exec timeout of %u ms.", afl->fsrv.exec_tmout); -- cgit v1.2.3 From 64b15a00f270f0ac9c00cf13e569481672227635 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 21 Jun 2023 12:20:10 +0200 Subject: fix afl-cmin* for old afl vanilla issue --- src/afl-showmap.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 9c029035..13867fda 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -243,7 +243,8 @@ static void analyze_results(afl_forkserver_t *fsrv) { total += fsrv->trace_bits[i]; if (fsrv->trace_bits[i] > highest) highest = fsrv->trace_bits[i]; - if (!coverage_map[i]) { coverage_map[i] = 1; } + // if (!coverage_map[i]) { coverage_map[i] = 1; } + coverage_map[i] |= fsrv->trace_bits[i]; } @@ -328,7 +329,7 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) { if (cmin_mode) { - fprintf(f, "%u%u\n", fsrv->trace_bits[i], i); + fprintf(f, "%u%03u\n", i, fsrv->trace_bits[i]); } else { -- cgit v1.2.3 From ec4ed66b1efd0953d42e6c7055a2b1cf766ff720 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 21 Jun 2023 13:51:02 +0200 Subject: nits --- src/afl-fuzz.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 9eabfae1..8cf786af 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -164,7 +164,7 @@ static void usage(u8 *argv0, int more_help) { "\n" "Mutator settings:\n" - " -a - target expects ascii text input\n" + " -a - target expects ascii text input (prefer text mutators)\n" " -g minlength - set min length of generated fuzz input (default: 1)\n" " -G maxlength - set max length of generated fuzz input (default: " "%lu)\n" -- cgit v1.2.3 From 90f83c13d08f44fbf50036076a1772909c4d2c86 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 22 Jun 2023 09:24:00 +0200 Subject: remove dead code, code format --- src/afl-fuzz-init.c | 8 ++++---- src/afl-fuzz.c | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 13802f40..24fd7077 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1542,8 +1542,8 @@ double get_runnable_processes(void) { processes well. */ FILE *f = fopen("/proc/stat", "r"); - u8 tmp[1024]; - u32 val = 0; + u8 tmp[1024]; + u32 val = 0; if (!f) { return 0; } @@ -2226,7 +2226,7 @@ void check_crash_handling(void) { *BSD, so we can just let it slide for now. */ s32 fd = open("/proc/sys/kernel/core_pattern", O_RDONLY); - u8 fchar; + u8 fchar; if (fd < 0) { return; } @@ -2365,7 +2365,7 @@ void check_cpu_governor(afl_state_t *afl) { FATAL("Suboptimal CPU scaling governor"); #elif defined __APPLE__ - u64 min = 0, max = 0; + u64 min = 0, max = 0; size_t mlen = sizeof(min); if (afl->afl_env.afl_skip_cpufreq) return; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 8cf786af..79b05da7 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -164,7 +164,8 @@ static void usage(u8 *argv0, int more_help) { "\n" "Mutator settings:\n" - " -a - target expects ascii text input (prefer text mutators)\n" + " -a - target expects ascii text input (prefer text " + "mutators)\n" " -g minlength - set min length of generated fuzz input (default: 1)\n" " -G maxlength - set max length of generated fuzz input (default: " "%lu)\n" -- cgit v1.2.3 From c2c27349c3d74f79ceb6cd3795862b21d90429ea Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 23 Jun 2023 17:08:21 +0200 Subject: new mutation weighting --- src/afl-fuzz-one.c | 30 ++++++------------------------ 1 file changed, 6 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 32c05182..c6e49653 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2101,27 +2101,17 @@ havoc_stage: */ - rand_max = MUT_STRATEGY_ARRAY_SIZE; - if (unlikely(afl->text_input)) { // is text? if (likely(afl->fuzz_mode == 0)) { // is exploration? - if (unlikely(afl->expand_havoc && afl->ready_for_splicing_count > 1)) { - - mutation_array = full_splice_array; - rand_max = MUT_SPLICE_ARRAY_SIZE; - - } else { - - mutation_array = normal_splice_array; - rand_max = MUT_NORMAL_ARRAY_SIZE; - - } + mutation_array = (unsigned int *)&text_array; + rand_max = MUT_TXT_ARRAY_SIZE; } else { // is exploitation! mutation_array = (unsigned int *)&mutation_strategy_exploitation_text; + rand_max = MUT_STRATEGY_ARRAY_SIZE; } @@ -2129,21 +2119,13 @@ havoc_stage: if (likely(afl->fuzz_mode == 0)) { // is exploration? - if (unlikely(afl->expand_havoc && afl->ready_for_splicing_count > 1)) { - - mutation_array = full_splice_array; - rand_max = MUT_SPLICE_ARRAY_SIZE; - - } else { - - mutation_array = normal_splice_array; - rand_max = MUT_NORMAL_ARRAY_SIZE; - - } + mutation_array = (unsigned int *)&binary_array; + rand_max = MUT_BIN_ARRAY_SIZE; } else { // is exploitation! mutation_array = (unsigned int *)&mutation_strategy_exploitation_binary; + rand_max = MUT_STRATEGY_ARRAY_SIZE; } -- cgit v1.2.3 From 32d5ccb92dd3f646db327d2b7c1ec5fa74b4d656 Mon Sep 17 00:00:00 2001 From: Siqi Chen Date: Tue, 27 Jun 2023 01:15:54 +0800 Subject: Increase the number of afl-cc supported params --- src/afl-cc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 9e56828c..58d44e5d 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -383,9 +383,11 @@ static u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0, have_o = 0, have_pic = 0, have_c = 0, partial_linking = 0, non_dash = 0; +#define MAX_PARAMS_NUM 2048 + static void process_params(u32 argc, char **argv) { - if (cc_par_cnt + argc >= 1024) { FATAL("Too many command line parameters"); } + if (cc_par_cnt + argc >= MAX_PARAMS_NUM) { FATAL("Too many command line parameters, please increase MAX_PARAMS_NUM."); } if (lto_mode && argc > 1) { @@ -679,7 +681,7 @@ static void process_params(u32 argc, char **argv) { static void edit_params(u32 argc, char **argv, char **envp) { - cc_params = ck_alloc(1024 * sizeof(u8 *)); + cc_params = ck_alloc(MAX_PARAMS_NUM * sizeof(u8 *)); if (lto_mode) { -- cgit v1.2.3 From 3e1d7941077b1457f702988063d6b9fdd9b80740 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 29 Jun 2023 16:57:20 +0200 Subject: update mutation strategy --- src/afl-fuzz-one.c | 56 ++++++++++++++++++++++++++++++++---------------------- src/afl-fuzz.c | 26 ++++++++++++++++++++----- 2 files changed, 54 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index c6e49653..0d3c29f2 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2085,47 +2085,57 @@ havoc_stage: u32 *mutation_array; u32 stack_max, rand_max; // stack_max_pow = afl->havoc_stack_pow2; - /* + switch (afl->input_mode) { - if (unlikely(afl->expand_havoc && afl->ready_for_splicing_count > 1)) { + case 1: { // TEXT - mutation_array = full_splice_array; - rand_max = MUT_SPLICE_ARRAY_SIZE; + if (likely(afl->fuzz_mode == 0)) { // is exploration? + mutation_array = (unsigned int *)&binary_array; + rand_max = MUT_BIN_ARRAY_SIZE; - } else { + } else { // exploitation mode - mutation_array = normal_splice_array; - rand_max = MUT_NORMAL_ARRAY_SIZE; + mutation_array = (unsigned int *)&mutation_strategy_exploitation_text; + rand_max = MUT_STRATEGY_ARRAY_SIZE; - } + } - */ + break; - if (unlikely(afl->text_input)) { // is text? + } - if (likely(afl->fuzz_mode == 0)) { // is exploration? + case 2: { // BINARY - mutation_array = (unsigned int *)&text_array; - rand_max = MUT_TXT_ARRAY_SIZE; + if (likely(afl->fuzz_mode == 0)) { // is exploration? + mutation_array = (unsigned int *)&mutation_strategy_exploration_binary; + rand_max = MUT_STRATEGY_ARRAY_SIZE; - } else { // is exploitation! + } else { // exploitation mode - mutation_array = (unsigned int *)&mutation_strategy_exploitation_text; - rand_max = MUT_STRATEGY_ARRAY_SIZE; + mutation_array = (unsigned int *)&mutation_strategy_exploitation_binary; + rand_max = MUT_STRATEGY_ARRAY_SIZE; + + } + + break; } - } else { // is binary! + default: { // DEFAULT/GENERIC - if (likely(afl->fuzz_mode == 0)) { // is exploration? + if (likely(afl->fuzz_mode == 0)) { // is exploration? + mutation_array = (unsigned int *)&binary_array; + rand_max = MUT_BIN_ARRAY_SIZE; - mutation_array = (unsigned int *)&binary_array; - rand_max = MUT_BIN_ARRAY_SIZE; + } else { // exploitation mode - } else { // is exploitation! + // this will need to be changed I guess + mutation_array = (unsigned int *)&mutation_strategy_exploration_text; + rand_max = MUT_STRATEGY_ARRAY_SIZE; + + } - mutation_array = (unsigned int *)&mutation_strategy_exploitation_binary; - rand_max = MUT_STRATEGY_ARRAY_SIZE; + break; } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 79b05da7..ab7d6534 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -125,7 +125,8 @@ static void usage(u8 *argv0, int more_help) { "Required parameters:\n" " -i dir - input directory with test cases (or '-' to resume, " - "also see AFL_AUTORESUME)\n" + "also see \n" + " AFL_AUTORESUME)\n" " -o dir - output directory for fuzzer findings\n\n" "Execution control settings:\n" @@ -164,8 +165,8 @@ static void usage(u8 *argv0, int more_help) { "\n" "Mutator settings:\n" - " -a - target expects ascii text input (prefer text " - "mutators)\n" + " -a - target input format, \"text\" or \"binary\" (default: " + "generic)\n" " -g minlength - set min length of generated fuzz input (default: 1)\n" " -G maxlength - set max length of generated fuzz input (default: " "%lu)\n" @@ -506,13 +507,28 @@ int main(int argc, char **argv_orig, char **envp) { // still available: HjJkKqruvwz while ((opt = getopt(argc, argv, - "+aAb:B:c:CdDe:E:f:F:g:G:hi:I:l:L:m:M:nNo:Op:P:QRs:S:t:" + "+a:Ab:B:c:CdDe:E:f:F:g:G:hi:I:l:L:m:M:nNo:Op:P:QRs:S:t:" "T:UV:WXx:YZ")) > 0) { switch (opt) { case 'a': - afl->text_input = 1; + + if (!stricmp(optarg, "text") || !stricmp(optarg, "ascii") || + !stricmp(optarg, "txt") || !stricmp(optarg, "asc")) { + + afl->input_mode = 1; + + } else if (!stricmp(optarg, "bin") || !stricmp(optarg, "binary")) { + + afl->input_mode = 2; + + } else { + + FATAL("-a input mode needs to be \"text\" or \"binary\"."); + + } + break; case 'P': -- cgit v1.2.3 From 819ad95f03c06aad7b01c5ec127bd52d89f110e6 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 30 Jun 2023 12:17:57 +0200 Subject: afl-showmap fix --- src/afl-showmap.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 13867fda..b82bcd72 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -111,8 +111,9 @@ static sharedmem_t *shm_fuzz; static const u8 count_class_human[256] = { - [0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, - [8] = 5, [16] = 6, [32] = 7, [128] = 8 + [0] = 0, [1] = 1, [2] = 2, [3] = 3, + [4 ... 7] = 4, [8 ... 15] = 5, [16 ... 31] = 6, [32 ... 127] = 7, + [128 ... 255] = 8 }; @@ -424,9 +425,9 @@ static void showmap_run_target_forkserver(afl_forkserver_t *fsrv, u8 *mem, } - if (fsrv->trace_bits[0] == 1) { + if (fsrv->trace_bits[0]) { - fsrv->trace_bits[0] = 0; + fsrv->trace_bits[0] -= 1; have_coverage = true; } else { @@ -655,9 +656,9 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) { } - if (fsrv->trace_bits[0] == 1) { + if (fsrv->trace_bits[0]) { - fsrv->trace_bits[0] = 0; + fsrv->trace_bits[0] -= 1; have_coverage = true; } else { -- cgit v1.2.3 From 03bae6c4fe544f87f07cdb554daa6519d37cdfc8 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 1 Jul 2023 12:19:44 +0200 Subject: switch exploit strategy --- src/afl-fuzz-one.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 0d3c29f2..942381dd 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2095,8 +2095,8 @@ havoc_stage: } else { // exploitation mode - mutation_array = (unsigned int *)&mutation_strategy_exploitation_text; - rand_max = MUT_STRATEGY_ARRAY_SIZE; + mutation_array = (unsigned int *)&text_array; + rand_max = MUT_TXT_ARRAY_SIZE; } @@ -2129,9 +2129,8 @@ havoc_stage: } else { // exploitation mode - // this will need to be changed I guess - mutation_array = (unsigned int *)&mutation_strategy_exploration_text; - rand_max = MUT_STRATEGY_ARRAY_SIZE; + mutation_array = (unsigned int *)&text_array; + rand_max = MUT_TXT_ARRAY_SIZE; } -- cgit v1.2.3 From d5184263350335b24daab635f0bcee455302f990 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 2 Jul 2023 14:50:18 +0200 Subject: no_ui: display time --- src/afl-common.c | 29 +++++++++++++++++++++++++++++ src/afl-fuzz-one.c | 10 +++++++--- 2 files changed, 36 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/afl-common.c b/src/afl-common.c index 84ddefd8..3e1ec09d 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -1298,6 +1298,35 @@ u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms) { } +/* Unsafe describe time delta as simple string. + Returns a pointer to buf for convenience. */ + +u8 *u_simplestring_time_diff(u8 *buf, u64 cur_ms, u64 event_ms) { + + if (!event_ms) { + + sprintf(buf, "00:00:00"); + + } else { + + u64 delta; + s32 t_d, t_h, t_m, t_s; + + 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; + + sprintf(buf, "%d:%02d:%02d:%02d", t_d, t_h, t_m, t_s); + + } + + return buf; + +} + /* Reads the map size from ENV */ u32 get_map_size(void) { diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 942381dd..e1ca44ab 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -399,20 +399,24 @@ u8 fuzz_one_original(afl_state_t *afl) { #endif /* ^IGNORE_FINDS */ - if (unlikely(afl->not_on_tty)) { + if (likely(afl->not_on_tty)) { + u8 time_tmp[64]; + + u_simplestring_time_diff(time_tmp, afl->prev_run_time + get_cur_time(), + afl->start_time); ACTF( "Fuzzing test case #%u (%u total, %llu crashes saved, state: %s, " "mode=%s, " "perf_score=%0.0f, weight=%0.0f, favorite=%u, was_fuzzed=%u, " - "exec_us=%llu, hits=%u, map=%u, ascii=%u)...", + "exec_us=%llu, hits=%u, map=%u, ascii=%u, run_time=%s)...", afl->current_entry, afl->queued_items, afl->saved_crashes, get_fuzzing_state(afl), afl->fuzz_mode ? "exploit" : "explore", afl->queue_cur->perf_score, afl->queue_cur->weight, afl->queue_cur->favored, afl->queue_cur->was_fuzzed, afl->queue_cur->exec_us, likely(afl->n_fuzz) ? afl->n_fuzz[afl->queue_cur->n_fuzz_entry] : 0, - afl->queue_cur->bitmap_size, afl->queue_cur->is_ascii); + afl->queue_cur->bitmap_size, afl->queue_cur->is_ascii, time_tmp); fflush(stdout); } -- cgit v1.2.3 From dcbfc88e7d1feae344a5288decc262fa7e8bce83 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 3 Jul 2023 09:17:41 +0200 Subject: comment --- src/afl-fuzz-one.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index e1ca44ab..8ee50bbf 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2118,6 +2118,9 @@ havoc_stage: mutation_array = (unsigned int *)&mutation_strategy_exploitation_binary; rand_max = MUT_STRATEGY_ARRAY_SIZE; + // or this one? we do not have enough binary bug benchmarks :-( + // mutation_array = (unsigned int *)&binary_array; + // rand_max = MUT_BIN_ARRAY_SIZE; } -- cgit v1.2.3 From 0966957631c3d537d38ae8f1c5cfdcbcc2779712 Mon Sep 17 00:00:00 2001 From: Eli Kobrin Date: Mon, 3 Jul 2023 15:03:45 +0300 Subject: Fix max_params define. --- src/afl-cc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 58d44e5d..07c2a2d3 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -383,7 +383,9 @@ static u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0, have_o = 0, have_pic = 0, have_c = 0, partial_linking = 0, non_dash = 0; +#ifndef MAX_PARAMS_NUM #define MAX_PARAMS_NUM 2048 +#endif static void process_params(u32 argc, char **argv) { -- cgit v1.2.3 From da3351085519acf73dc8ddde3cf0b526b816551b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 4 Jul 2023 11:34:13 +0200 Subject: nits --- src/afl-cc.c | 14 +++++++------- src/afl-fuzz.c | 4 ++++ 2 files changed, 11 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 07c2a2d3..ec460f17 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -2111,11 +2111,6 @@ int main(int argc, char **argv, char **envp) { "-------------|\n" "MODES: NCC PERSIST DICT LAF " "CMPLOG SELECT\n" - " [LTO] LLVM LTO: %s%s\n" - " PCGUARD DEFAULT yes yes yes yes yes " - " yes\n" - " CLASSIC yes yes yes yes yes " - " yes\n" " [LLVM] LLVM: %s%s\n" " PCGUARD %s yes yes module yes yes " "yes\n" @@ -2125,16 +2120,21 @@ int main(int argc, char **argv, char **envp) { " - CALLER\n" " - CTX\n" " - NGRAM-{2-16}\n" + " [LTO] LLVM LTO: %s%s\n" + " PCGUARD DEFAULT yes yes yes yes yes " + " yes\n" + " CLASSIC yes yes yes yes yes " + " yes\n" " [GCC_PLUGIN] gcc plugin: %s%s\n" " CLASSIC DEFAULT no yes no no no " "yes\n" " [GCC/CLANG] simple gcc/clang: %s%s\n" " CLASSIC DEFAULT no no no no no " "no\n\n", - have_lto ? "AVAILABLE" : "unavailable!", - compiler_mode == LTO ? " [SELECTED]" : "", have_llvm ? "AVAILABLE" : "unavailable!", compiler_mode == LLVM ? " [SELECTED]" : "", + have_lto ? "AVAILABLE" : "unavailable!", + compiler_mode == LTO ? " [SELECTED]" : "", LLVM_MAJOR >= 7 ? "DEFAULT" : " ", LLVM_MAJOR >= 7 ? " " : "DEFAULT", have_gcc_plugin ? "AVAILABLE" : "unavailable!", diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index ab7d6534..70258e33 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1281,6 +1281,10 @@ int main(int argc, char **argv_orig, char **envp) { } + WARNF( + "Note that the MOpt mode is not maintained and is not as effective " + "normal havoc mode."); + } break; case 'h': -- cgit v1.2.3 From f37c4c86622c5e0ea10e0a0249e203c412c2db2e Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 5 Jul 2023 13:03:17 +0200 Subject: update llvm recommendations --- src/afl-cc.c | 17 +++++++++++++++-- src/afl-fuzz.c | 2 +- 2 files changed, 16 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index ec460f17..86b81459 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -384,12 +384,16 @@ static u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0, non_dash = 0; #ifndef MAX_PARAMS_NUM -#define MAX_PARAMS_NUM 2048 + #define MAX_PARAMS_NUM 2048 #endif static void process_params(u32 argc, char **argv) { - if (cc_par_cnt + argc >= MAX_PARAMS_NUM) { FATAL("Too many command line parameters, please increase MAX_PARAMS_NUM."); } + if (cc_par_cnt + argc >= MAX_PARAMS_NUM) { + + FATAL("Too many command line parameters, please increase MAX_PARAMS_NUM."); + + } if (lto_mode && argc > 1) { @@ -2350,6 +2354,15 @@ int main(int argc, char **argv, char **envp) { "AFL_LLVM_CMPLOG and " "AFL_LLVM_DICT2FILE+AFL_LLVM_DICT2FILE_NO_MAIN.\n\n"); + if (LLVM_MAJOR < 13) { + + SAYF( + "Warning: It is highly recommended to use at least LLVM version 13 " + "(or better, higher) rather than %d!\n\n", + LLVM_MAJOR); + + } + exit(1); } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 70258e33..9afece66 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1283,7 +1283,7 @@ int main(int argc, char **argv_orig, char **envp) { WARNF( "Note that the MOpt mode is not maintained and is not as effective " - "normal havoc mode."); + "as normal havoc mode."); } break; -- cgit v1.2.3 From 877b2bcab614fdc4a076cf940fda8d0b11b95d42 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 7 Jul 2023 15:03:31 +0200 Subject: add limits.h to afl-ld-lto --- src/afl-ld-lto.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c index 420dd817..cb76ba9c 100644 --- a/src/afl-ld-lto.c +++ b/src/afl-ld-lto.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3 From e71de2f2b8f4507edef752ce865e49ef2d389e3e Mon Sep 17 00:00:00 2001 From: fuzzah Date: Fri, 7 Jul 2023 16:57:45 +0300 Subject: remove extra limits.h in afl-ld-lto for BSD --- src/afl-ld-lto.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'src') diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c index cb76ba9c..b306c8d5 100644 --- a/src/afl-ld-lto.c +++ b/src/afl-ld-lto.c @@ -46,11 +46,6 @@ #include -#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || \ - defined(__DragonFly__) - #include -#endif - #ifdef __APPLE__ #include #endif -- cgit v1.2.3 From a46d27fad51a8fdd905bb8771bd73eeb2c054895 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 10 Jul 2023 18:29:21 +0200 Subject: nits --- src/afl-common.c | 2 +- src/afl-forkserver.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/afl-common.c b/src/afl-common.c index 3e1ec09d..a6f83f6d 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -403,7 +403,7 @@ u8 *find_binary(u8 *fname) { FATAL( "Unexpected overflow when processing ENV. This should never " - "happend."); + "happened."); } diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 7322f1ad..ba7cdd66 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -667,13 +667,13 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, switch (fsrv->nyx_handlers->nyx_exec(fsrv->nyx_runner)) { case Abort: - NYX_PRE_FATAL(fsrv, "Error: Nyx abort occured..."); + NYX_PRE_FATAL(fsrv, "Error: Nyx abort occurred..."); break; case IoError: NYX_PRE_FATAL(fsrv, "Error: QEMU-Nyx has died..."); break; case Error: - NYX_PRE_FATAL(fsrv, "Error: Nyx runtime error has occured..."); + NYX_PRE_FATAL(fsrv, "Error: Nyx runtime error has occurred..."); break; default: break; @@ -1581,7 +1581,7 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, FATAL("FixMe: Nyx InvalidWriteToPayload handler is missing"); break; case Abort: - FATAL("Error: Nyx abort occured..."); + FATAL("Error: Nyx abort occurred..."); case IoError: if (*stop_soon_p) { @@ -1595,7 +1595,7 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, break; case Error: - FATAL("Error: Nyx runtime error has occured..."); + FATAL("Error: Nyx runtime error has occurred..."); break; } -- cgit v1.2.3 From 2a34e845072204b29200bf0e480d1d4f2201b332 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 12 Jul 2023 16:08:22 +0200 Subject: nits --- src/afl-ld-lto.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c index b306c8d5..b1e6c848 100644 --- a/src/afl-ld-lto.c +++ b/src/afl-ld-lto.c @@ -23,7 +23,9 @@ */ #define AFL_MAIN -#define _GNU_SOURCE +#ifndef _GNU_SOURCE + #define _GNU_SOURCE +#endif #include "config.h" #include "types.h" -- cgit v1.2.3 From 1132b08d7d3ef6bae712ced57d32ce06abfa973d Mon Sep 17 00:00:00 2001 From: hexcoder Date: Thu, 13 Jul 2023 13:37:47 +0200 Subject: Update afl-common.c typo --- src/afl-common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-common.c b/src/afl-common.c index a6f83f6d..b4143a1b 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -403,7 +403,7 @@ u8 *find_binary(u8 *fname) { FATAL( "Unexpected overflow when processing ENV. This should never " - "happened."); + "had happened."); } -- cgit v1.2.3 From 4113b6ccada97c32b3852ece5ffe2fee6dcbc2c8 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 18 Jul 2023 09:56:28 +0200 Subject: take care of uninstrumented mode for fuzz state and mode --- src/afl-fuzz-bitmap.c | 3 ++- src/afl-fuzz-stats.c | 9 +++++++-- src/afl-fuzz.c | 3 ++- 3 files changed, 11 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index fb8a1d4b..87157cad 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -533,7 +533,8 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { close(fd); add_to_queue(afl, queue_fn, len, 0); - if (unlikely(afl->fuzz_mode) && likely(afl->switch_fuzz_mode)) { + if (unlikely(afl->fuzz_mode) && + likely(afl->switch_fuzz_mode && !afl->non_instrumented_mode)) { if (afl->afl_env.afl_no_ui) { diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 4013370d..3d0a9b9a 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -37,8 +37,13 @@ char *get_fuzzing_state(afl_state_t *afl) { u64 cur_run_time = cur_ms - afl->start_time; u64 cur_total_run_time = afl->prev_run_time + cur_run_time; - if (unlikely(cur_run_time < 60 * 3 * 1000 || - cur_total_run_time < 60 * 5 * 1000)) { + if (unlikely(afl->non_instrumented_mode)) { + + return fuzzing_state[1]; + + } else if (unlikely(cur_run_time < 60 * 3 * 1000 || + + cur_total_run_time < 60 * 5 * 1000)) { return fuzzing_state[0]; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 9afece66..d8a88f00 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2755,7 +2755,8 @@ int main(int argc, char **argv_orig, char **envp) { u64 cur_time = get_cur_time(); - if (likely(afl->switch_fuzz_mode && afl->fuzz_mode == 0) && + if (likely(afl->switch_fuzz_mode && afl->fuzz_mode == 0 && + !afl->non_instrumented_mode) && unlikely(cur_time > afl->last_find_time + afl->switch_fuzz_mode)) { if (afl->afl_env.afl_no_ui) { -- cgit v1.2.3 From 5f813bbb86e1c9e2480669c44501e9780043728c Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 21 Jul 2023 18:02:30 +0200 Subject: improve cmplog level 3 --- src/afl-fuzz-redqueen.c | 171 +++++++++++++++++++++++++----------------------- src/afl-fuzz.c | 7 +- 2 files changed, 95 insertions(+), 83 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 73e188e7..5a1f512d 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -571,7 +571,6 @@ static u8 its_fuzz(afl_state_t *afl, u8 *buf, u32 len, u8 *status) { } -// #ifdef CMPLOG_SOLVE_TRANSFORM static int strntoll(const char *str, size_t sz, char **end, int base, long long *out) { @@ -656,7 +655,6 @@ static int is_hex(const char *str) { } -#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 // tests 4 bytes at location static int is_base64(const char *str) { @@ -769,10 +767,6 @@ static void to_base64(u8 *src, u8 *dst, u32 dst_len) { } -#endif - -// #endif - static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, u64 pattern, u64 repl, u64 o_pattern, u64 changed_val, u8 attr, u32 idx, u32 taint_len, @@ -797,42 +791,54 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, } - // fprintf(stderr, - // "Encode: %llx->%llx into %llx(<-%llx) at idx=%u " - // "taint_len=%u shape=%u attr=%u\n", - // o_pattern, pattern, repl, changed_val, idx, taint_len, - // hshape, attr); + /* + fprintf(stderr, + "Encode: %llx->%llx into %llx(<-%llx) at idx=%u " + "taint_len=%u shape=%u attr=%u\n", + o_pattern, pattern, repl, changed_val, idx, taint_len, + hshape, attr); + */ - // #ifdef CMPLOG_SOLVE_TRANSFORM // reverse atoi()/strnu?toll() is expensive, so we only to it in lvl 3 if (afl->cmplog_enable_transform && (lvl & LVL3)) { u8 *endptr; u8 use_num = 0, use_unum = 0; - unsigned long long unum; - long long num; + unsigned long long unum = 0; + long long num = 0; + + // if (afl->queue_cur->is_ascii) { + + // we first check if our input are ascii numbers that are transformed to + // an integer and used for comparison: - if (afl->queue_cur->is_ascii) { + endptr = buf_8; + if (strntoll(buf_8, len - idx, (char **)&endptr, 0, &num)) { - endptr = buf_8; - if (strntoll(buf_8, len - idx, (char **)&endptr, 0, &num)) { + if (!strntoull(buf_8, len - idx, (char **)&endptr, 0, &unum)) { - if (!strntoull(buf_8, len - idx, (char **)&endptr, 0, &unum)) - use_unum = 1; + use_unum = 1; - } else + } + + } else { - use_num = 1; + use_num = 1; } + //} + #ifdef _DEBUG if (idx == 0) - fprintf(stderr, "ASCII is=%u use_num=%u use_unum=%u idx=%u %llx==%llx\n", - afl->queue_cur->is_ascii, use_num, use_unum, idx, num, pattern); + fprintf(stderr, + "ASCII is=%u use_num=%u>%lld use_unum=%u>%llu idx=%u " + "pattern=0x%llx\n", + afl->queue_cur->is_ascii, use_num, num, use_unum, unum, idx, + pattern); #endif - // num is likely not pattern as atoi("AAA") will be zero... + // atoi("AAA") == 0 so !num means we have to investigate if (use_num && ((u64)num == pattern || !num)) { u8 tmp_buf[32]; @@ -961,10 +967,12 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, // test for arithmetic, eg. "if ((user_val - 0x1111) == 0x1234) ..." s64 diff = pattern - b_val; s64 o_diff = o_pattern - o_b_val; - /* fprintf(stderr, "DIFF1 idx=%03u shape=%02u %llx-%llx=%lx\n", idx, - hshape, o_pattern, o_b_val, o_diff); - fprintf(stderr, "DIFF1 %016llx %llx-%llx=%lx\n", repl, pattern, - b_val, diff); */ + /* + fprintf(stderr, "DIFF1 idx=%03u shape=%02u %llx-%llx=%lx\n", idx, + hshape, o_pattern, o_b_val, o_diff); + fprintf(stderr, "DIFF1 %016llx %llx-%llx=%lx\n", repl, pattern, + b_val, diff); + */ if (diff == o_diff && diff) { // this could be an arithmetic transformation @@ -1275,7 +1283,6 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, // 16 = modified float, 32 = modified integer (modified = wont match // in original buffer) - // #ifdef CMPLOG_SOLVE_ARITHMETIC if (!afl->cmplog_enable_arith || lvl < LVL3 || attr == IS_TRANSFORM) { return 0; @@ -2009,8 +2016,12 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, its_len = MIN(its_len, taint_len); u32 saved_its_len = its_len; + if (its_len <= 1) { return 0; } + if (lvl & LVL3) { + if (memcmp(changed_val, repl, its_len) != 0) { return 0; } + u32 max_to = MIN(4U, idx); if (!(lvl & LVL1) && max_to) { from = 1; } to = max_to; @@ -2089,9 +2100,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, if (afl->cmplog_enable_transform && (lvl & LVL3)) { u32 toupper = 0, tolower = 0, xor = 0, arith = 0, tohex = 0, fromhex = 0; -#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 u32 tob64 = 0, fromb64 = 0; -#endif u32 from_0 = 0, from_x = 0, from_X = 0, from_slash = 0, from_up = 0; u32 to_0 = 0, to_x = 0, to_slash = 0, to_up = 0; u8 xor_val[32], arith_val[32], tmp[48]; @@ -2144,7 +2153,8 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, } - if (i < 16 && is_hex(repl + (i << 1))) { + if (afl->cmplog_enable_xtreme_transform && i < 16 && + is_hex(repl + (i << 1))) { ++tohex; @@ -2163,7 +2173,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, } - if ((i % 2)) { + if (afl->cmplog_enable_xtreme_transform && (i % 2)) { if (len > idx + i + 1 && is_hex(orig_buf + idx + i)) { @@ -2187,20 +2197,21 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, } -#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 - if (i % 3 == 2 && i < 24) { + if (afl->cmplog_enable_xtreme_transform) { - if (is_base64(repl + ((i / 3) << 2))) tob64 += 3; + if (i % 3 == 2 && i < 24) { - } + if (is_base64(repl + ((i / 3) << 2))) tob64 += 3; + + } - if (i % 4 == 3 && i < 24) { + if (i % 4 == 3 && i < 24) { - if (is_base64(orig_buf + idx + i - 3)) fromb64 += 4; + if (is_base64(orig_buf + idx + i - 3)) fromb64 += 4; - } + } -#endif + } if ((o_pattern[i] ^ orig_buf[idx + i]) == xor_val[i] && xor_val[i]) { @@ -2229,45 +2240,50 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, } #ifdef _DEBUG + fprintf(stderr, "RTN %s %s %s %s\n", buf, pattern, orig_buf, o_pattern); fprintf(stderr, - "RTN idx=%u loop=%u xor=%u arith=%u tolower=%u toupper=%u " + "RTN idx=%u len=%u loop=%u xor=%u arith=%u tolower=%u toupper=%u " "tohex=%u fromhex=%u to_0=%u to_slash=%u to_x=%u " "from_0=%u from_slash=%u from_x=%u\n", - idx, i, xor, arith, tolower, toupper, tohex, fromhex, to_0, - to_slash, to_x, from_0, from_slash, from_x); - #ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 - fprintf(stderr, "RTN idx=%u loop=%u tob64=%u from64=%u\n", tob64, - fromb64); - #endif + idx, its_len, i, xor, arith, tolower, toupper, tohex, fromhex, + to_0, to_slash, to_x, from_0, from_slash, from_x); + if (afl->cmplog_enable_xtreme_transform) { + + fprintf(stderr, "RTN idx=%u loop=%u tob64=%u from64=%u\n", idx, i, + tob64, fromb64); + + } + #endif -#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 - // input is base64 and converted to binary? convert repl to base64! - if ((i % 4) == 3 && i < 24 && fromb64 > i) { + if (afl->cmplog_enable_xtreme_transform) { - to_base64(repl, tmp, i + 1); - memcpy(buf + idx, tmp, i + 1); - if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } - // fprintf(stderr, "RTN ATTEMPT fromb64 %u result %u\n", fromb64, - // *status); + // input is base64 and converted to binary? convert repl to base64! + if ((i % 4) == 3 && i < 24 && fromb64 > i) { - } + to_base64(repl, tmp, i + 1); + memcpy(buf + idx, tmp, i + 1); + if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } + // fprintf(stderr, "RTN ATTEMPT fromb64 %u result %u\n", fromb64, + // *status); + + } - // input is converted to base64? decode repl with base64! - if ((i % 3) == 2 && i < 24 && tob64 > i) { + // input is converted to base64? decode repl with base64! + if ((i % 3) == 2 && i < 24 && tob64 > i) { - u32 olen = from_base64(repl, tmp, i + 1); - memcpy(buf + idx, tmp, olen); - if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } - // fprintf(stderr, "RTN ATTEMPT tob64 %u idx=%u result %u\n", tob64, - // idx, *status); + u32 olen = from_base64(repl, tmp, i + 1); + memcpy(buf + idx, tmp, olen); + if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } + // fprintf(stderr, "RTN ATTEMPT tob64 %u idx=%u result %u\n", tob64, + // idx, *status); - } + } -#endif + } // input is converted to hex? convert repl to binary! - if (i < 16 && tohex > i) { + if (afl->cmplog_enable_xtreme_transform && i < 16 && tohex > i) { u32 off; if (to_slash + to_x + to_0 == 2) { @@ -2292,8 +2308,8 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, } // input is hex and converted to binary? convert repl to hex! - if (i && (i % 2) && i < 16 && fromhex && - fromhex + from_slash + from_x + from_0 > i) { + if (afl->cmplog_enable_xtreme_transform && i && (i % 2) && i < 16 && + fromhex && fromhex + from_slash + from_x + from_0 > i) { u8 off = 0; if (from_slash && from_x) { @@ -2401,11 +2417,9 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, if ((i >= 7 && (i >= xor&&i >= arith &&i >= tolower &&i >= toupper &&i > tohex &&i > - (fromhex + from_0 + from_x + from_slash + 1) -#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64 - && i > tob64 + 3 && i > fromb64 + 4 -#endif - )) || + (fromhex + from_0 + from_x + from_slash + 1) && + (afl->cmplog_enable_xtreme_transform && i > tob64 + 3 && + i > fromb64 + 4))) || repl[i] != changed_val[i] || *status == 1) { break; @@ -2418,8 +2432,6 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, } - // #endif - return 0; } @@ -2818,12 +2830,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) { } - } else if ((lvl & LVL1) - - // #ifdef CMPLOG_SOLVE_TRANSFORM - || ((lvl & LVL3) && afl->cmplog_enable_transform) - // #endif - ) { + } else if ((lvl & LVL1) || ((lvl & LVL3) && afl->cmplog_enable_transform)) { if (unlikely(rtn_fuzz(afl, k, orig_buf, buf, cbuf, len, lvl, taint))) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index d8a88f00..21a8915c 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -185,7 +185,8 @@ static void usage(u8 *argv0, int more_help) { " 1=small files, 2=larger files (default), 3=all " "files,\n" " A=arithmetic solving, T=transformational solving,\n" - " R=random colorization bytes.\n\n" + " X=extreme transform solving, R=random colorization " + "bytes.\n\n" "Fuzzing behavior settings:\n" " -Z - sequential queue selection instead of weighted " "random\n" @@ -1120,6 +1121,10 @@ int main(int argc, char **argv_orig, char **envp) { case 'T': afl->cmplog_enable_transform = 1; break; + case 'x': + case 'X': + afl->cmplog_enable_xtreme_transform = 1; + break; case 'r': case 'R': afl->cmplog_random_colorization = 1; -- cgit v1.2.3 From 705cdf45fc32e6f5fcf3b8e58242ede3b99b8b6e Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 23 Jul 2023 13:05:10 +0200 Subject: temp cmplog fixes --- src/afl-fuzz-redqueen.c | 190 ++++++++++++++++++++++++++++++------------------ 1 file changed, 119 insertions(+), 71 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 5a1f512d..8a652a9f 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -129,7 +129,6 @@ static struct range *pop_biggest_range(struct range **ranges) { } #ifdef _DEBUG -// static int logging = 0; static void dump(char *txt, u8 *buf, u32 len) { u32 i; @@ -140,6 +139,7 @@ static void dump(char *txt, u8 *buf, u32 len) { } +/* static void dump_file(char *path, char *name, u32 counter, u8 *buf, u32 len) { char fn[4096]; @@ -155,6 +155,8 @@ static void dump_file(char *path, char *name, u32 counter, u8 *buf, u32 len) { } +*/ + #endif static u8 get_exec_checksum(afl_state_t *afl, u8 *buf, u32 len, u64 *cksum) { @@ -730,12 +732,14 @@ static u32 from_base64(u8 *src, u8 *dst, u32 dst_len) { } -static void to_base64(u8 *src, u8 *dst, u32 dst_len) { +static u32 to_base64(u8 *src, u8 *dst, u32 dst_len) { u32 i, j, v; - u32 len = (dst_len >> 2) * 3; + // u32 len = (dst_len >> 2) * 3; + u32 len = (dst_len / 3) * 4; + if (dst_len % 3) len += 4; - for (i = 0, j = 0; i < len; i += 3, j += 4) { + for (i = 0, j = 0; j < len; i += 3, j += 4) { v = src[i]; v = i + 1 < len ? v << 8 | src[i + 1] : v << 8; @@ -743,7 +747,8 @@ static void to_base64(u8 *src, u8 *dst, u32 dst_len) { dst[j] = base64_encode_table[(v >> 18) & 0x3F]; dst[j + 1] = base64_encode_table[(v >> 12) & 0x3F]; - if (i + 1 < len) { + + if (i + 1 < dst_len) { dst[j + 2] = base64_encode_table[(v >> 6) & 0x3F]; @@ -753,7 +758,7 @@ static void to_base64(u8 *src, u8 *dst, u32 dst_len) { } - if (i + 2 < len) { + if (i + 2 < dst_len) { dst[j + 3] = base64_encode_table[v & 0x3F]; @@ -765,6 +770,9 @@ static void to_base64(u8 *src, u8 *dst, u32 dst_len) { } + dst[len] = 0; + return len; + } static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, @@ -2016,6 +2024,8 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, its_len = MIN(its_len, taint_len); u32 saved_its_len = its_len; + // fprintf(stderr, "its_len=%u repl=%s\n", its_len, repl); + if (its_len <= 1) { return 0; } if (lvl & LVL3) { @@ -2032,27 +2042,32 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, (void)(j); #ifdef _DEBUG - fprintf(stderr, "RTN T idx=%u lvl=%02x is_txt=%u shape=%u/%u ", idx, lvl, - o->v0_len >= 0x80 ? 1 : 0, hshape, l0); - for (j = 0; j < 8; j++) - fprintf(stderr, "%02x", orig_buf[idx + j]); - fprintf(stderr, " -> "); - for (j = 0; j < 8; j++) - fprintf(stderr, "%02x", o_pattern[j]); - fprintf(stderr, " <= "); - for (j = 0; j < 8; j++) - fprintf(stderr, "%02x", repl[j]); - fprintf(stderr, "\n"); - fprintf(stderr, " "); - for (j = 0; j < 8; j++) - fprintf(stderr, "%02x", buf[idx + j]); - fprintf(stderr, " -> "); - for (j = 0; j < 8; j++) - fprintf(stderr, "%02x", pattern[j]); - fprintf(stderr, " <= "); - for (j = 0; j < 8; j++) - fprintf(stderr, "%02x", changed_val[j]); - fprintf(stderr, "\n"); + if (idx == 0) { + + fprintf(stderr, "RTN T idx=%u lvl=%02x is_txt=%u shape=%u/%u ", idx, lvl, + o->v0_len >= 0x80 ? 1 : 0, hshape, l0); + for (j = 0; j < 8; j++) + fprintf(stderr, "%02x", orig_buf[idx + j]); + fprintf(stderr, " -> "); + for (j = 0; j < 8; j++) + fprintf(stderr, "%02x", o_pattern[j]); + fprintf(stderr, " <= "); + for (j = 0; j < 8; j++) + fprintf(stderr, "%02x", repl[j]); + fprintf(stderr, "\n"); + fprintf(stderr, " "); + for (j = 0; j < 8; j++) + fprintf(stderr, "%02x", buf[idx + j]); + fprintf(stderr, " -> "); + for (j = 0; j < 8; j++) + fprintf(stderr, "%02x", pattern[j]); + fprintf(stderr, " <= "); + for (j = 0; j < 8; j++) + fprintf(stderr, "%02x", changed_val[j]); + fprintf(stderr, "\n"); + + } + #endif // Try to match the replace value up to 4 bytes before the current idx. @@ -2061,6 +2076,9 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, // if (memcmp(user_val, "TEST-VALUE") == 0) ... // We only do this in lvl 3, otherwise we only do direct matching + // fprintf(stderr, "XXXX FROMB64 saved_idx=%u its_len=%u from=%u to=%u FROMHEX + // repl=%s\n", saved_idx, saved_its_len, from, to, repl); + for (pre = from; pre <= to; pre++) { if (*status != 1 && (!pre || !memcmp(buf + saved_idx - pre, repl, pre))) { @@ -2173,9 +2191,9 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, } - if (afl->cmplog_enable_xtreme_transform && (i % 2)) { + if (afl->cmplog_enable_xtreme_transform && (i % 2) == 1) { - if (len > idx + i + 1 && is_hex(orig_buf + idx + i)) { + if (len > idx + i + 1 && is_hex(orig_buf + idx + i - 1)) { fromhex += 2; @@ -2205,6 +2223,8 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, } + // fprintf(stderr, "X FROMB64 idx=%u i=%u repl=%s\n", saved_idx, i, + // repl); if (i % 4 == 3 && i < 24) { if (is_base64(orig_buf + idx + i - 3)) fromb64 += 4; @@ -2240,17 +2260,23 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, } #ifdef _DEBUG - fprintf(stderr, "RTN %s %s %s %s\n", buf, pattern, orig_buf, o_pattern); - fprintf(stderr, - "RTN idx=%u len=%u loop=%u xor=%u arith=%u tolower=%u toupper=%u " - "tohex=%u fromhex=%u to_0=%u to_slash=%u to_x=%u " - "from_0=%u from_slash=%u from_x=%u\n", - idx, its_len, i, xor, arith, tolower, toupper, tohex, fromhex, - to_0, to_slash, to_x, from_0, from_slash, from_x); - if (afl->cmplog_enable_xtreme_transform) { + if (idx == 0) { + + fprintf(stderr, "RTN Z %s %s %s %s repl=%s\n", buf, pattern, orig_buf, + o_pattern, repl); + fprintf( + stderr, + "RTN Z idx=%u len=%u loop=%u xor=%u arith=%u tolower=%u toupper=%u " + "tohex=%u fromhex=%u to_0=%u to_slash=%u to_x=%u " + "from_0=%u from_slash=%u from_x=%u\n", + idx, its_len, i, xor, arith, tolower, toupper, tohex, fromhex, to_0, + to_slash, to_x, from_0, from_slash, from_x); + if (afl->cmplog_enable_xtreme_transform) { + + fprintf(stderr, "RTN Z idx=%u loop=%u tob64=%u from64=%u\n", idx, i, + tob64, fromb64); - fprintf(stderr, "RTN idx=%u loop=%u tob64=%u from64=%u\n", idx, i, - tob64, fromb64); + } } @@ -2259,13 +2285,27 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, if (afl->cmplog_enable_xtreme_transform) { // input is base64 and converted to binary? convert repl to base64! + // fprintf(stderr, "FROMB64 idx=%u i=%u %% 4 == 3 && i < 24 && + // fromb64=%u > i, repl=%s\n", saved_idx, i, fromb64, repl); if ((i % 4) == 3 && i < 24 && fromb64 > i) { - to_base64(repl, tmp, i + 1); - memcpy(buf + idx, tmp, i + 1); - if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } - // fprintf(stderr, "RTN ATTEMPT fromb64 %u result %u\n", fromb64, - // *status); + for (u32 hlen = i; hlen + saved_idx < len && hlen <= its_len; + ++hlen) { + + u32 res = to_base64(repl, tmp, hlen); + // fprintf(stderr, "FROMB64 GOGO! idx=%u repl=%s tmp[%u]=%s + // hlen=%u\n", saved_idx, repl, res, tmp, hlen); + if (res + saved_idx < len) { + + memcpy(buf + idx, tmp, res); + if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } + // fprintf(stderr, "RTN ATTEMPT FROMB64 idx=%u fromb64 %u %s %s + // result %u\n", saved_idx, fromb64, tmp, repl, + // *status); + + } + + } } @@ -2308,7 +2348,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, } // input is hex and converted to binary? convert repl to hex! - if (afl->cmplog_enable_xtreme_transform && i && (i % 2) && i < 16 && + if (afl->cmplog_enable_xtreme_transform && (i % 2) == 1 && i < 16 && fromhex && fromhex + from_slash + from_x + from_0 > i) { u8 off = 0; @@ -2344,31 +2384,36 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, } - if (to_up == 1) { + for (u32 hlen = i; hlen <= (i << 1) && hlen + idx < len; hlen += i) { - for (j = 0; j <= (i >> 1); j++) { + if (to_up == 1) { - tmp[off + (j << 1)] = hex_table_up[repl[j] >> 4]; - tmp[off + (j << 1) + 1] = hex_table_up[repl[j] % 16]; + for (j = 0; j <= (hlen >> 1); j++) { - } + tmp[off + (j << 1)] = hex_table_up[repl[j] >> 4]; + tmp[off + (j << 1) + 1] = hex_table_up[repl[j] % 16]; - } else { + } + + } else { + + for (j = 0; j <= (hlen >> 1); j++) { - for (j = 0; j <= (i >> 1); j++) { + tmp[off + (j << 1)] = hex_table_low[repl[j] >> 4]; + tmp[off + (j << 1) + 1] = hex_table_low[repl[j] % 16]; - tmp[off + (j << 1)] = hex_table_low[repl[j] >> 4]; - tmp[off + (j << 1) + 1] = hex_table_low[repl[j] % 16]; + } } - } + memcpy(buf + idx, tmp, hlen + 1 + off); + if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } + tmp[hlen + 1 + off] = 0; + // fprintf(stderr, "RTN ATTEMPT idx=%u len=%u fromhex %u %s %s result + // %u\n", idx, len, fromhex, tmp, repl, *status); + memcpy(buf + idx, save, hlen + 1 + off); - memcpy(buf + idx, tmp, i + 1 + off); - if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } - // fprintf(stderr, "RTN ATTEMPT fromhex %u result %u\n", fromhex, - // *status); - memcpy(buf + idx, save, i + 1 + off); + } } @@ -2441,7 +2486,7 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, struct tainted *t; struct cmp_header *h = &afl->shm.cmp_map->headers[key]; - u32 i, j, idx, have_taint = 1, taint_len, loggeds; + u32 i, idx, have_taint = 1, taint_len, loggeds; u8 status = 0, found_one = 0; hshape = SHAPE_BYTES(h->shape); @@ -2464,19 +2509,22 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, struct cmpfn_operands *orig_o = &((struct cmpfn_operands *)afl->orig_cmp_map->log[key])[i]; - // opt not in the paper - for (j = 0; j < i; ++j) { + /* + // opt not in the paper + for (j = 0; j < i; ++j) { - if (!memcmp(&((struct cmpfn_operands *)afl->shm.cmp_map->log[key])[j], o, - sizeof(struct cmpfn_operands))) { + if (!memcmp(&((struct cmpfn_operands *)afl->shm.cmp_map->log[key])[j], + o, sizeof(struct cmpfn_operands))) { - goto rtn_fuzz_next_iter; + goto rtn_fuzz_next_iter; - } + } - } + } - /* + */ + +#ifdef _DEBUG struct cmp_header *hh = &afl->orig_cmp_map->headers[key]; fprintf(stderr, "RTN N hits=%u id=%u shape=%u attr=%u v0=", h->hits, h->id, hshape, h->attribute); @@ -2493,7 +2541,7 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, for (j = 0; j < 8; j++) fprintf(stderr, "%02x", orig_o->v1[j]); fprintf(stderr, "\n"); - */ +#endif t = taint; while (t->next) { @@ -2527,7 +2575,7 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, status = 0; #ifdef _DEBUG - int w; + u32 w; fprintf(stderr, "key=%u idx=%u len=%u o0=", key, idx, hshape); for (w = 0; w < hshape; ++w) fprintf(stderr, "%02x", orig_o->v0[w]); -- cgit v1.2.3 From bd1648e707b85b79d816fd8737909789d7d2a09c Mon Sep 17 00:00:00 2001 From: mark0 <757410129@qq.com> Date: Fri, 28 Jul 2023 17:32:59 +0800 Subject: fix the file descriptor without determining null --- src/afl-showmap.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/afl-showmap.c b/src/afl-showmap.c index b82bcd72..7a639cf6 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -1611,6 +1611,7 @@ int main(int argc, char **argv_orig, char **envp) { if (in_dir || in_filelist) { afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY); + if (afl->fsrv.dev_urandom_fd < 0) { PFATAL("Unable to open /dev/urandom"); } afl->afl_env.afl_custom_mutator_library = getenv("AFL_CUSTOM_MUTATOR_LIBRARY"); afl->afl_env.afl_python_module = getenv("AFL_PYTHON_MODULE"); -- cgit v1.2.3 From f87ba7ed6324e9d33c2b93da5103344d53218f2c Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 28 Jul 2023 15:18:12 +0200 Subject: doc fix --- src/afl-fuzz.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 21a8915c..bacbafc4 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -278,7 +278,8 @@ static void usage(u8 *argv0, int more_help) { "AFL_IGNORE_UNKNOWN_ENVS: don't warn on unknown env vars\n" "AFL_IMPORT_FIRST: sync and import test cases from other fuzzer instances first\n" "AFL_INPUT_LEN_MIN/AFL_INPUT_LEN_MAX: like -g/-G set min/max fuzz length produced\n" - "AFL_PIZZA_MODE: 1 - enforce pizza mode, 0 - disable for April 1st\n" + "AFL_PIZZA_MODE: 1 - enforce pizza mode, -1 - disable for April 1st,\n" + " 0 (default) - activate on April 1st\n" "AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, etc.\n" " (default: SIGKILL)\n" "AFL_FORK_SERVER_KILL_SIGNAL: Kill signal for the fork server on termination\n" -- cgit v1.2.3 From 168ade3b70077ec6a24df9fc594e3b8c1db89bd6 Mon Sep 17 00:00:00 2001 From: mark0 <59284400+mark0-cn@users.noreply.github.com> Date: Mon, 31 Jul 2023 05:51:24 +0800 Subject: Fix format specifiers (#1818) * Update afl-mutations.h Fix bug: compilation cannot pass when DEBUG macro is enabled * Update afl-fuzz-one.c Fix bug: compilation cannot pass when DEBUG macro is enabled --- src/afl-fuzz-one.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 8ee50bbf..f4ae7bfd 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2995,7 +2995,7 @@ havoc_stage: // fprintf(stderr, "val: %u-%u = %ld\n", off, off2, val); char buf[20]; - snprintf(buf, sizeof(buf), "%ld", val); + snprintf(buf, sizeof(buf), "%lld", val); // fprintf(stderr, "BEFORE: %s\n", out_buf); -- cgit v1.2.3 From d0782a7f03a23f8323772d189e5b66a4eb086afd Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sun, 30 Jul 2023 21:59:57 +0000 Subject: Various fixes for warnings, extends #1818 --- src/afl-fuzz-one.c | 2 +- src/afl-fuzz-redqueen.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index f4ae7bfd..2ad4697e 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2995,7 +2995,7 @@ havoc_stage: // fprintf(stderr, "val: %u-%u = %ld\n", off, off2, val); char buf[20]; - snprintf(buf, sizeof(buf), "%lld", val); + snprintf(buf, sizeof(buf), "%" PRId64, val); // fprintf(stderr, "BEFORE: %s\n", out_buf); diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 8a652a9f..54bf4e32 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -2665,7 +2665,7 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, } - rtn_fuzz_next_iter: + // rtn_fuzz_next_iter: afl->stage_cur++; } -- cgit v1.2.3 From 1429c9724efb62e5ac90ec27d93a64c28632ba5d Mon Sep 17 00:00:00 2001 From: Junwha Date: Wed, 2 Aug 2023 02:59:07 +0900 Subject: Add option for treating crashing input as new crash Signed-off-by: Junwha Hong --- src/afl-fuzz-init.c | 99 +++++++++++++++++++++++++++++++++++++++++++---------- src/afl-fuzz.c | 3 +- 2 files changed, 83 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 24fd7077..6b7f3036 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1056,6 +1056,13 @@ void perform_dry_run(afl_state_t *afl) { "skipping", fn, (int)(s8)afl->fsrv.crash_exitcode); + } else if (afl->crashing_seeds_as_new_crash) { + + WARNF( + "Test case '%s' results in a crash," + "as AFL_CRASHING_SEEDS_AS_NEW_CRASH is set, " + "saving as a crash", fn); + } else { WARNF("Test case '%s' results in a crash, skipping", fn); @@ -1078,38 +1085,94 @@ void perform_dry_run(afl_state_t *afl) { } - q->disabled = 1; - q->perf_score = 0; + /* Crashing corpus will regrad as normal, and categorized as new crash at fuzzing */ + if (afl->crashing_seeds_as_new_crash) { + + ++afl->total_crashes; - u32 i = 0; - while (unlikely(i < afl->queued_items && afl->queue_buf[i] && - afl->queue_buf[i]->disabled)) { + if (likely(!afl->non_instrumented_mode)) { - ++i; + classify_counts(&afl->fsrv); + + simplify_trace(afl, afl->fsrv.trace_bits); - } + if (!has_new_bits(afl, afl->virgin_crash)) { break; } + + } + + + if (unlikely(!afl->saved_crashes) && + (afl->afl_env.afl_no_crash_readme != 1)) { + + write_crash_readme(afl); + + } + + u8 crash_fn[PATH_MAX]; + u8 *use_name = strstr(q->fname, ",orig:"); + + afl->stage_name = "dry_run"; + afl->stage_short = "dry_run"; + + #ifndef SIMPLE_FILES + + snprintf(crash_fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s", afl->out_dir, + afl->saved_crashes, afl->fsrv.last_kill_signal, + describe_op(afl, 0, NAME_MAX - strlen("id:000000,sig:00,") - strlen(use_name)), use_name); + + #else + + snprintf(crash_fn, PATH_MAX, "%s/crashes/id_%06llu_%02u", afl->out_dir, + afl->saved_crashes, afl->fsrv.last_kill_signal); + + #endif - if (i < afl->queued_items && afl->queue_buf[i]) { + ++afl->saved_crashes; - afl->queue = afl->queue_buf[i]; + fd = open(crash_fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); + if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", crash_fn); } + ck_write(fd, use_mem, read_len, crash_fn); + close(fd); + + afl->last_crash_time = get_cur_time(); + afl->last_crash_execs = afl->fsrv.total_execs; } else { - afl->queue = afl->queue_buf[0]; + q->disabled = 1; + q->perf_score = 0; - } + u32 i = 0; + while (unlikely(i < afl->queued_items && afl->queue_buf[i] && + afl->queue_buf[i]->disabled)) { - afl->max_depth = 0; - for (i = 0; i < afl->queued_items && likely(afl->queue_buf[i]); i++) { + ++i; - if (!afl->queue_buf[i]->disabled && - afl->queue_buf[i]->depth > afl->max_depth) - afl->max_depth = afl->queue_buf[i]->depth; + } - } + if (i < afl->queued_items && afl->queue_buf[i]) { - break; + afl->queue = afl->queue_buf[i]; + + } else { + afl->queue = afl->queue_buf[0]; + + } + + afl->max_depth = 0; + for (i = 0; i < afl->queued_items && likely(afl->queue_buf[i]); i++) { + + if (!afl->queue_buf[i]->disabled && + afl->queue_buf[i]->depth > afl->max_depth) + afl->max_depth = afl->queue_buf[i]->depth; + + } + + } + + break; + case FSRV_RUN_ERROR: FATAL("Unable to execute target application ('%s')", afl->argv[0]); diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index bacbafc4..5cbebb0e 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1573,7 +1573,8 @@ int main(int argc, char **argv_orig, char **envp) { if (get_afl_env("AFL_NO_ARITH")) { afl->no_arith = 1; } if (get_afl_env("AFL_SHUFFLE_QUEUE")) { afl->shuffle_queue = 1; } if (get_afl_env("AFL_EXPAND_HAVOC_NOW")) { afl->expand_havoc = 1; } - + if (get_afl_env("AFL_CRASHING_SEEDS_AS_NEW_CRASH")) { afl->crashing_seeds_as_new_crash = 1; } + if (afl->afl_env.afl_autoresume) { afl->autoresume = 1; -- cgit v1.2.3 From 8f31086a7fa1d7ef9d4dc416f238a10dd140e2d3 Mon Sep 17 00:00:00 2001 From: Sergej Schumilo Date: Thu, 3 Aug 2023 14:40:10 +0200 Subject: make nyx aux buffer size configurable --- src/afl-forkserver.c | 10 ++++++++++ src/afl-fuzz.c | 3 +++ 2 files changed, 13 insertions(+) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index ba7cdd66..957cb2b7 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -129,6 +129,9 @@ nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary) { plugin->nyx_remove_work_dir = dlsym(handle, "nyx_remove_work_dir"); if (plugin->nyx_remove_work_dir == NULL) { goto fail; } + plugin->nyx_config_set_aux_buffer_size = dlsym(handle, "nyx_config_set_aux_buffer_size"); + if (plugin->nyx_config_set_aux_buffer_size == NULL) { goto fail; } + OKF("libnyx plugin is ready!"); return plugin; @@ -589,6 +592,13 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } + if (getenv("AFL_NYX_AUX_SIZE") != NULL) { + if(fsrv->nyx_handlers->nyx_config_set_aux_buffer_size( + nyx_config, atoi(getenv("AFL_NYX_AUX_SIZE"))) != 1) { + NYX_PRE_FATAL(fsrv, "Invalid AFL_NYX_AUX_SIZE value set (must be a multiple of 4096) ..."); + } + } + if (getenv("NYX_REUSE_SNAPSHOT") != NULL) { if (access(getenv("NYX_REUSE_SNAPSHOT"), F_OK) == -1) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index bacbafc4..9504d908 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -299,6 +299,9 @@ static void usage(u8 *argv0, int more_help) { "AFL_NO_SNAPSHOT: do not use the snapshot feature (if the snapshot lkm is loaded)\n" "AFL_NO_STARTUP_CALIBRATION: no initial seed calibration, start fuzzing at once\n" "AFL_NO_UI: switch status screen off\n" + "AFL_NYX_AUX_SIZE: size of the Nyx auxiliary buffer. Must be a multiple of 4096.\n" + " Increase this value in case the crash reports are truncated.\n" + " Default value is 4096.\n" DYN_COLOR -- cgit v1.2.3 From 79640acbf1ffff9677ec9094b61ac4a158b1551c Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 4 Aug 2023 09:25:19 +0200 Subject: nits --- src/afl-forkserver.c | 17 ++++++++++++----- src/afl-fuzz-redqueen.c | 2 +- src/afl-fuzz.c | 15 +++++++-------- 3 files changed, 20 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 957cb2b7..e90ea460 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -129,7 +129,8 @@ nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary) { plugin->nyx_remove_work_dir = dlsym(handle, "nyx_remove_work_dir"); if (plugin->nyx_remove_work_dir == NULL) { goto fail; } - plugin->nyx_config_set_aux_buffer_size = dlsym(handle, "nyx_config_set_aux_buffer_size"); + plugin->nyx_config_set_aux_buffer_size = + dlsym(handle, "nyx_config_set_aux_buffer_size"); if (plugin->nyx_config_set_aux_buffer_size == NULL) { goto fail; } OKF("libnyx plugin is ready!"); @@ -593,10 +594,16 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } if (getenv("AFL_NYX_AUX_SIZE") != NULL) { - if(fsrv->nyx_handlers->nyx_config_set_aux_buffer_size( - nyx_config, atoi(getenv("AFL_NYX_AUX_SIZE"))) != 1) { - NYX_PRE_FATAL(fsrv, "Invalid AFL_NYX_AUX_SIZE value set (must be a multiple of 4096) ..."); - } + + if (fsrv->nyx_handlers->nyx_config_set_aux_buffer_size( + nyx_config, atoi(getenv("AFL_NYX_AUX_SIZE"))) != 1) { + + NYX_PRE_FATAL(fsrv, + "Invalid AFL_NYX_AUX_SIZE value set (must be a multiple " + "of 4096) ..."); + + } + } if (getenv("NYX_REUSE_SNAPSHOT") != NULL) { diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 54bf4e32..ca5104c0 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -2665,7 +2665,7 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, } - // rtn_fuzz_next_iter: + // rtn_fuzz_next_iter: afl->stage_cur++; } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 9504d908..29659013 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -311,8 +311,8 @@ static void usage(u8 *argv0, int more_help) { PERSISTENT_MSG - "AFL_POST_PROCESS_KEEP_ORIGINAL: save the file as it was prior post-processing to the queue,\n" - " but execute the post-processed one\n" + "AFL_POST_PROCESS_KEEP_ORIGINAL: save the file as it was prior post-processing to\n" + " the queue, but execute the post-processed one\n" "AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n" "AFL_TARGET_ENV: pass extra environment variables to target\n" "AFL_SHUFFLE_QUEUE: reorder the input queue randomly on startup\n" @@ -323,18 +323,17 @@ static void usage(u8 *argv0, int more_help) { "AFL_STATSD_HOST: change default statsd host (default 127.0.0.1)\n" "AFL_STATSD_PORT: change default statsd port (default: 8125)\n" "AFL_STATSD_TAGS_FLAVOR: set statsd tags format (default: disable tags)\n" - " Supported formats are: 'dogstatsd', 'librato',\n" - " 'signalfx' and 'influxdb'\n" + " suported formats: dogstatsd, librato, signalfx, influxdb\n" "AFL_SYNC_TIME: sync time between fuzzing instances (in minutes)\n" "AFL_NO_CRASH_README: do not create a README in the crashes directory\n" "AFL_TESTCACHE_SIZE: use a cache for testcases, improves performance (in MB)\n" "AFL_TMPDIR: directory to use for input file generation (ramdisk recommended)\n" "AFL_EARLY_FORKSERVER: force an early forkserver in an afl-clang-fast/\n" " afl-clang-lto/afl-gcc-fast target\n" - "AFL_PERSISTENT: enforce persistent mode (if __AFL_LOOP is in a shared lib\n" - "AFL_DEFER_FORKSRV: enforced deferred forkserver (__AFL_INIT is in a .so)\n" - "AFL_FUZZER_STATS_UPDATE_INTERVAL: interval to update fuzzer_stats file in seconds, " - "(default: 60, minimum: 1)\n" + "AFL_PERSISTENT: enforce persistent mode (if __AFL_LOOP is in a shared lib)\n" + "AFL_DEFER_FORKSRV: enforced deferred forkserver (__AFL_INIT is in a shared lib)\n" + "AFL_FUZZER_STATS_UPDATE_INTERVAL: interval to update fuzzer_stats file in\n" + " seconds (default: 60, minimum: 1)\n" "\n" ); -- cgit v1.2.3 From fcdfe9e990d84ab477cd3c571cbf540e8bc8e15a Mon Sep 17 00:00:00 2001 From: Junwha Date: Fri, 4 Aug 2023 18:36:58 +0900 Subject: Define AFL_CRASHING_SEEDS_AS_NEW_CRASH as env variable - and fix typo Signed-off-by: Junwha --- src/afl-fuzz-init.c | 30 ++++++++++++++++-------------- src/afl-fuzz-state.c | 7 +++++++ src/afl-fuzz.c | 1 - 3 files changed, 23 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 6b7f3036..d994d749 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1056,17 +1056,19 @@ void perform_dry_run(afl_state_t *afl) { "skipping", fn, (int)(s8)afl->fsrv.crash_exitcode); - } else if (afl->crashing_seeds_as_new_crash) { - - WARNF( - "Test case '%s' results in a crash," - "as AFL_CRASHING_SEEDS_AS_NEW_CRASH is set, " - "saving as a crash", fn); - } else { + if (afl->afl_env.afl_crashing_seeds_as_new_crash) { + + WARNF( + "Test case '%s' results in a crash, " + "as AFL_CRASHING_SEEDS_AS_NEW_CRASH is set, " + "saving as a new crash", fn); + + } else { - WARNF("Test case '%s' results in a crash, skipping", fn); - + WARNF("Test case '%s' results in a crash, skipping", fn); + + } } if (afl->afl_env.afl_exit_on_seed_issues) { @@ -1085,8 +1087,8 @@ void perform_dry_run(afl_state_t *afl) { } - /* Crashing corpus will regrad as normal, and categorized as new crash at fuzzing */ - if (afl->crashing_seeds_as_new_crash) { + /* Crashing seeds will be regarded as new crashes on startup */ + if (afl->afl_env.afl_crashing_seeds_as_new_crash) { ++afl->total_crashes; @@ -1139,9 +1141,6 @@ void perform_dry_run(afl_state_t *afl) { } else { - q->disabled = 1; - q->perf_score = 0; - u32 i = 0; while (unlikely(i < afl->queued_items && afl->queue_buf[i] && afl->queue_buf[i]->disabled)) { @@ -1171,6 +1170,9 @@ void perform_dry_run(afl_state_t *afl) { } + q->disabled = 1; + q->perf_score = 0; + break; case FSRV_RUN_ERROR: diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 99f69314..5a6b95cf 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -200,6 +200,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_exit_on_time = (u8 *)get_afl_env(afl_environment_variables[i]); + } else if (!strncmp(env, "AFL_CRASHING_SEEDS_AS_NEW_CRASH", + + afl_environment_variable_len)) { + + afl->afl_env.afl_crashing_seeds_as_new_crash = + atoi((u8 *)get_afl_env(afl_environment_variables[i])); + } else if (!strncmp(env, "AFL_NO_AFFINITY", afl_environment_variable_len)) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 5cbebb0e..51ca4ee6 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1573,7 +1573,6 @@ int main(int argc, char **argv_orig, char **envp) { if (get_afl_env("AFL_NO_ARITH")) { afl->no_arith = 1; } if (get_afl_env("AFL_SHUFFLE_QUEUE")) { afl->shuffle_queue = 1; } if (get_afl_env("AFL_EXPAND_HAVOC_NOW")) { afl->expand_havoc = 1; } - if (get_afl_env("AFL_CRASHING_SEEDS_AS_NEW_CRASH")) { afl->crashing_seeds_as_new_crash = 1; } if (afl->afl_env.afl_autoresume) { -- cgit v1.2.3 From 08a6fd7c29489f5477f50b94d7a0e425f64fef34 Mon Sep 17 00:00:00 2001 From: Sergej Schumilo Date: Fri, 4 Aug 2023 12:13:06 +0200 Subject: update the old nyx env var naming scheme (to have a more consistent naming overall) --- src/afl-forkserver.c | 27 ++++++++++++++------------- src/afl-fuzz.c | 3 ++- 2 files changed, 16 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index e90ea460..717898d1 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -606,23 +606,23 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } - if (getenv("NYX_REUSE_SNAPSHOT") != NULL) { + if (getenv("AFL_NYX_REUSE_SNAPSHOT") != NULL) { - if (access(getenv("NYX_REUSE_SNAPSHOT"), F_OK) == -1) { + if (access(getenv("AFL_NYX_REUSE_SNAPSHOT"), F_OK) == -1) { - NYX_PRE_FATAL(fsrv, "NYX_REUSE_SNAPSHOT path does not exist"); + NYX_PRE_FATAL(fsrv, "AFL_NYX_REUSE_SNAPSHOT path does not exist"); } /* stupid sanity check to avoid passing an empty or invalid snapshot * directory */ char *snapshot_file_path = - alloc_printf("%s/global.state", getenv("NYX_REUSE_SNAPSHOT")); + alloc_printf("%s/global.state", getenv("AFL_NYX_REUSE_SNAPSHOT")); if (access(snapshot_file_path, R_OK) == -1) { - NYX_PRE_FATAL( - fsrv, - "NYX_REUSE_SNAPSHOT path does not contain a valid Nyx snapshot"); + NYX_PRE_FATAL(fsrv, + "AFL_NYX_REUSE_SNAPSHOT path does not contain a valid " + "Nyx snapshot"); } @@ -634,13 +634,14 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, char *workdir_snapshot_path = alloc_printf("%s/workdir/snapshot", outdir_path_absolute); char *reuse_snapshot_path_real = - realpath(getenv("NYX_REUSE_SNAPSHOT"), NULL); + realpath(getenv("AFL_NYX_REUSE_SNAPSHOT"), NULL); if (strcmp(workdir_snapshot_path, reuse_snapshot_path_real) == 0) { - NYX_PRE_FATAL(fsrv, - "NYX_REUSE_SNAPSHOT path is located in current workdir " - "(use another output directory)"); + NYX_PRE_FATAL( + fsrv, + "AFL_NYX_REUSE_SNAPSHOT path is located in current workdir " + "(use another output directory)"); } @@ -648,7 +649,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, ck_free(workdir_snapshot_path); fsrv->nyx_handlers->nyx_config_set_reuse_snapshot_path( - nyx_config, getenv("NYX_REUSE_SNAPSHOT")); + nyx_config, getenv("AFL_NYX_REUSE_SNAPSHOT")); } @@ -670,7 +671,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, fsrv->nyx_handlers->nyx_get_bitmap_buffer(fsrv->nyx_runner); fsrv->nyx_handlers->nyx_option_set_reload_mode( - fsrv->nyx_runner, getenv("NYX_DISABLE_SNAPSHOT_MODE") == NULL); + fsrv->nyx_runner, getenv("AFL_NYX_DISABLE_SNAPSHOT_MODE") == NULL); fsrv->nyx_handlers->nyx_option_apply(fsrv->nyx_runner); fsrv->nyx_handlers->nyx_option_set_timeout(fsrv->nyx_runner, 2, 0); diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 29659013..3d7adf41 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -302,7 +302,8 @@ static void usage(u8 *argv0, int more_help) { "AFL_NYX_AUX_SIZE: size of the Nyx auxiliary buffer. Must be a multiple of 4096.\n" " Increase this value in case the crash reports are truncated.\n" " Default value is 4096.\n" - + "AFL_NYX_DISABLE_SNAPSHOT_MODE: disable snapshot mode (must be supported by the agent)\n" + "AFL_NYX_REUSE_SNAPSHOT: reuse an existing Nyx root snapshot\n" DYN_COLOR "AFL_PATH: path to AFL support binaries\n" -- cgit v1.2.3 From 247d8539feb0dee3eab80586ee4e32292dc7ca78 Mon Sep 17 00:00:00 2001 From: Jesse Schwartzentruber Date: Fri, 4 Aug 2023 15:29:10 -0400 Subject: Add AFL_NYX_LOG to redirect NYX hprintf messages to a file. --- src/afl-forkserver.c | 19 +++++++++++++++++++ src/afl-fuzz.c | 1 + 2 files changed, 20 insertions(+) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 717898d1..9da096f7 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -164,6 +164,8 @@ void afl_nyx_runner_kill(afl_forkserver_t *fsrv) { } + if (fsrv->nyx_log_fd >= 0) { close(fsrv->nyx_log_fd); } + } } @@ -218,6 +220,7 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) { fsrv->nyx_bind_cpu_id = 0xFFFFFFFF; fsrv->nyx_use_tmp_workdir = false; fsrv->nyx_tmp_workdir_path = NULL; + fsrv->nyx_log_fd = -1; #endif // this structure needs default so we initialize it if this was not done @@ -575,6 +578,22 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, fsrv->nyx_handlers->nyx_config_set_input_buffer_write_protection(nyx_config, true); + char *nyx_log_path = getenv("AFL_NYX_LOG"); + if (nyx_log_path) { + + fsrv->nyx_log_fd = + open(nyx_log_path, O_CREAT | O_TRUNC | O_WRONLY, DEFAULT_PERMISSION); + if (fsrv->nyx_log_fd < 0) { + + NYX_PRE_FATAL(fsrv, "AFL_NYX_LOG path could not be written"); + + } + + fsrv->nyx_handlers->nyx_config_set_hprintf_fd(nyx_config, + fsrv->nyx_log_fd); + + } + if (fsrv->nyx_standalone) { fsrv->nyx_handlers->nyx_config_set_process_role(nyx_config, StandAlone); diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 3d7adf41..e1f93f0d 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -303,6 +303,7 @@ static void usage(u8 *argv0, int more_help) { " Increase this value in case the crash reports are truncated.\n" " Default value is 4096.\n" "AFL_NYX_DISABLE_SNAPSHOT_MODE: disable snapshot mode (must be supported by the agent)\n" + "AFL_NYX_LOG: output NYX hprintf messages to another file\n" "AFL_NYX_REUSE_SNAPSHOT: reuse an existing Nyx root snapshot\n" DYN_COLOR -- cgit v1.2.3 From 2c376f899456f3c9ecd010832e5be87c59e8c947 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Tue, 8 Aug 2023 21:24:05 +0100 Subject: afl-fuzz-redqueen.c fix build, also forgotten math lib for ilog* calls --- src/afl-fuzz-redqueen.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index ca5104c0..509f66a3 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -2525,6 +2525,7 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, */ #ifdef _DEBUG + u32 j; struct cmp_header *hh = &afl->orig_cmp_map->headers[key]; fprintf(stderr, "RTN N hits=%u id=%u shape=%u attr=%u v0=", h->hits, h->id, hshape, h->attribute); -- cgit v1.2.3 From d9cadb2e7db1d1c208cd40299f0e5c4f6364aa2c Mon Sep 17 00:00:00 2001 From: marc Date: Wed, 9 Aug 2023 16:31:30 +0200 Subject: -c - support --- src/afl-fuzz.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index e1f93f0d..cdb3f996 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -180,7 +180,8 @@ static void usage(u8 *argv0, int more_help) { "it.\n" " if using QEMU/FRIDA or the fuzzing target is " "compiled\n" - " for CmpLog then just use -c 0.\n" + " for CmpLog then use '-c 0'. To disable Cmplog use '-c " + "-'.\n" " -l cmplog_opts - CmpLog configuration values (e.g. \"2ATR\"):\n" " 1=small files, 2=larger files (default), 3=all " "files,\n" @@ -600,8 +601,23 @@ int main(int argc, char **argv_orig, char **envp) { case 'c': { - afl->shm.cmplog_mode = 1; - afl->cmplog_binary = ck_strdup(optarg); + if (strcmp(optarg, "-") == 0) { + + if (afl->shm.cmplog_mode) { + + ACTF("Disabling cmplog again because of '-c -'."); + afl->shm.cmplog_mode = 0; + afl->cmplog_binary = NULL; + + } + + } else { + + afl->shm.cmplog_mode = 1; + afl->cmplog_binary = ck_strdup(optarg); + + } + break; } @@ -1510,8 +1526,7 @@ int main(int argc, char **argv_orig, char **envp) { if (!afl->use_banner) { afl->use_banner = argv[optind]; } - if (afl->shm.cmplog_mode && - (!strcmp("-", afl->cmplog_binary) || !strcmp("0", afl->cmplog_binary))) { + if (afl->shm.cmplog_mode && strcmp("0", afl->cmplog_binary) == 0) { afl->cmplog_binary = strdup(argv[optind]); -- cgit v1.2.3 From 55d696fbae435e0e69adf75cb2df1361186fb999 Mon Sep 17 00:00:00 2001 From: marc Date: Wed, 9 Aug 2023 17:14:13 +0200 Subject: code format --- src/afl-fuzz-init.c | 42 ++++++++++++++++++++++++------------------ src/afl-fuzz-redqueen.c | 2 +- src/afl-fuzz.c | 2 +- 3 files changed, 26 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index d994d749..5a530821 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1057,18 +1057,21 @@ void perform_dry_run(afl_state_t *afl) { fn, (int)(s8)afl->fsrv.crash_exitcode); } else { + if (afl->afl_env.afl_crashing_seeds_as_new_crash) { - + WARNF( "Test case '%s' results in a crash, " "as AFL_CRASHING_SEEDS_AS_NEW_CRASH is set, " - "saving as a new crash", fn); - + "saving as a new crash", + fn); + } else { WARNF("Test case '%s' results in a crash, skipping", fn); - + } + } if (afl->afl_env.afl_exit_on_seed_issues) { @@ -1089,20 +1092,19 @@ void perform_dry_run(afl_state_t *afl) { /* Crashing seeds will be regarded as new crashes on startup */ if (afl->afl_env.afl_crashing_seeds_as_new_crash) { - + ++afl->total_crashes; if (likely(!afl->non_instrumented_mode)) { classify_counts(&afl->fsrv); - + simplify_trace(afl, afl->fsrv.trace_bits); if (!has_new_bits(afl, afl->virgin_crash)) { break; } } - if (unlikely(!afl->saved_crashes) && (afl->afl_env.afl_no_crash_readme != 1)) { @@ -1116,18 +1118,22 @@ void perform_dry_run(afl_state_t *afl) { afl->stage_name = "dry_run"; afl->stage_short = "dry_run"; - #ifndef SIMPLE_FILES +#ifndef SIMPLE_FILES - snprintf(crash_fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s", afl->out_dir, - afl->saved_crashes, afl->fsrv.last_kill_signal, - describe_op(afl, 0, NAME_MAX - strlen("id:000000,sig:00,") - strlen(use_name)), use_name); + snprintf(crash_fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s", + afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal, + describe_op(afl, 0, + NAME_MAX - strlen("id:000000,sig:00,") - + strlen(use_name)), + use_name); - #else +#else - snprintf(crash_fn, PATH_MAX, "%s/crashes/id_%06llu_%02u", afl->out_dir, - afl->saved_crashes, afl->fsrv.last_kill_signal); + snprintf(crash_fn, PATH_MAX, "%s/crashes/id_%06llu_%02u", + afl->out_dir, afl->saved_crashes, + afl->fsrv.last_kill_signal); - #endif +#endif ++afl->saved_crashes; @@ -1169,12 +1175,12 @@ void perform_dry_run(afl_state_t *afl) { } } - + q->disabled = 1; q->perf_score = 0; - break; - + break; + case FSRV_RUN_ERROR: FATAL("Unable to execute target application ('%s')", afl->argv[0]); diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 509f66a3..db4991db 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -2525,7 +2525,7 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, */ #ifdef _DEBUG - u32 j; + u32 j; struct cmp_header *hh = &afl->orig_cmp_map->headers[key]; fprintf(stderr, "RTN N hits=%u id=%u shape=%u attr=%u v0=", h->hits, h->id, hshape, h->attribute); diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 733c7429..cdb3f996 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1592,7 +1592,7 @@ int main(int argc, char **argv_orig, char **envp) { if (get_afl_env("AFL_NO_ARITH")) { afl->no_arith = 1; } if (get_afl_env("AFL_SHUFFLE_QUEUE")) { afl->shuffle_queue = 1; } if (get_afl_env("AFL_EXPAND_HAVOC_NOW")) { afl->expand_havoc = 1; } - + if (afl->afl_env.afl_autoresume) { afl->autoresume = 1; -- cgit v1.2.3 From 8823f22a9c87123c1bfcc5bff10044de4c7a4a1f Mon Sep 17 00:00:00 2001 From: marc Date: Fri, 11 Aug 2023 11:22:18 +0200 Subject: add AFL_FINAL_SYNC --- src/afl-fuzz-state.c | 7 +++++++ src/afl-fuzz.c | 9 +++++++++ 2 files changed, 16 insertions(+) (limited to 'src') diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 5a6b95cf..97e00415 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -269,6 +269,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_import_first = get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_FINAL_SYNC", + + afl_environment_variable_len)) { + + afl->afl_env.afl_final_sync = + get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_CUSTOM_MUTATOR_ONLY", afl_environment_variable_len)) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index cdb3f996..c2ec4a1d 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2899,6 +2899,15 @@ stop_fuzzing: time_spent_working / afl->fsrv.total_execs); #endif + if (afl->afl_env.afl_final_sync) { + + SAYF(cYEL "[!] " cRST "\nPerforming final sync, this make take some time ...\n"); + sync_fuzzers(afl); + write_bitmap(afl); + SAYF(cYEL "[!] " cRST "Done!\n\n"); + + } + if (afl->is_main_node) { u8 path[PATH_MAX]; -- cgit v1.2.3 From 030799638ddb7bd42d97fea81951c7cb246e263b Mon Sep 17 00:00:00 2001 From: chinggg <24590067+chinggg@users.noreply.github.com> Date: Sun, 13 Aug 2023 00:24:44 +0800 Subject: Remove redundant comparison of `fav_factor` in `update_bitmap_score` `top_rated_fav_factor` was actually calculated twice, but only one calculation and comparison is needed. Since `fav_factor` > `top_rated_fav_factor` will always cause skip of current iteration, `else if (fuzz_p2 == top_rated_fuzz_p2)` is also redundant. --- src/afl-fuzz-queue.c | 25 ++----------------------- 1 file changed, 2 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 48fd33ec..20973f51 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -746,30 +746,9 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { } - if (fuzz_p2 > top_rated_fuzz_p2) { + if (fuzz_p2 > top_rated_fuzz_p2) continue; - continue; - - } else if (fuzz_p2 == top_rated_fuzz_p2) { - - if (fav_factor > top_rated_fav_factor) { continue; } - - } - - if (unlikely(afl->schedule >= RARE) || unlikely(afl->fixed_seed)) { - - if (fav_factor > afl->top_rated[i]->len << 2) { continue; } - - } else { - - if (fav_factor > - afl->top_rated[i]->exec_us * afl->top_rated[i]->len) { - - continue; - - } - - } + if (fav_factor > top_rated_fav_factor) continue; /* Looks like we're going to win. Decrease ref count for the previous winner, discard its afl->fsrv.trace_bits[] if necessary. */ -- cgit v1.2.3 From 26f29fd485efaa08824c27501f82caeea525b5e3 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 13 Aug 2023 10:18:33 +0200 Subject: nits --- src/afl-fuzz-bitmap.c | 2 +- src/afl-fuzz-queue.c | 27 ++++++++++++++++++++------- src/afl-fuzz.c | 3 ++- 3 files changed, 23 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 87157cad..0429db34 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -474,7 +474,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { /* Generating a hash on every input is super expensive. Bad idea and should only be used for special schedules */ - if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) { + if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) { classify_counts(&afl->fsrv); classified = 1; diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 20973f51..14ba1ace 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -701,13 +701,20 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { u64 fav_factor; u64 fuzz_p2; - if (unlikely(afl->schedule >= FAST && afl->schedule < RARE)) + if (likely(afl->schedule >= FAST && afl->schedule < RARE)) { + fuzz_p2 = 0; // Skip the fuzz_p2 comparison - else if (unlikely(afl->schedule == RARE)) + + } else if (unlikely(afl->schedule == RARE)) { + fuzz_p2 = next_pow2(afl->n_fuzz[q->n_fuzz_entry]); - else + + } else { + fuzz_p2 = q->fuzz_level; + } + if (unlikely(afl->schedule >= RARE) || unlikely(afl->fixed_seed)) { fav_factor = q->len << 2; @@ -729,12 +736,18 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { /* Faster-executing or smaller test cases are favored. */ u64 top_rated_fav_factor; u64 top_rated_fuzz_p2; - if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) + + if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) { + top_rated_fuzz_p2 = next_pow2(afl->n_fuzz[afl->top_rated[i]->n_fuzz_entry]); - else + + } else { + top_rated_fuzz_p2 = afl->top_rated[i]->fuzz_level; + } + if (unlikely(afl->schedule >= RARE) || unlikely(afl->fixed_seed)) { top_rated_fav_factor = afl->top_rated[i]->len << 2; @@ -746,9 +759,9 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { } - if (fuzz_p2 > top_rated_fuzz_p2) continue; + if (likely(fuzz_p2 > top_rated_fuzz_p2)) { continue; } - if (fav_factor > top_rated_fav_factor) continue; + if (likely(fav_factor > top_rated_fav_factor)) { continue; } /* Looks like we're going to win. Decrease ref count for the previous winner, discard its afl->fsrv.trace_bits[] if necessary. */ diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index c2ec4a1d..93bcdccf 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2901,7 +2901,8 @@ stop_fuzzing: if (afl->afl_env.afl_final_sync) { - SAYF(cYEL "[!] " cRST "\nPerforming final sync, this make take some time ...\n"); + SAYF(cYEL "[!] " cRST + "\nPerforming final sync, this make take some time ...\n"); sync_fuzzers(afl); write_bitmap(afl); SAYF(cYEL "[!] " cRST "Done!\n\n"); -- cgit v1.2.3 From 8cf6a13eb7f0d56495baf92745fae3084dc2fb67 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 17 Aug 2023 11:47:12 +0200 Subject: add env var to help output --- src/afl-fuzz.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 93bcdccf..43834172 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -299,6 +299,7 @@ static void usage(u8 *argv0, int more_help) { "AFL_NO_FORKSRV: run target via execve instead of using the forkserver\n" "AFL_NO_SNAPSHOT: do not use the snapshot feature (if the snapshot lkm is loaded)\n" "AFL_NO_STARTUP_CALIBRATION: no initial seed calibration, start fuzzing at once\n" + "AFL_NO_WARN_INSTABILITY: no warn about instability issues on startup calibration\n" "AFL_NO_UI: switch status screen off\n" "AFL_NYX_AUX_SIZE: size of the Nyx auxiliary buffer. Must be a multiple of 4096.\n" " Increase this value in case the crash reports are truncated.\n" -- cgit v1.2.3 From 53c26d086b94c4e5f31dddac0dd212cbff89e957 Mon Sep 17 00:00:00 2001 From: "Samuel E. Moelius III" Date: Sat, 19 Aug 2023 08:17:23 -0400 Subject: Loosen `ReportCrash` check --- src/afl-fuzz-init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 5a530821..4c09fab7 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -2270,7 +2270,7 @@ void check_crash_handling(void) { reporting the awful way. */ #if !TARGET_OS_IPHONE - if (system("launchctl list 2>/dev/null | grep -q '\\.ReportCrash$'")) return; + if (system("launchctl list 2>/dev/null | grep -q '\\.ReportCrash\\>'")) return; SAYF( "\n" cLRD "[-] " cRST -- cgit v1.2.3 From 549e5dd9269238ac43ff482d439f7f671946185c Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 23 Aug 2023 18:02:33 +0200 Subject: AFL_IGNORE_SEED_PROBLEMS --- src/afl-fuzz-init.c | 53 ++++++++++++++++++++++++++++++++++++++++------------ src/afl-fuzz-state.c | 7 +++++++ src/afl-fuzz.c | 2 ++ 3 files changed, 50 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 4c09fab7..9fc0cc57 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -951,19 +951,47 @@ void perform_dry_run(afl_state_t *afl) { } else { - SAYF("\n" cLRD "[-] " cRST - "The program took more than %u ms to process one of the initial " - "test cases.\n" - " This is bad news; raising the limit with the -t option is " - "possible, but\n" - " will probably make the fuzzing process extremely slow.\n\n" + static int say_once = 0; + + if (!say_once) { + + SAYF( + "\n" cLRD "[-] " cRST + "The program took more than %u ms to process one of the " + "initial " + "test cases.\n" + " This is bad news; raising the limit with the -t option is " + "possible, but\n" + " will probably make the fuzzing process extremely slow.\n\n" + + " If this test case is just a fluke, the other option is to " + "just avoid it\n" + " altogether, and find one that is less of a CPU hog.\n", + afl->fsrv.exec_tmout); + + if (!afl->afl_env.afl_ignore_seed_problems) { + + FATAL("Test case '%s' results in a timeout", fn); + + } + + say_once = 1; + + } + + if (!q->was_fuzzed) { - " If this test case is just a fluke, the other option is to " - "just avoid it\n" - " altogether, and find one that is less of a CPU hog.\n", - afl->fsrv.exec_tmout); + q->was_fuzzed = 1; + --afl->pending_not_fuzzed; + --afl->active_items; - FATAL("Test case '%s' results in a timeout", fn); + } + + q->disabled = 1; + q->perf_score = 0; + + WARNF("Test case '%s' results in a timeout, skipping", fn); + break; } @@ -2270,7 +2298,8 @@ void check_crash_handling(void) { reporting the awful way. */ #if !TARGET_OS_IPHONE - if (system("launchctl list 2>/dev/null | grep -q '\\.ReportCrash\\>'")) return; + if (system("launchctl list 2>/dev/null | grep -q '\\.ReportCrash\\>'")) + return; SAYF( "\n" cLRD "[-] " cRST diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 97e00415..db82536d 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -316,6 +316,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_ignore_problems = get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_IGNORE_SEED_PROBLEMS", + + afl_environment_variable_len)) { + + afl->afl_env.afl_ignore_seed_problems = + get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_IGNORE_TIMEOUTS", afl_environment_variable_len)) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 43834172..08960ac6 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -275,6 +275,8 @@ static void usage(u8 *argv0, int more_help) { "AFL_IGNORE_PROBLEMS: do not abort fuzzing if an incorrect setup is detected\n" "AFL_IGNORE_PROBLEMS_COVERAGE: if set in addition to AFL_IGNORE_PROBLEMS - also\n" " ignore those libs for coverage\n" + "AFL_IGNORE_SEED_PROBLEMS: skip over crashes and timeouts in the seeds instead of\n" + " exiting\n" "AFL_IGNORE_TIMEOUTS: do not process or save any timeouts\n" "AFL_IGNORE_UNKNOWN_ENVS: don't warn on unknown env vars\n" "AFL_IMPORT_FIRST: sync and import test cases from other fuzzer instances first\n" -- cgit v1.2.3 From 4a7e35b29c6711b68d3d579716685c3752ff62a8 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 24 Aug 2023 09:26:54 +0200 Subject: add missing envs --- src/afl-fuzz.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 08960ac6..8b9c1e50 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -265,6 +265,7 @@ static void usage(u8 *argv0, int more_help) { "AFL_DUMB_FORKSRV: use fork server without feedback from target\n" "AFL_EXIT_WHEN_DONE: exit when all inputs are run and no new finds are found\n" "AFL_EXIT_ON_TIME: exit when no new coverage is found within the specified time\n" + "AFL_EXIT_ON_SEED_ISSUES: exit on any kind of seed issues\n" "AFL_EXPAND_HAVOC_NOW: immediately enable expand havoc mode (default: after 60\n" " minutes and a cycle without finds)\n" "AFL_FAST_CAL: limit the calibration stage to three cycles for speedup\n" @@ -331,6 +332,7 @@ static void usage(u8 *argv0, int more_help) { "AFL_STATSD_TAGS_FLAVOR: set statsd tags format (default: disable tags)\n" " suported formats: dogstatsd, librato, signalfx, influxdb\n" "AFL_SYNC_TIME: sync time between fuzzing instances (in minutes)\n" + "AFL_FINAL_SYNC: sync a final time when exiting (will delay the exit!)\n" "AFL_NO_CRASH_README: do not create a README in the crashes directory\n" "AFL_TESTCACHE_SIZE: use a cache for testcases, improves performance (in MB)\n" "AFL_TMPDIR: directory to use for input file generation (ramdisk recommended)\n" -- cgit v1.2.3 From c60431247e971881bc159a84e5505dfec7adcf6d Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 29 Aug 2023 16:38:31 +0200 Subject: update docs --- src/afl-fuzz.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 8b9c1e50..90c255e3 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -176,6 +176,7 @@ static void usage(u8 *argv0, int more_help) { " pacemaker mode (minutes of no new finds). 0 = " "immediately,\n" " -1 = immediately and together with normal mutation.\n" + " Note: this option is usually not very effective\n" " -c program - enable CmpLog by specifying a binary compiled for " "it.\n" " if using QEMU/FRIDA or the fuzzing target is " -- cgit v1.2.3 From 78848f863767cee6543166bd52d67e0051641360 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 31 Aug 2023 09:25:41 +0200 Subject: pendfav --- src/afl-fuzz.c | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 90c255e3..c8cc7da6 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2707,22 +2707,42 @@ int main(int argc, char **argv_orig, char **envp) { if (likely(!afl->old_seed_selection)) { - if (unlikely(prev_queued_items < afl->queued_items || - afl->reinit_table)) { + if (likely(afl->pending_favored)) { - // we have new queue entries since the last run, recreate alias table - prev_queued_items = afl->queued_items; - create_alias_table(afl); + for (u32 iter = 0; iter < afl->queued_items; ++iter) { - } + if (unlikely(afl->queue_buf[iter]->favored && + !afl->queue_buf[iter]->was_fuzzed)) { - do { + afl->current_entry = iter; + afl->queue_cur = afl->queue_buf[afl->current_entry]; + break; - afl->current_entry = select_next_queue_entry(afl); + } - } while (unlikely(afl->current_entry >= afl->queued_items)); + } - afl->queue_cur = afl->queue_buf[afl->current_entry]; + } else { + + if (unlikely(prev_queued_items < afl->queued_items || + afl->reinit_table)) { + + // we have new queue entries since the last run, recreate alias + // table + prev_queued_items = afl->queued_items; + create_alias_table(afl); + + } + + do { + + afl->current_entry = select_next_queue_entry(afl); + + } while (unlikely(afl->current_entry >= afl->queued_items)); + + afl->queue_cur = afl->queue_buf[afl->current_entry]; + + } } -- cgit v1.2.3 From 88ca5c75634d8edfa268005f2e1855a35a5b9e2e Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 31 Aug 2023 14:42:08 +0200 Subject: nit --- src/afl-cc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 86b81459..12707007 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -317,7 +317,7 @@ void parse_fsanitize(char *string) { char *p, *ptr = string + strlen("-fsanitize="); char *new = malloc(strlen(string) + 1); - char *tmp = malloc(strlen(ptr)); + char *tmp = malloc(strlen(ptr) + 1); u32 count = 0, len, ende = 0; if (!new || !tmp) { FATAL("could not acquire memory"); } -- cgit v1.2.3 From a809c3c50ce32fde390769b607b020dd68730474 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 3 Sep 2023 11:22:54 +0200 Subject: less impact --- src/afl-fuzz-one.c | 10 ++++++++-- src/afl-fuzz-queue.c | 13 ++++++++++++- src/afl-fuzz.c | 28 +++++++++++++++++++--------- 3 files changed, 39 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 2ad4697e..ae39abe8 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -3442,7 +3442,12 @@ abandon_entry: --afl->pending_not_fuzzed; afl->queue_cur->was_fuzzed = 1; afl->reinit_table = 1; - if (afl->queue_cur->favored) { --afl->pending_favored; } + if (afl->queue_cur->favored) { + + --afl->pending_favored; + afl->smallest_favored = -1; + + } } @@ -5905,7 +5910,8 @@ pacemaker_fuzzing: --afl->pending_not_fuzzed; afl->queue_cur->was_fuzzed = 1; - if (afl->queue_cur->favored) { --afl->pending_favored; } + if (afl->queue_cur->favored) { --afl->pending_favored; + afl->smallest_favored = -1; } } diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 14ba1ace..5f915c9a 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -826,6 +826,8 @@ void cull_queue(afl_state_t *afl) { /* Let's see if anything in the bitmap isn't captured in temp_v. If yes, and if it has a afl->top_rated[] contender, let's use it. */ + afl->smallest_favored = -1; + for (i = 0; i < afl->fsrv.map_size; ++i) { if (afl->top_rated[i] && (temp_v[i >> 3] & (1 << (i & 7)))) { @@ -849,7 +851,16 @@ void cull_queue(afl_state_t *afl) { afl->top_rated[i]->favored = 1; ++afl->queued_favored; - if (!afl->top_rated[i]->was_fuzzed) { ++afl->pending_favored; } + if (!afl->top_rated[i]->was_fuzzed) { + + ++afl->pending_favored; + if (unlikely(afl->smallest_favored > (s64)afl->top_rated[i]->id)) { + + afl->smallest_favored = (s64)afl->top_rated[i]->id; + + } + + } } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index c8cc7da6..d34b52db 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2707,20 +2707,30 @@ int main(int argc, char **argv_orig, char **envp) { if (likely(!afl->old_seed_selection)) { - if (likely(afl->pending_favored)) { + if (likely(afl->pending_favored && afl->smallest_favored >= 0)) { - for (u32 iter = 0; iter < afl->queued_items; ++iter) { + afl->current_entry = afl->smallest_favored; - if (unlikely(afl->queue_buf[iter]->favored && - !afl->queue_buf[iter]->was_fuzzed)) { + /* - afl->current_entry = iter; - afl->queue_cur = afl->queue_buf[afl->current_entry]; - break; + } else { - } + for (s32 iter = afl->queued_items - 1; iter >= 0; --iter) + { - } + if (unlikely(afl->queue_buf[iter]->favored && + !afl->queue_buf[iter]->was_fuzzed)) { + + afl->current_entry = iter; + break; + + } + + } + + */ + + afl->queue_cur = afl->queue_buf[afl->current_entry]; } else { -- cgit v1.2.3 From d83edc6175b8a4aa9f1a89c118b0ecf93dcef31c Mon Sep 17 00:00:00 2001 From: chinggg <24590067+chinggg@users.noreply.github.com> Date: Sun, 3 Sep 2023 19:20:44 +0800 Subject: Skip calculating top_rated_fuzz_p2 with FAST schedule when FAST schedule is used, fuzz_p2 is already set to 0 so `fuzz_p2 > top_rated_fuzz_p2` never happens, just set top_rated_fuzz_p2 to 0 to reduce calculation --- src/afl-fuzz-queue.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 14ba1ace..793bec90 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -737,7 +737,11 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { u64 top_rated_fav_factor; u64 top_rated_fuzz_p2; - if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) { + if (likely(afl->schedule >= FAST && afl->schedule < RARE)) { + + top_rated_fuzz_p2 = 0; // Skip the fuzz_p2 comparison + + } else if (unlikely(afl->schedule == RARE)) { top_rated_fuzz_p2 = next_pow2(afl->n_fuzz[afl->top_rated[i]->n_fuzz_entry]); -- cgit v1.2.3 From cd6b89eb74cc501a67b1c14a4433a496b2053eec Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 3 Sep 2023 13:54:54 +0200 Subject: nit --- src/afl-fuzz-queue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 5f915c9a..2b102879 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -854,7 +854,7 @@ void cull_queue(afl_state_t *afl) { if (!afl->top_rated[i]->was_fuzzed) { ++afl->pending_favored; - if (unlikely(afl->smallest_favored > (s64)afl->top_rated[i]->id)) { + if (unlikely(afl->smallest_favored < 0)) { afl->smallest_favored = (s64)afl->top_rated[i]->id; -- cgit v1.2.3 From 87b33740ea426bac276a9eb4bc5f201bd396b6dc Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 4 Sep 2023 13:38:09 +0200 Subject: ensure table reinit, downgrade redundant --- src/afl-fuzz-init.c | 5 +++++ src/afl-fuzz-one.c | 1 + src/afl-fuzz-queue.c | 3 +++ src/afl-fuzz.c | 2 +- 4 files changed, 10 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 9fc0cc57..35932913 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -942,6 +942,7 @@ void perform_dry_run(afl_state_t *afl) { if (!q->was_fuzzed) { q->was_fuzzed = 1; + afl->reinit_table = 1; --afl->pending_not_fuzzed; --afl->active_items; @@ -982,6 +983,7 @@ void perform_dry_run(afl_state_t *afl) { if (!q->was_fuzzed) { q->was_fuzzed = 1; + afl->reinit_table = 1; --afl->pending_not_fuzzed; --afl->active_items; @@ -1113,6 +1115,7 @@ void perform_dry_run(afl_state_t *afl) { if (!q->was_fuzzed) { q->was_fuzzed = 1; + afl->reinit_table = 1; --afl->pending_not_fuzzed; --afl->active_items; @@ -1291,6 +1294,7 @@ void perform_dry_run(afl_state_t *afl) { if (!p->was_fuzzed) { p->was_fuzzed = 1; + afl->reinit_table = 1; --afl->pending_not_fuzzed; --afl->active_items; @@ -1311,6 +1315,7 @@ void perform_dry_run(afl_state_t *afl) { if (!q->was_fuzzed) { q->was_fuzzed = 1; + afl->reinit_table = 1; --afl->pending_not_fuzzed; --afl->active_items; diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 2ad4697e..c2b7e583 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -5905,6 +5905,7 @@ pacemaker_fuzzing: --afl->pending_not_fuzzed; afl->queue_cur->was_fuzzed = 1; + afl->reinit_table = 1 if (afl->queue_cur->favored) { --afl->pending_favored; } } diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 14ba1ace..78c1d654 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -80,6 +80,7 @@ double compute_weight(afl_state_t *afl, struct queue_entry *q, if (unlikely(weight < 0.1)) { weight = 0.1; } if (unlikely(q->favored)) { weight *= 5; } if (unlikely(!q->was_fuzzed)) { weight *= 2; } + if (unlikely(q->fs_redundant)) { weight *= 0.2; } return weight; @@ -867,6 +868,8 @@ void cull_queue(afl_state_t *afl) { } + afl->reinit_table = 1; + } /* Calculate case desirability score to adjust the length of havoc fuzzing. diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 90c255e3..768a5bbd 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2369,7 +2369,7 @@ int main(int argc, char **argv_orig, char **envp) { } else { - ACTF("skipping initial seed calibration due option override"); + ACTF("skipping initial seed calibration due option override!"); usleep(1000); } -- cgit v1.2.3 From 5f6c76e192bcfde6abcf9d4156bfbb87d5480e23 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 8 Sep 2023 13:40:57 +0200 Subject: fix cmplog forkserver kill signal --- src/afl-forkserver.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 9da096f7..07f5a1a9 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -272,6 +272,7 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) { fsrv_to->uses_crash_exitcode = from->uses_crash_exitcode; fsrv_to->crash_exitcode = from->crash_exitcode; fsrv_to->child_kill_signal = from->child_kill_signal; + fsrv_to->fsrv_kill_signal = from->fsrv_kill_signal; fsrv_to->debug = from->debug; // These are forkserver specific. -- cgit v1.2.3 From 6c7c4b821adae1ed244973127426ef2e966f6350 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 11 Sep 2023 14:56:34 +0200 Subject: reweight redundant --- src/afl-fuzz-one.c | 3 +++ src/afl-fuzz-queue.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index db88f239..2003be1f 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -5912,9 +5912,12 @@ pacemaker_fuzzing: afl->queue_cur->was_fuzzed = 1; afl->reinit_table = 1 if (afl->queue_cur->favored) { + --afl->pending_favored; afl->smallest_favored = -1; + } + } } diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index ce9718b0..4b9627f7 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -80,7 +80,7 @@ double compute_weight(afl_state_t *afl, struct queue_entry *q, if (unlikely(weight < 0.1)) { weight = 0.1; } if (unlikely(q->favored)) { weight *= 5; } if (unlikely(!q->was_fuzzed)) { weight *= 2; } - if (unlikely(q->fs_redundant)) { weight *= 0.2; } + if (unlikely(q->fs_redundant)) { weight *= 0.8; } return weight; -- cgit v1.2.3 From 3b835b7c8b2f73be6d5972951d049cef66c24abd Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 12 Sep 2023 16:05:56 +0200 Subject: increase sync length --- src/afl-fuzz.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index a3d5e300..f659395e 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1492,9 +1492,9 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->sync_id) { - if (strlen(afl->sync_id) > 24) { + if (strlen(afl->sync_id) > 50) { - FATAL("sync_id max length is 24 characters"); + FATAL("sync_id max length is 50 characters"); } -- cgit v1.2.3 From 98eed79f5701726d6fe566832707f32ab6d42e3e Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 13 Sep 2023 09:39:06 +0200 Subject: -a default --- src/afl-fuzz.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index f659395e..cf57702f 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -536,6 +536,10 @@ int main(int argc, char **argv_orig, char **envp) { afl->input_mode = 2; + } else if (!stricmp(optarg, "def") || !stricmp(optarg, "default")) { + + afl->input_mode = 0; + } else { FATAL("-a input mode needs to be \"text\" or \"binary\"."); -- cgit v1.2.3 From 6dc054be0faa2fe934ec24465f75fb8676798d13 Mon Sep 17 00:00:00 2001 From: Thomas Rooijakkers Date: Tue, 19 Sep 2023 13:42:53 +0200 Subject: Add usage compilation status print for NO_UTF --- src/afl-fuzz.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index cf57702f..9aaec2c7 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -381,6 +381,12 @@ static void usage(u8 *argv0, int more_help) { SAYF("Compiled with NO_SPLICING.\n"); #endif +#ifdef NO_UTF + SAYF("Compiled without UTF-8 support for line rendering in status screen.\n"); +#else + SAYF("Compiled with UTF-8 support for line rendering in status screen.\n"); +#endif + #ifdef PROFILING SAYF("Compiled with PROFILING.\n"); #endif -- cgit v1.2.3 From abbdf1c3ac61322e9fd55a78fbb3ad60c6e68971 Mon Sep 17 00:00:00 2001 From: Thomas Rooijakkers Date: Tue, 19 Sep 2023 13:52:36 +0200 Subject: Use proper ifdef, remove else in line with other compile options --- src/afl-fuzz.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 9aaec2c7..86c05223 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -381,10 +381,8 @@ static void usage(u8 *argv0, int more_help) { SAYF("Compiled with NO_SPLICING.\n"); #endif -#ifdef NO_UTF +#ifdef FANCY_BOXES_NO_UTF SAYF("Compiled without UTF-8 support for line rendering in status screen.\n"); -#else - SAYF("Compiled with UTF-8 support for line rendering in status screen.\n"); #endif #ifdef PROFILING -- cgit v1.2.3 From 5eb4c6eacdce06ef0313c389ce1616f52110dbb0 Mon Sep 17 00:00:00 2001 From: Nikolay Shaplov Date: Tue, 19 Sep 2023 21:55:40 +0300 Subject: Use shorter fuzzer name in stat header when user's banner is too big --- src/afl-fuzz-stats.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 3d0a9b9a..adf04420 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -778,10 +778,29 @@ void show_stats_normal(afl_state_t *afl) { if (unlikely(!banner[0])) { char *si = ""; + char *fuzzer_name; + if (afl->sync_id) { si = afl->sync_id; } memset(banner, 0, sizeof(banner)); - banner_len = (afl->crash_mode ? 20 : 18) + strlen(VERSION) + strlen(si) + - strlen(afl->power_name) + 4 + 6; + + banner_len = strlen(VERSION) + strlen(si) + strlen(afl->power_name) + 4 + 6; + + if (afl->crash_mode) { + + fuzzer_name = "peruvian were-rabbit"; + + } else { + + fuzzer_name = "american fuzzy lop"; + if (banner_len + strlen(fuzzer_name) + strlen(afl->use_banner) > 75) { + + fuzzer_name = "AFL"; + + } + + } + + banner_len += strlen(fuzzer_name); if (strlen(afl->use_banner) + banner_len > 75) { @@ -798,18 +817,16 @@ void show_stats_normal(afl_state_t *afl) { if (afl->fsrv.nyx_mode) { snprintf(banner + banner_pad, sizeof(banner) - banner_pad, - "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s] - Nyx", - afl->crash_mode ? cPIN "peruvian were-rabbit" - : cYEL "american fuzzy lop", + "%s%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s] - Nyx", + afl->crash_mode ? cPIN : cYEL, fuzzer_name, si, afl->use_banner, afl->power_name); } else { #endif snprintf(banner + banner_pad, sizeof(banner) - banner_pad, - "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]", - afl->crash_mode ? cPIN "peruvian were-rabbit" - : cYEL "american fuzzy lop", + "%s%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]", + afl->crash_mode ? cPIN : cYEL, fuzzer_name, si, afl->use_banner, afl->power_name); #ifdef __linux__ -- cgit v1.2.3 From 5f7c3a1ee0d6f20e42a207a7e75e0f19e726a0f5 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 27 Sep 2023 16:32:55 +0200 Subject: fix afl-cc help output --- src/afl-cc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 12707007..037a5c30 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -2118,6 +2118,8 @@ int main(int argc, char **argv, char **envp) { " [LLVM] LLVM: %s%s\n" " PCGUARD %s yes yes module yes yes " "yes\n" + " NATIVE AVAILABLE no yes no no " + "part. yes\n" " CLASSIC %s no yes module yes yes " "yes\n" " - NORMAL\n" @@ -2137,10 +2139,10 @@ int main(int argc, char **argv, char **envp) { "no\n\n", have_llvm ? "AVAILABLE" : "unavailable!", compiler_mode == LLVM ? " [SELECTED]" : "", + have_llvm ? "AVAILABLE" : "unavailable!", + have_llvm ? "AVAILABLE" : "unavailable!", have_lto ? "AVAILABLE" : "unavailable!", compiler_mode == LTO ? " [SELECTED]" : "", - LLVM_MAJOR >= 7 ? "DEFAULT" : " ", - LLVM_MAJOR >= 7 ? " " : "DEFAULT", have_gcc_plugin ? "AVAILABLE" : "unavailable!", compiler_mode == GCC_PLUGIN ? " [SELECTED]" : "", have_gcc ? "AVAILABLE" : "unavailable!", -- cgit v1.2.3 From fd76d6a43304c671422854a062f40c21b0d3d7b1 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 28 Sep 2023 15:35:41 +0200 Subject: fix exploit mode on startup --- src/afl-fuzz.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 86c05223..8574b9b3 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2826,7 +2826,9 @@ int main(int argc, char **argv_orig, char **envp) { if (likely(afl->switch_fuzz_mode && afl->fuzz_mode == 0 && !afl->non_instrumented_mode) && - unlikely(cur_time > afl->last_find_time + afl->switch_fuzz_mode)) { + unlikely(cur_time > (likely(afl->last_find_time) ? afl->last_find_time + : afl->start_time) + + afl->switch_fuzz_mode)) { if (afl->afl_env.afl_no_ui) { -- cgit v1.2.3 From 6b73dee7da4e4e8bd227a9cb156c7a683d124682 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 30 Sep 2023 12:42:40 +0200 Subject: add afl-addseeds tool --- src/afl-fuzz.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 8574b9b3..0a6755d7 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1346,6 +1346,12 @@ int main(int argc, char **argv_orig, char **envp) { } + if (strcmp(afl->sync_id, "addseeds") == 0) { + + FATAL("-M/-S name 'addseeds' is a reserved name, choose something else"); + + } + if (afl->is_main_node == 1 && afl->schedule != FAST && afl->schedule != EXPLORE) { -- cgit v1.2.3 From 9a9dbaff72b127cbb974afa4c1781cf8bc015d15 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 2 Oct 2023 14:41:47 +0200 Subject: remove old credits --- src/afl-performance.c | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'src') diff --git a/src/afl-performance.c b/src/afl-performance.c index 04507410..07c1b527 100644 --- a/src/afl-performance.c +++ b/src/afl-performance.c @@ -1,24 +1,3 @@ -/* - Written in 2019 by David Blackman and Sebastiano Vigna (vigna@acm.org) - - To the extent possible under law, the author has dedicated all copyright - and related and neighboring rights to this software to the public domain - worldwide. This software is distributed without any warranty. - - See . - - This is xoshiro256++ 1.0, one of our all-purpose, rock-solid generators. - It has excellent (sub-ns) speed, a state (256 bits) that is large - enough for any parallel application, and it passes all tests we are - aware of. - - For generating just floating-point numbers, xoshiro256+ is even faster. - - The state must be seeded so that it is not everywhere zero. If you have - a 64-bit seed, we suggest to seed a splitmix64 generator and use its - output to fill s[]. -*/ - #include #include "afl-fuzz.h" #include "types.h" -- cgit v1.2.3 From 1f7f1eff4323720997079d468c9a55096ac2fc3e Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 2 Oct 2023 15:52:11 +0200 Subject: fix addseeds test --- src/afl-fuzz.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 0a6755d7..2538f4a4 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1346,7 +1346,7 @@ int main(int argc, char **argv_orig, char **envp) { } - if (strcmp(afl->sync_id, "addseeds") == 0) { + if (afl->sync_id && strcmp(afl->sync_id, "addseeds") == 0) { FATAL("-M/-S name 'addseeds' is a reserved name, choose something else"); -- cgit v1.2.3 From d97c7e42584e2c1e094a7c57fa469bf3b5b46b21 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 3 Oct 2023 11:14:59 +0200 Subject: nits --- src/afl-fuzz-stats.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index adf04420..81628a86 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -817,17 +817,18 @@ void show_stats_normal(afl_state_t *afl) { if (afl->fsrv.nyx_mode) { snprintf(banner + banner_pad, sizeof(banner) - banner_pad, - "%s%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s] - Nyx", - afl->crash_mode ? cPIN : cYEL, fuzzer_name, - si, afl->use_banner, afl->power_name); + "%s%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN + "[%s] - Nyx", + afl->crash_mode ? cPIN : cYEL, fuzzer_name, si, afl->use_banner, + afl->power_name); } else { #endif snprintf(banner + banner_pad, sizeof(banner) - banner_pad, "%s%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]", - afl->crash_mode ? cPIN : cYEL, fuzzer_name, - si, afl->use_banner, afl->power_name); + afl->crash_mode ? cPIN : cYEL, fuzzer_name, si, afl->use_banner, + afl->power_name); #ifdef __linux__ -- cgit v1.2.3 From 8eaa590c59e3694e1fdad0aca7bf3f809f8df727 Mon Sep 17 00:00:00 2001 From: Theodor Arsenij Date: Tue, 3 Oct 2023 13:54:19 +0300 Subject: Use sync_id instead of use_banner while building statsd metric messages --- src/afl-fuzz-statsd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz-statsd.c b/src/afl-fuzz-statsd.c index e835c8ea..2e42ea9b 100644 --- a/src/afl-fuzz-statsd.c +++ b/src/afl-fuzz-statsd.c @@ -223,7 +223,7 @@ int statsd_format_metric(afl_state_t *afl, char *buff, size_t bufflen) { char tags[MAX_TAG_LEN * 2] = {0}; if (afl->statsd_tags_format) { - snprintf(tags, MAX_TAG_LEN * 2, afl->statsd_tags_format, afl->use_banner, + snprintf(tags, MAX_TAG_LEN * 2, afl->statsd_tags_format, afl->sync_id, VERSION); } -- cgit v1.2.3 From c622e4c5652b8a3dca8ad057d8c5c2130f735867 Mon Sep 17 00:00:00 2001 From: coco Date: Wed, 4 Oct 2023 12:29:41 -0700 Subject: Make fuzzer_stats update atomic This writes fuzzer_stats to a temp file and then atomically renames the temp file into fuzzer_stats so that any read on fuzzer_stats will always return a consistent view of the AFL state (otherwise there is a very low change of AFL's write and $tool's reads to race and yield inconsistent results). --- src/afl-fuzz-stats.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 81628a86..66e32e78 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -250,11 +250,13 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, #endif u64 cur_time = get_cur_time(); - u8 fn[PATH_MAX]; + u8 fn_tmp[PATH_MAX]; + u8 fn_final[PATH_MAX]; FILE *f; - snprintf(fn, PATH_MAX, "%s/fuzzer_stats", afl->out_dir); - f = create_ffile(fn); + snprintf(fn_tmp, PATH_MAX, "%s/.fuzzer_stats_tmp", afl->out_dir); + snprintf(fn_final, PATH_MAX, "%s/fuzzer_stats", afl->out_dir); + f = create_ffile(fn_tmp); /* Keep last values in case we're called from another context where exec/sec stats and such are not readily available. */ @@ -412,6 +414,7 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, } fclose(f); + rename(fn_tmp, fn_final); } -- cgit v1.2.3 From bfb841d01383a4801a28b007c5f7039f2f28bef9 Mon Sep 17 00:00:00 2001 From: "Christian Holler (:decoder)" Date: Fri, 20 Oct 2023 00:07:35 +0200 Subject: Use proper AFL_NYX_AUX_SIZE for nyx_aux_string --- src/afl-forkserver.c | 12 +++++++++--- src/afl-fuzz-bitmap.c | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 07f5a1a9..9b710733 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -615,8 +615,10 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if (getenv("AFL_NYX_AUX_SIZE") != NULL) { + fsrv->nyx_aux_string_len = atoi(getenv("AFL_NYX_AUX_SIZE")); + if (fsrv->nyx_handlers->nyx_config_set_aux_buffer_size( - nyx_config, atoi(getenv("AFL_NYX_AUX_SIZE"))) != 1) { + nyx_config, fsrv->nyx_aux_string_len) != 1) { NYX_PRE_FATAL(fsrv, "Invalid AFL_NYX_AUX_SIZE value set (must be a multiple " @@ -624,6 +626,10 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } + } else { + + fsrv->nyx_aux_string_len = 0x1000; + } if (getenv("AFL_NYX_REUSE_SNAPSHOT") != NULL) { @@ -697,8 +703,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, fsrv->nyx_handlers->nyx_option_set_timeout(fsrv->nyx_runner, 2, 0); fsrv->nyx_handlers->nyx_option_apply(fsrv->nyx_runner); - fsrv->nyx_aux_string = malloc(0x1000); - memset(fsrv->nyx_aux_string, 0, 0x1000); + fsrv->nyx_aux_string = malloc(fsrv->nyx_aux_string_len); + memset(fsrv->nyx_aux_string, 0, fsrv->nyx_aux_string_len); /* dry run */ fsrv->nyx_handlers->nyx_set_afl_input(fsrv->nyx_runner, "INIT", 4); diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 0429db34..d76158ce 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -866,7 +866,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", fn_log); } u32 nyx_aux_string_len = afl->fsrv.nyx_handlers->nyx_get_aux_string( - afl->fsrv.nyx_runner, afl->fsrv.nyx_aux_string, 0x1000); + afl->fsrv.nyx_runner, afl->fsrv.nyx_aux_string, afl->fsrv.nyx_aux_string_len); ck_write(fd, afl->fsrv.nyx_aux_string, nyx_aux_string_len, fn_log); close(fd); -- cgit v1.2.3 From 4cdf7a1e3e351f10537683d49a08181b6c1576cc Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 23 Oct 2023 18:03:59 +0200 Subject: add scale encode mode for cmplog --- src/afl-fuzz-redqueen.c | 263 +++++++++++++++++++++++++++++++++++++++++++----- src/afl-fuzz.c | 4 + 2 files changed, 243 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index db4991db..b6c54df2 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -40,7 +40,7 @@ enum { IS_FP = 8, // is a floating point, not an integer /* --- below are internal settings, not from target cmplog */ IS_FP_MOD = 16, // arithemtic changed floating point - IS_INT_MOD = 32, // arithmetic changed interger + IS_INT_MOD = 32, // arithmetic changed integer IS_TRANSFORM = 64 // transformed integer }; @@ -775,6 +775,13 @@ static u32 to_base64(u8 *src, u8 *dst, u32 dst_len) { } +#ifdef WORD_SIZE_64 +static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h, + u128 pattern, u128 repl, u128 o_pattern, + u128 changed_val, u8 attr, u32 idx, + u32 taint_len, u8 *orig_buf, u8 *buf, u8 *cbuf, + u32 len, u8 do_reverse, u8 lvl, u8 *status); +#endif static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, u64 pattern, u64 repl, u64 o_pattern, u64 changed_val, u8 attr, u32 idx, u32 taint_len, @@ -807,6 +814,29 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, hshape, attr); */ + u8 bytes; + + switch (hshape) { + + case 0: + case 1: + bytes = 1; + break; + case 2: + bytes = 2; + break; + case 3: + case 4: + bytes = 4; + break; + default: + bytes = 8; + + } + + // necessary for preventing heap access overflow + bytes = MIN(bytes, len - idx); + // reverse atoi()/strnu?toll() is expensive, so we only to it in lvl 3 if (afl->cmplog_enable_transform && (lvl & LVL3)) { @@ -895,29 +925,6 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, if (pattern != o_pattern && repl == changed_val && attr <= IS_EQUAL) { u64 b_val, o_b_val, mask; - u8 bytes; - - switch (hshape) { - - case 0: - case 1: - bytes = 1; - break; - case 2: - bytes = 2; - break; - case 3: - case 4: - bytes = 4; - break; - default: - bytes = 8; - - } - - // necessary for preventing heap access overflow - bytes = MIN(bytes, len - idx); - switch (bytes) { case 0: // cannot happen @@ -1285,6 +1292,125 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, } + // If 'S' is set for cmplog mode then we try a scale encoding of the value. + // Currently we can only handle bytes up to 1 << 55 + + if (attr < IS_FP && attr < 32 && (afl->cmplog_enable_scale || lvl >= LVL3)) { + + u8 do_call = 1; + u64 new_val = repl << 2; + u32 saved_hshape = hshape; + + if (changed_val <= 255) { + + // nothing + + } else if (new_val <= 65535) { + + new_val += 1; // two byte mode + hshape = 2; + + } else if (new_val <= 4294967295) { + + new_val += 2; // four byte mode + hshape = 4; + + } else { + +#ifndef WORD_SIZE_64 + if (repl <= 0x00ffffffffffffff { + + new_val = repl << 8; + u8 scale_len = 0; + u64 tmp_val = repl; + while (tmp_val) { + + tmp_val >>= 8; + ++scale_len; + + } // scale_len will be >= 4; + + if (scale_len >= 4) { + + scale_len -= 4; + + } else { + + scale_len = 0; + + }; + + new_val += (scale_len << 2) + 3; + hshape = 8; + + } else { + + do_call = 0; + + } + +#else + { + + u128 new_val = ((u128)repl) << 8; + u8 scale_len = 0; + u128 tmp_val = (u128)repl; + + while (tmp_val) { + + tmp_val >>= 8; + ++scale_len; + + } // scale_len will be >= 4; + + if (scale_len >= 4) { + + scale_len -= 4; + + } else { + + scale_len = 0; + + }; + + new_val += (scale_len << 2) + 3; + hshape = scale_len + 5; + + if (unlikely(cmp_extend_encodingN(afl, h, (u128)pattern, new_val, + (u128)o_pattern, (u128)changed_val, + 32, idx, taint_len, orig_buf, buf, + cbuf, len, 1, lvl, status))) { + + hshape = saved_hshape; + return 1; + + } + + do_call = 0; + + } + +#endif + + } + + if (do_call) { + + if (unlikely(cmp_extend_encoding( + afl, h, pattern, new_val, o_pattern, changed_val, 32, idx, + taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) { + + hshape = saved_hshape; + return 1; + + } + + } + + hshape = saved_hshape; + + } + // here we add and subract 1 from the value, but only if it is not an // == or != comparison // Bits: 1 = Equal, 2 = Greater, 4 = Lesser, 8 = Float @@ -1551,6 +1677,95 @@ static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h, } + if (attr < IS_FP && attr < 32 && + (afl->cmplog_enable_scale || lvl >= LVL3)) { + + u128 new_val = repl << 2; + u128 max_scale = (u128)1 << 120; + u32 saved_hshape = hshape; + + if (new_val <= 255) { + + hshape = 1; + if (unlikely(cmp_extend_encoding(afl, h, (u64)pattern, new_val, + (u64)o_pattern, (u64)changed_val, 32, + idx, taint_len, orig_buf, buf, cbuf, + len, 1, lvl, status))) { + + hshape = saved_hshape; + return 1; + + } + + } else if (new_val <= 65535) { + + new_val += 1; // two byte mode + hshape = 2; + if (unlikely(cmp_extend_encoding(afl, h, (u64)pattern, new_val, + (u64)o_pattern, (u64)changed_val, 32, + idx, taint_len, orig_buf, buf, cbuf, + len, 1, lvl, status))) { + + hshape = saved_hshape; + return 1; + + } + + } else if (new_val <= 4294967295) { + + new_val += 2; // four byte mode + hshape = 4; + if (unlikely(cmp_extend_encoding(afl, h, (u64)pattern, new_val, + (u64)o_pattern, (u64)changed_val, 32, + idx, taint_len, orig_buf, buf, cbuf, + len, 1, lvl, status))) { + + hshape = saved_hshape; + return 1; + + } + + } else if (repl < max_scale) { + + u128 new_val = (u128)repl << 8; + u8 scale_len = 0; + u128 tmp_val = (u128)repl; + while (tmp_val) { + + tmp_val >>= 8; + ++scale_len; + + } // scale_len will be >= 4; + + if (scale_len >= 4) { + + scale_len -= 4; + + } else { + + scale_len = 0; + + }; + + new_val += (scale_len << 2) + 3; + hshape = scale_len + 5; + + if (unlikely(cmp_extend_encodingN(afl, h, (u128)pattern, new_val, + (u128)o_pattern, (u128)changed_val, + 32, idx, taint_len, orig_buf, buf, + cbuf, len, 1, lvl, status))) { + + hshape = saved_hshape; + return 1; + + } + + } + + hshape = saved_hshape; + + } + } return 0; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 2538f4a4..9fdd2193 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1152,6 +1152,10 @@ int main(int argc, char **argv_orig, char **envp) { case 'A': afl->cmplog_enable_arith = 1; break; + case 's': + case 'S': + afl->cmplog_enable_scale = 1; + break; case 't': case 'T': afl->cmplog_enable_transform = 1; -- cgit v1.2.3 From cf458a7d25dc3448b94ffe08d3d89531fc8d4818 Mon Sep 17 00:00:00 2001 From: Jesse Schwartzentruber Date: Thu, 19 Oct 2023 17:14:31 -0400 Subject: Add an env to afl-clang-fast to disable setting rpath if LLVM path isn't recognized --- src/afl-cc.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 037a5c30..5f8f278f 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1144,19 +1144,22 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (!have_pic) { cc_params[cc_par_cnt++] = "-fPIC"; } - // in case LLVM is installed not via a package manager or "make install" - // e.g. compiled download or compiled from github then its ./lib directory - // might not be in the search path. Add it if so. - u8 *libdir = strdup(LLVM_LIBDIR); - if (plusplus_mode && strlen(libdir) && strncmp(libdir, "/usr", 4) && - strncmp(libdir, "/lib", 4)) { + if (!getenv("AFL_LLVM_NO_RPATH")) { + // in case LLVM is installed not via a package manager or "make install" + // e.g. compiled download or compiled from github then its ./lib directory + // might not be in the search path. Add it if so. + u8 *libdir = strdup(LLVM_LIBDIR); + if (plusplus_mode && strlen(libdir) && strncmp(libdir, "/usr", 4) && + strncmp(libdir, "/lib", 4)) { - cc_params[cc_par_cnt++] = "-Wl,-rpath"; - cc_params[cc_par_cnt++] = libdir; + cc_params[cc_par_cnt++] = "-Wl,-rpath"; + cc_params[cc_par_cnt++] = libdir; - } else { + } else { - free(libdir); + free(libdir); + + } } @@ -2289,7 +2292,9 @@ int main(int argc, char **argv, char **envp) { " AFL_LLVM_CTX: use full context sensitive coverage (for " "CLASSIC)\n" " AFL_LLVM_NGRAM_SIZE: use ngram prev_loc count coverage (for " - "CLASSIC)\n"); + "CLASSIC)\n" + " AFL_LLVM_NO_RPATH: disable rpath setting for custom LLVM " + "locations\n"); #ifdef AFL_CLANG_FLTO if (have_lto) -- cgit v1.2.3 From f7fab7915550196366e47204d882886671d5bbf9 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 24 Oct 2023 11:52:02 +0200 Subject: code format --- src/afl-cc.c | 1 + src/afl-fuzz-bitmap.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 5f8f278f..c3c677b4 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1145,6 +1145,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (!have_pic) { cc_params[cc_par_cnt++] = "-fPIC"; } if (!getenv("AFL_LLVM_NO_RPATH")) { + // in case LLVM is installed not via a package manager or "make install" // e.g. compiled download or compiled from github then its ./lib directory // might not be in the search path. Add it if so. diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index d76158ce..568c5274 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -866,7 +866,8 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", fn_log); } u32 nyx_aux_string_len = afl->fsrv.nyx_handlers->nyx_get_aux_string( - afl->fsrv.nyx_runner, afl->fsrv.nyx_aux_string, afl->fsrv.nyx_aux_string_len); + afl->fsrv.nyx_runner, afl->fsrv.nyx_aux_string, + afl->fsrv.nyx_aux_string_len); ck_write(fd, afl->fsrv.nyx_aux_string, nyx_aux_string_len, fn_log); close(fd); -- cgit v1.2.3 From 7210a1c35972244325ceb0d4e357a78de2afb757 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 25 Oct 2023 10:58:05 +0200 Subject: fix scale --- src/afl-fuzz-redqueen.c | 126 +++++++++++++++++++++++------------------------- 1 file changed, 59 insertions(+), 67 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index b6c54df2..43b5c8bd 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -1293,27 +1293,30 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, } // If 'S' is set for cmplog mode then we try a scale encoding of the value. - // Currently we can only handle bytes up to 1 << 55 + // Currently we can only handle bytes up to 1 << 55 on 32 bit and 1 << 119 + // on 64 bit systems. + // Caveat: This implementation here works only on little endian systems. - if (attr < IS_FP && attr < 32 && (afl->cmplog_enable_scale || lvl >= LVL3)) { + if (attr < IS_FP && (afl->cmplog_enable_scale || lvl >= LVL3) && + repl == changed_val) { u8 do_call = 1; u64 new_val = repl << 2; - u32 saved_hshape = hshape; + u32 ilen = 0; if (changed_val <= 255) { - // nothing + ilen = 1; } else if (new_val <= 65535) { new_val += 1; // two byte mode - hshape = 2; + ilen = 2; } else if (new_val <= 4294967295) { new_val += 2; // four byte mode - hshape = 4; + ilen = 4; } else { @@ -1341,7 +1344,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, }; new_val += (scale_len << 2) + 3; - hshape = 8; + ilen = scale_len + 5; } else { @@ -1352,7 +1355,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, #else { - u128 new_val = ((u128)repl) << 8; + u128 new_vall = ((u128)repl) << 8; u8 scale_len = 0; u128 tmp_val = (u128)repl; @@ -1373,18 +1376,22 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, }; - new_val += (scale_len << 2) + 3; - hshape = scale_len + 5; + new_vall += (scale_len << 2) + 3; + ilen = scale_len + 5; - if (unlikely(cmp_extend_encodingN(afl, h, (u128)pattern, new_val, - (u128)o_pattern, (u128)changed_val, - 32, idx, taint_len, orig_buf, buf, - cbuf, len, 1, lvl, status))) { + if (ilen <= its_len) { - hshape = saved_hshape; - return 1; + u8 tmpbuf[32]; + memcpy(tmpbuf, buf + idx, ilen); + memcpy(buf + idx, (char *)&new_vall, ilen); - } + if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } + #ifdef CMPLOG_COMBINE + if (*status == 1) { memcpy(cbuf + idx, (char *)&new_vall, ilen); } + #endif + memcpy(buf + idx, tmpbuf, ilen); + + }; do_call = 0; @@ -1396,18 +1403,21 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, if (do_call) { - if (unlikely(cmp_extend_encoding( - afl, h, pattern, new_val, o_pattern, changed_val, 32, idx, - taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) { + if (ilen <= its_len) { - hshape = saved_hshape; - return 1; + u8 tmpbuf[32]; + memcpy(tmpbuf, buf + idx, ilen); + memcpy(buf + idx, (char *)&new_val, ilen); - } + if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } +#ifdef CMPLOG_COMBINE + if (*status == 1) { memcpy(cbuf + idx, (char *)&new_val, ilen); } +#endif + memcpy(buf + idx, tmpbuf, ilen); - } + }; - hshape = saved_hshape; + } } @@ -1677,57 +1687,33 @@ static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h, } + // Scale encoding only works on little endian systems + if (attr < IS_FP && attr < 32 && (afl->cmplog_enable_scale || lvl >= LVL3)) { u128 new_val = repl << 2; u128 max_scale = (u128)1 << 120; - u32 saved_hshape = hshape; + u32 ilen = 0; + u8 do_call = 1; if (new_val <= 255) { - hshape = 1; - if (unlikely(cmp_extend_encoding(afl, h, (u64)pattern, new_val, - (u64)o_pattern, (u64)changed_val, 32, - idx, taint_len, orig_buf, buf, cbuf, - len, 1, lvl, status))) { - - hshape = saved_hshape; - return 1; - - } + ilen = 1; } else if (new_val <= 65535) { new_val += 1; // two byte mode - hshape = 2; - if (unlikely(cmp_extend_encoding(afl, h, (u64)pattern, new_val, - (u64)o_pattern, (u64)changed_val, 32, - idx, taint_len, orig_buf, buf, cbuf, - len, 1, lvl, status))) { - - hshape = saved_hshape; - return 1; - - } + ilen = 2; } else if (new_val <= 4294967295) { new_val += 2; // four byte mode - hshape = 4; - if (unlikely(cmp_extend_encoding(afl, h, (u64)pattern, new_val, - (u64)o_pattern, (u64)changed_val, 32, - idx, taint_len, orig_buf, buf, cbuf, - len, 1, lvl, status))) { - - hshape = saved_hshape; - return 1; - - } + ilen = 4; } else if (repl < max_scale) { - u128 new_val = (u128)repl << 8; + new_val = (u128)repl << 8; u8 scale_len = 0; u128 tmp_val = (u128)repl; while (tmp_val) { @@ -1748,21 +1734,27 @@ static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h, }; new_val += (scale_len << 2) + 3; - hshape = scale_len + 5; - - if (unlikely(cmp_extend_encodingN(afl, h, (u128)pattern, new_val, - (u128)o_pattern, (u128)changed_val, - 32, idx, taint_len, orig_buf, buf, - cbuf, len, 1, lvl, status))) { + ilen = scale_len + 5; - hshape = saved_hshape; - return 1; + } else { - } + do_call = 0; } - hshape = saved_hshape; + if (do_call && ilen <= its_len) { + + u8 tmpbuf[32]; + memcpy(tmpbuf, buf + idx, ilen); + memcpy(buf + idx, (char *)&new_val, ilen); + + if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } + #ifdef CMPLOG_COMBINE + if (*status == 1) { memcpy(cbuf + idx, (char *)&new_val, ilen); } + #endif + memcpy(buf + idx, tmpbuf, ilen); + + }; } -- cgit v1.2.3 From 2230f88887e3e8d1793fdb98f9cd12d3449ba791 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 3 Nov 2023 11:19:14 +0100 Subject: add --help/--version/... --- src/afl-fuzz.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 2538f4a4..6a8a6aae 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -486,6 +486,22 @@ int main(int argc, char **argv_orig, char **envp) { struct timeval tv; struct timezone tz; + doc_path = access(DOC_PATH, F_OK) != 0 ? (u8 *)"docs" : (u8 *)DOC_PATH; + + if (argc > 1 && strcmp(argv_orig[1], "--version") == 0) { + + printf("afl-fuzz" VERSION "\n"); + exit(0); + + } + + if (argc > 1 && strcmp(argv_orig[1], "--help") == 0) { + + usage(argv_orig[0], 1); + exit(0); + + } + #if defined USE_COLOR && defined ALWAYS_COLORED if (getenv("AFL_NO_COLOR") || getenv("AFL_NO_COLOUR")) { @@ -515,8 +531,6 @@ int main(int argc, char **argv_orig, char **envp) { SAYF(cCYA "afl-fuzz" VERSION cRST " based on afl by Michal Zalewski and a large online community\n"); - doc_path = access(DOC_PATH, F_OK) != 0 ? (u8 *)"docs" : (u8 *)DOC_PATH; - gettimeofday(&tv, &tz); rand_set_seed(afl, tv.tv_sec ^ tv.tv_usec ^ getpid()); -- cgit v1.2.3 From 8338844284a2a1f340d859e7b0871878537a0729 Mon Sep 17 00:00:00 2001 From: hexcoder Date: Sat, 4 Nov 2023 22:01:09 +0100 Subject: copy 'detect_leaks=0' from ASAN to LSAN fix for issue #1733, set "detect_leaks=0" when ASAN_OPTIONS contains it and LSAN_OPTIONS are not set. --- src/afl-common.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-common.c b/src/afl-common.c index b4143a1b..9ba7116d 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -103,7 +103,12 @@ void set_sanitizer_defaults() { u8 buf[2048] = ""; if (!have_san_options) { strcpy(buf, default_options); } - strcat(buf, "exitcode=" STRINGIFY(LSAN_ERROR) ":fast_unwind_on_malloc=0:print_suppressions=0:detect_leaks=1:malloc_context_size=30:"); + if (have_san_options && NULL != strstr(have_asan_options, "detect_leaks=0")) { + strcat(buf, "exitcode=" STRINGIFY(LSAN_ERROR) ":fast_unwind_on_malloc=0:print_suppressions=0:detect_leaks=0:malloc_context_size=30:"); + } else { + strcat(buf, "exitcode=" STRINGIFY(LSAN_ERROR) ":fast_unwind_on_malloc=0:print_suppressions=0:detect_leaks=1:malloc_context_size=30:"); + } + setenv("LSAN_OPTIONS", buf, 1); } -- cgit v1.2.3 From 6ed3f4cfac52d2bef60321bccb236c7c5d215404 Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Sat, 4 Nov 2023 22:48:27 +0100 Subject: fix of fix: make sure ASAN_OPTIONS and LSAN_OPTIONS agree on leak detection --- src/afl-common.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/afl-common.c b/src/afl-common.c index 9ba7116d..65932e26 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -98,14 +98,16 @@ void set_sanitizer_defaults() { } /* LSAN does not support abort_on_error=1. (is this still true??) */ + u8 should_detect_leaks = 0; if (!have_lsan_options) { u8 buf[2048] = ""; if (!have_san_options) { strcpy(buf, default_options); } - if (have_san_options && NULL != strstr(have_asan_options, "detect_leaks=0")) { - strcat(buf, "exitcode=" STRINGIFY(LSAN_ERROR) ":fast_unwind_on_malloc=0:print_suppressions=0:detect_leaks=0:malloc_context_size=30:"); + if (have_asan_options && NULL != strstr(have_asan_options, "detect_leaks=0")) { + strcat(buf, "exitcode=" STRINGIFY(LSAN_ERROR) ":fast_unwind_on_malloc=0:print_suppressions=0:detect_leaks=0:malloc_context_size=0:"); } else { + should_detect_leaks = 1; strcat(buf, "exitcode=" STRINGIFY(LSAN_ERROR) ":fast_unwind_on_malloc=0:print_suppressions=0:detect_leaks=1:malloc_context_size=30:"); } @@ -117,7 +119,11 @@ void set_sanitizer_defaults() { if (!have_lsan_options) { - strcat(default_options, "detect_leaks=0:malloc_context_size=0:"); + if (should_detect_leaks) { + strcat(default_options, "detect_leaks=1:malloc_context_size=30:"); + } else { + strcat(default_options, "detect_leaks=0:malloc_context_size=0:"); + } } -- cgit v1.2.3 From 053334f35d0e8d6eace444781d52504585c69f76 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 6 Nov 2023 10:02:53 +0100 Subject: fix lsan fix --- src/afl-common.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/afl-common.c b/src/afl-common.c index 65932e26..ba498b3b 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -104,11 +104,19 @@ void set_sanitizer_defaults() { u8 buf[2048] = ""; if (!have_san_options) { strcpy(buf, default_options); } - if (have_asan_options && NULL != strstr(have_asan_options, "detect_leaks=0")) { - strcat(buf, "exitcode=" STRINGIFY(LSAN_ERROR) ":fast_unwind_on_malloc=0:print_suppressions=0:detect_leaks=0:malloc_context_size=0:"); - } else { - should_detect_leaks = 1; - strcat(buf, "exitcode=" STRINGIFY(LSAN_ERROR) ":fast_unwind_on_malloc=0:print_suppressions=0:detect_leaks=1:malloc_context_size=30:"); + if (have_asan_options) { + + if (NULL != strstr(have_asan_options, "detect_leaks=0")) { + + strcat(buf, "exitcode=" STRINGIFY(LSAN_ERROR) ":fast_unwind_on_malloc=0:print_suppressions=0:detect_leaks=0:malloc_context_size=0:"); + + } else { + + should_detect_leaks = 1; + strcat(buf, "exitcode=" STRINGIFY(LSAN_ERROR) ":fast_unwind_on_malloc=0:print_suppressions=0:detect_leaks=1:malloc_context_size=30:"); + + } + } setenv("LSAN_OPTIONS", buf, 1); @@ -120,9 +128,13 @@ void set_sanitizer_defaults() { if (!have_lsan_options) { if (should_detect_leaks) { + strcat(default_options, "detect_leaks=1:malloc_context_size=30:"); + } else { + strcat(default_options, "detect_leaks=0:malloc_context_size=0:"); + } } -- cgit v1.2.3 From f3d2127fd815bed2ec9dfab981123898d11cea65 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 6 Nov 2023 10:13:59 +0100 Subject: clang-format 16->17 --- src/afl-fuzz-one.c | 30 +++++++++++++++--------------- src/afl-fuzz-redqueen.c | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 2003be1f..b2306996 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -577,13 +577,13 @@ u8 fuzz_one_original(afl_state_t *afl) { * SIMPLE BITFLIP (+dictionary construction) * *********************************************/ -#define FLIP_BIT(_ar, _b) \ - do { \ - \ - u8 *_arf = (u8 *)(_ar); \ - u32 _bf = (_b); \ - _arf[(_bf) >> 3] ^= (128 >> ((_bf)&7)); \ - \ +#define FLIP_BIT(_ar, _b) \ + do { \ + \ + u8 *_arf = (u8 *)(_ar); \ + u32 _bf = (_b); \ + _arf[(_bf) >> 3] ^= (128 >> ((_bf) & 7)); \ + \ } while (0) /* Single walking bit. */ @@ -2216,7 +2216,7 @@ havoc_stage: } - retry_havoc_step : { + retry_havoc_step: { u32 r = rand_below(afl, rand_max), item; @@ -3703,13 +3703,13 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { * SIMPLE BITFLIP (+dictionary construction) * *********************************************/ -#define FLIP_BIT(_ar, _b) \ - do { \ - \ - u8 *_arf = (u8 *)(_ar); \ - u32 _bf = (_b); \ - _arf[(_bf) >> 3] ^= (128 >> ((_bf)&7)); \ - \ +#define FLIP_BIT(_ar, _b) \ + do { \ + \ + u8 *_arf = (u8 *)(_ar); \ + u32 _bf = (_b); \ + _arf[(_bf) >> 3] ^= (128 >> ((_bf) & 7)); \ + \ } while (0) /* Single walking bit. */ diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 43b5c8bd..86e7f1cf 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -1828,7 +1828,7 @@ static void try_to_add_to_dictN(afl_state_t *afl, u128 v, u8 size) { for (k = 0; k < size; ++k) { #else - u32 off = 16 - size; + u32 off = 16 - size; for (k = 16 - size; k < 16; ++k) { #endif -- cgit v1.2.3 From 8ad36af95d9bcfa172d217f0f8ca29c6b24ba78a Mon Sep 17 00:00:00 2001 From: Manuel Carrasco Date: Mon, 6 Nov 2023 17:50:15 +0000 Subject: Add missing initialisation for havoc_queued during the custom mutator's stage. --- src/afl-fuzz-one.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index b2306996..67dafda8 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -1894,6 +1894,7 @@ custom_mutator_stage: LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { if (el->afl_custom_fuzz) { + havoc_queued = afl->queued_items; afl->current_custom_fuzz = el; afl->stage_name = el->name_short; -- cgit v1.2.3 From ac0ad563480e3bf1fb69349e960b7957fffe75df Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 7 Nov 2023 10:31:09 +0100 Subject: fix dictionary and cmin --- src/afl-fuzz-extras.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c index f6de11ae..905431d1 100644 --- a/src/afl-fuzz-extras.c +++ b/src/afl-fuzz-extras.c @@ -176,6 +176,8 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len, afl->extras = afl_realloc((void **)&afl->extras, (afl->extras_cnt + 1) * sizeof(struct extra_data)); + char *hexdigits = "0123456789abcdef"; + if (unlikely(!afl->extras)) { PFATAL("alloc"); } wptr = afl->extras[afl->extras_cnt].data = ck_alloc(rptr - lptr); @@ -184,13 +186,12 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len, while (*lptr) { - char *hexdigits = "0123456789abcdef"; - switch (*lptr) { case 1 ... 31: case 128 ... 255: WARNF("Non-printable characters in line %u.", cur_line); + ++lptr; continue; break; -- cgit v1.2.3 From a0714309834e9aecb348608a2c5da5b726868b82 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 16 Nov 2023 11:00:33 +0100 Subject: fix inf in stats --- src/afl-fuzz-stats.c | 59 +++++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 66e32e78..07184cf0 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -138,7 +138,7 @@ void load_stats_file(afl_state_t *afl) { FILE *f; u8 buf[MAX_LINE]; - u8 *lptr; + u8 * lptr; u8 fn[PATH_MAX]; u32 lineno = 0; snprintf(fn, PATH_MAX, "%s/fuzzer_stats", afl->out_dir); @@ -288,6 +288,8 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, #ifndef __HAIKU__ if (getrusage(RUSAGE_CHILDREN, &rus)) { rus.ru_maxrss = 0; } #endif + u64 runtime = afl->prev_run_time + cur_time - afl->start_time; + if (!runtime) { runtime = 1; } fprintf( f, @@ -336,17 +338,14 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, "target_mode : %s%s%s%s%s%s%s%s%s%s\n" "command_line : %s\n", (afl->start_time - afl->prev_run_time) / 1000, cur_time / 1000, - (afl->prev_run_time + cur_time - afl->start_time) / 1000, (u32)getpid(), + runtime / 1000, (u32)getpid(), afl->queue_cycle ? (afl->queue_cycle - 1) : 0, afl->cycles_wo_finds, afl->longest_find_time > cur_time - afl->last_find_time ? afl->longest_find_time / 1000 : ((afl->start_time == 0 || afl->last_find_time == 0) ? 0 : (cur_time - afl->last_find_time) / 1000), - afl->fsrv.total_execs, - afl->fsrv.total_execs / - ((double)(afl->prev_run_time + get_cur_time() - afl->start_time) / - 1000), + afl->fsrv.total_execs, afl->fsrv.total_execs / ((double)(runtime) / 1000), afl->last_avg_execs_saved, afl->queued_items, afl->queued_favored, afl->queued_discovered, afl->queued_imported, afl->queued_variable, afl->max_depth, afl->current_entry, afl->pending_favored, @@ -422,7 +421,7 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, void write_queue_stats(afl_state_t *afl) { FILE *f; - u8 *fn = alloc_printf("%s/queue_data", afl->out_dir); + u8 * fn = alloc_printf("%s/queue_data", afl->out_dir); if ((f = fopen(fn, "w")) != NULL) { u32 id; @@ -858,9 +857,8 @@ void show_stats_normal(afl_state_t *afl) { /* Since `total_crashes` does not get reloaded from disk on restart, it indicates if we found crashes this round already -> paint red. If it's 0, but `saved_crashes` is set from a past run, paint in yellow. */ - char *crash_color = afl->total_crashes ? cLRD - : afl->saved_crashes ? cYEL - : cRST; + char *crash_color = + afl->total_crashes ? cLRD : afl->saved_crashes ? cYEL : cRST; /* Lord, forgive me this. */ @@ -883,26 +881,26 @@ void show_stats_normal(afl_state_t *afl) { } else - /* Subsequent cycles, but we're still making finds. */ - if (afl->cycles_wo_finds < 25 || min_wo_finds < 30) { + /* Subsequent cycles, but we're still making finds. */ + if (afl->cycles_wo_finds < 25 || min_wo_finds < 30) { - strcpy(tmp, cYEL); + strcpy(tmp, cYEL); - } else + } else /* No finds for a long time and no test cases to try. */ if (afl->cycles_wo_finds > 100 && !afl->pending_not_fuzzed && min_wo_finds > 120) { - strcpy(tmp, cLGN); + strcpy(tmp, cLGN); - /* Default: cautiously OK to stop? */ + /* Default: cautiously OK to stop? */ - } else { + } else { - strcpy(tmp, cLBL); + strcpy(tmp, cLBL); - } + } } @@ -1668,9 +1666,8 @@ void show_stats_pizza(afl_state_t *afl) { /* Since `total_crashes` does not get reloaded from disk on restart, it indicates if we found crashes this round already -> paint red. If it's 0, but `saved_crashes` is set from a past run, paint in yellow. */ - char *crash_color = afl->total_crashes ? cLRD - : afl->saved_crashes ? cYEL - : cRST; + char *crash_color = + afl->total_crashes ? cLRD : afl->saved_crashes ? cYEL : cRST; /* Lord, forgive me this. */ @@ -1693,26 +1690,26 @@ void show_stats_pizza(afl_state_t *afl) { } else - /* Subsequent cycles, but we're still making finds. */ - if (afl->cycles_wo_finds < 25 || min_wo_finds < 30) { + /* Subsequent cycles, but we're still making finds. */ + if (afl->cycles_wo_finds < 25 || min_wo_finds < 30) { - strcpy(tmp, cYEL); + strcpy(tmp, cYEL); - } else + } else /* No finds for a long time and no test cases to try. */ if (afl->cycles_wo_finds > 100 && !afl->pending_not_fuzzed && min_wo_finds > 120) { - strcpy(tmp, cLGN); + strcpy(tmp, cLGN); - /* Default: cautiously OK to stop? */ + /* Default: cautiously OK to stop? */ - } else { + } else { - strcpy(tmp, cLBL); + strcpy(tmp, cLBL); - } + } } -- cgit v1.2.3 From b05e3f7ac019224884af9f35d3cfdb72a604d02d Mon Sep 17 00:00:00 2001 From: ifyGecko <26214995+ifyGecko@users.noreply.github.com> Date: Thu, 16 Nov 2023 19:02:46 -0500 Subject: missing closing parenthesis --- src/afl-fuzz-redqueen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 86e7f1cf..13f164f5 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -1321,7 +1321,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, } else { #ifndef WORD_SIZE_64 - if (repl <= 0x00ffffffffffffff { + if (repl <= 0x00ffffffffffffff) { new_val = repl << 8; u8 scale_len = 0; -- cgit v1.2.3 From a2a4171039a2cdef0204ff673f888177dec04560 Mon Sep 17 00:00:00 2001 From: "Christian Holler (:decoder)" Date: Wed, 22 Nov 2023 15:08:26 +0100 Subject: Pass correct Nyx ID when creating a Nyx runner --- src/afl-forkserver.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 9b710733..3f9bfa72 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -679,8 +679,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } - fsrv->nyx_runner = - fsrv->nyx_handlers->nyx_new(nyx_config, fsrv->nyx_bind_cpu_id); + fsrv->nyx_runner = fsrv->nyx_handlers->nyx_new(nyx_config, fsrv->nyx_id); ck_free(workdir_path); ck_free(outdir_path_absolute); -- cgit v1.2.3 From c96aa400e4cf4e85d234375f47028a926babe4c0 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 23 Nov 2023 21:28:44 +0100 Subject: mini fix --- src/afl-fuzz-stats.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 07184cf0..f212a4b8 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -1058,7 +1058,7 @@ void show_stats_normal(afl_state_t *afl) { sprintf(tmp, "%s (%s%s saved)", u_stringify_int(IB(0), afl->total_tmouts), u_stringify_int(IB(1), afl->saved_tmouts), - (afl->saved_hangs >= KEEP_UNIQUE_HANG) ? "+" : ""); + (afl->saved_tmouts >= KEEP_UNIQUE_HANG) ? "+" : ""); SAYF(bSTG bV bSTOP " total tmouts : " cRST "%-20s" bSTG bV "\n", tmp); @@ -1889,7 +1889,7 @@ void show_stats_pizza(afl_state_t *afl) { sprintf(tmp, "%s (%s%s saved)", u_stringify_int(IB(0), afl->total_tmouts), u_stringify_int(IB(1), afl->saved_tmouts), - (afl->saved_hangs >= KEEP_UNIQUE_HANG) ? "+" : ""); + (afl->saved_tmouts >= KEEP_UNIQUE_HANG) ? "+" : ""); SAYF(bSTG bV bSTOP " burned pizzas : " cRST "%-20s" bSTG bV "\n", -- cgit v1.2.3 From 770e868d04c0f52a1c57e5471e459dd24a002748 Mon Sep 17 00:00:00 2001 From: yangzao Date: Fri, 24 Nov 2023 11:06:06 -0700 Subject: add custom_post_run.c --- src/afl-fuzz-mutators.c | 12 ++++++++++++ src/afl-fuzz-run.c | 2 ++ 2 files changed, 14 insertions(+) (limited to 'src') diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index 64dbe7c6..17fb9368 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -397,6 +397,18 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) { } + /* "afl_custom_post_run", optional */ + mutator->afl_custom_post_run = dlsym(dh, "afl_custom_post_run"); + if (!mutator->afl_custom_post_run) { + + ACTF("optional symbol 'afl_custom_post_run' not found."); + + } else { + + OKF("Found 'afl_custom_post_run'."); + + } + /* "afl_custom_queue_new_entry", optional */ mutator->afl_custom_queue_new_entry = dlsym(dh, "afl_custom_queue_new_entry"); if (!mutator->afl_custom_queue_new_entry) { diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index ac4fb4a9..29cc5352 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -60,6 +60,8 @@ fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 timeout) { fsrv_run_result_t res = afl_fsrv_run_target(fsrv, timeout, &afl->stop_soon); + + #ifdef PROFILING clock_gettime(CLOCK_REALTIME, &spec); time_spent_start = (spec.tv_sec * 1000000000) + spec.tv_nsec; -- cgit v1.2.3 From 8af74bcaeebbe2407006333024d8803baacdb4e2 Mon Sep 17 00:00:00 2001 From: yangzao Date: Fri, 24 Nov 2023 22:47:50 -0700 Subject: update afl-fuzz-run --- src/afl-fuzz-run.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 29cc5352..ac346b86 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -60,7 +60,7 @@ fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 timeout) { fsrv_run_result_t res = afl_fsrv_run_target(fsrv, timeout, &afl->stop_soon); - + post_run(afl); #ifdef PROFILING clock_gettime(CLOCK_REALTIME, &spec); @@ -1113,3 +1113,20 @@ common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { } +/* Run some code each time scripts each time AFL++ executes the target + with afl-fuzz. */ + +void post_run(afl_state_t *afl) { + if (unlikely(afl->custom_mutators_count)) { + + LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { + + if (el->afl_custom_post_run) { + + el->afl_custom_post_run(el->data); + + } + + }); + } +} \ No newline at end of file -- cgit v1.2.3 From faedb3fb29186c29a4f0cf28daa5d07350ed8094 Mon Sep 17 00:00:00 2001 From: yangzao Date: Sat, 25 Nov 2023 21:18:32 -0700 Subject: update python module --- src/afl-fuzz-python.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'src') diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c index 7dad0770..1b287405 100644 --- a/src/afl-fuzz-python.c +++ b/src/afl-fuzz-python.c @@ -249,6 +249,8 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) { PyObject_GetAttrString(py_module, "queue_get"); py_functions[PY_FUNC_FUZZ_SEND] = PyObject_GetAttrString(py_module, "fuzz_send"); + py_functions[PY_FUNC_POST_RUN] = + PyObject_GetAttrString(py_module, "post_run"); py_functions[PY_FUNC_SPLICE_OPTOUT] = PyObject_GetAttrString(py_module, "splice_optout"); if (py_functions[PY_FUNC_SPLICE_OPTOUT]) { afl->custom_splice_optout = 1; } @@ -468,6 +470,12 @@ struct custom_mutator *load_custom_mutator_py(afl_state_t *afl, } + if (py_functions[PY_FUNC_POST_RUN]) { + + mutator->afl_custom_post_run = post_run_py; + + } + if (py_functions[PY_FUNC_SPLICE_OPTOUT]) { mutator->afl_custom_splice_optout = splice_optout_py; @@ -925,6 +933,30 @@ void fuzz_send_py(void *py_mutator, const u8 *buf, size_t buf_size) { } +void post_run_py(void *py_mutator) { + + PyObject *py_args, *py_value; + + py_args = PyTuple_New(0); + py_value = PyObject_CallObject( + ((py_mutator_t *)py_mutator) + ->py_functions[PY_FUNC_POST_RUN], + py_args); + Py_DECREF(py_args); + + if (py_value != NULL) { + + Py_DECREF(py_value); + + } else { + + PyErr_Print(); + FATAL("Call failed"); + + } + +} + u8 queue_new_entry_py(void *py_mutator, const u8 *filename_new_queue, const u8 *filename_orig_queue) { -- cgit v1.2.3 From c9e0f01b439870dc2b619ab2c18240b201ca1460 Mon Sep 17 00:00:00 2001 From: yangzao Date: Mon, 27 Nov 2023 09:58:03 -0700 Subject: format code --- src/afl-fuzz-one.c | 1 + src/afl-fuzz-python.c | 4 +--- src/afl-fuzz-run.c | 13 ++++++------- src/afl-fuzz-stats.c | 50 ++++++++++++++++++++++++++------------------------ 4 files changed, 34 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 67dafda8..01e34b69 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -1894,6 +1894,7 @@ custom_mutator_stage: LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { if (el->afl_custom_fuzz) { + havoc_queued = afl->queued_items; afl->current_custom_fuzz = el; diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c index 1b287405..4c7da774 100644 --- a/src/afl-fuzz-python.c +++ b/src/afl-fuzz-python.c @@ -939,9 +939,7 @@ void post_run_py(void *py_mutator) { py_args = PyTuple_New(0); py_value = PyObject_CallObject( - ((py_mutator_t *)py_mutator) - ->py_functions[PY_FUNC_POST_RUN], - py_args); + ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_POST_RUN], py_args); Py_DECREF(py_args); if (py_value != NULL) { diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index ac346b86..04ccccba 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -1117,16 +1117,15 @@ common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { with afl-fuzz. */ void post_run(afl_state_t *afl) { + if (unlikely(afl->custom_mutators_count)) { - LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { + LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { - if (el->afl_custom_post_run) { + if (el->afl_custom_post_run) { el->afl_custom_post_run(el->data); } - el->afl_custom_post_run(el->data); + }); - } + } - }); - } -} \ No newline at end of file +} diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 07184cf0..d945dabf 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -138,7 +138,7 @@ void load_stats_file(afl_state_t *afl) { FILE *f; u8 buf[MAX_LINE]; - u8 * lptr; + u8 *lptr; u8 fn[PATH_MAX]; u32 lineno = 0; snprintf(fn, PATH_MAX, "%s/fuzzer_stats", afl->out_dir); @@ -421,7 +421,7 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, void write_queue_stats(afl_state_t *afl) { FILE *f; - u8 * fn = alloc_printf("%s/queue_data", afl->out_dir); + u8 *fn = alloc_printf("%s/queue_data", afl->out_dir); if ((f = fopen(fn, "w")) != NULL) { u32 id; @@ -857,8 +857,9 @@ void show_stats_normal(afl_state_t *afl) { /* Since `total_crashes` does not get reloaded from disk on restart, it indicates if we found crashes this round already -> paint red. If it's 0, but `saved_crashes` is set from a past run, paint in yellow. */ - char *crash_color = - afl->total_crashes ? cLRD : afl->saved_crashes ? cYEL : cRST; + char *crash_color = afl->total_crashes ? cLRD + : afl->saved_crashes ? cYEL + : cRST; /* Lord, forgive me this. */ @@ -881,26 +882,26 @@ void show_stats_normal(afl_state_t *afl) { } else - /* Subsequent cycles, but we're still making finds. */ - if (afl->cycles_wo_finds < 25 || min_wo_finds < 30) { + /* Subsequent cycles, but we're still making finds. */ + if (afl->cycles_wo_finds < 25 || min_wo_finds < 30) { - strcpy(tmp, cYEL); + strcpy(tmp, cYEL); - } else + } else /* No finds for a long time and no test cases to try. */ if (afl->cycles_wo_finds > 100 && !afl->pending_not_fuzzed && min_wo_finds > 120) { - strcpy(tmp, cLGN); + strcpy(tmp, cLGN); - /* Default: cautiously OK to stop? */ + /* Default: cautiously OK to stop? */ - } else { + } else { - strcpy(tmp, cLBL); + strcpy(tmp, cLBL); - } + } } @@ -1666,8 +1667,9 @@ void show_stats_pizza(afl_state_t *afl) { /* Since `total_crashes` does not get reloaded from disk on restart, it indicates if we found crashes this round already -> paint red. If it's 0, but `saved_crashes` is set from a past run, paint in yellow. */ - char *crash_color = - afl->total_crashes ? cLRD : afl->saved_crashes ? cYEL : cRST; + char *crash_color = afl->total_crashes ? cLRD + : afl->saved_crashes ? cYEL + : cRST; /* Lord, forgive me this. */ @@ -1690,26 +1692,26 @@ void show_stats_pizza(afl_state_t *afl) { } else - /* Subsequent cycles, but we're still making finds. */ - if (afl->cycles_wo_finds < 25 || min_wo_finds < 30) { + /* Subsequent cycles, but we're still making finds. */ + if (afl->cycles_wo_finds < 25 || min_wo_finds < 30) { - strcpy(tmp, cYEL); + strcpy(tmp, cYEL); - } else + } else /* No finds for a long time and no test cases to try. */ if (afl->cycles_wo_finds > 100 && !afl->pending_not_fuzzed && min_wo_finds > 120) { - strcpy(tmp, cLGN); + strcpy(tmp, cLGN); - /* Default: cautiously OK to stop? */ + /* Default: cautiously OK to stop? */ - } else { + } else { - strcpy(tmp, cLBL); + strcpy(tmp, cLBL); - } + } } -- cgit v1.2.3 From bb523b46482ce212355b32882158cb129d2e8487 Mon Sep 17 00:00:00 2001 From: yangzao Date: Mon, 27 Nov 2023 09:59:02 -0700 Subject: update --- src/afl-fuzz-run.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 04ccccba..8d0f2c2d 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -1113,7 +1113,7 @@ common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { } -/* Run some code each time scripts each time AFL++ executes the target +/* Run some code or scripts each time AFL++ executes the target program with afl-fuzz. */ void post_run(afl_state_t *afl) { -- cgit v1.2.3 From 81b43cefdfa99b14628c487dc0183a4c1a21c811 Mon Sep 17 00:00:00 2001 From: yangzao Date: Mon, 27 Nov 2023 10:25:12 -0700 Subject: merge function --- src/afl-fuzz-run.c | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 8d0f2c2d..ae7969a6 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -60,7 +60,18 @@ fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 timeout) { fsrv_run_result_t res = afl_fsrv_run_target(fsrv, timeout, &afl->stop_soon); - post_run(afl); + /* If post_run() function is defined in custom mutator, the function will be + called each time after AFL++ executes the target program. */ + + if (unlikely(afl->custom_mutators_count)) { + + LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { + + if (el->afl_custom_post_run) { el->afl_custom_post_run(el->data); } + + }); + + } #ifdef PROFILING clock_gettime(CLOCK_REALTIME, &spec); @@ -1112,20 +1123,3 @@ common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { return 0; } - -/* Run some code or scripts each time AFL++ executes the target program - with afl-fuzz. */ - -void post_run(afl_state_t *afl) { - - if (unlikely(afl->custom_mutators_count)) { - - LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { - - if (el->afl_custom_post_run) { el->afl_custom_post_run(el->data); } - - }); - - } - -} -- cgit v1.2.3 From d2aef74ad77e49a96f152517445a515ba4814bcb Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 22 Nov 2023 14:56:57 +0100 Subject: changes --- src/afl-fuzz-run.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index ae7969a6..b6d5df95 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -931,7 +931,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { detected, it will still work to some extent, so we don't check for this. */ - if (q->len < 5) { return 0; } + if (unlikely(q->len < 5)) { return 0; } afl->stage_name = afl->stage_name_buf; afl->bytes_trim_in += q->len; -- cgit v1.2.3 From dd9a04c901c79fe2f3f078de6cc0777e3a5d96df Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 28 Nov 2023 09:14:29 +0100 Subject: code format --- src/afl-fuzz-run.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index b6d5df95..34a5ff81 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -62,12 +62,16 @@ fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 timeout) { /* If post_run() function is defined in custom mutator, the function will be called each time after AFL++ executes the target program. */ - + if (unlikely(afl->custom_mutators_count)) { LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { - if (el->afl_custom_post_run) { el->afl_custom_post_run(el->data); } + if (unlikely(el->afl_custom_post_run)) { + + el->afl_custom_post_run(el->data); + + } }); @@ -1123,3 +1127,4 @@ common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { return 0; } + -- cgit v1.2.3 From 74f8ca6b468b6d89e8d588e3835486be48184893 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 28 Nov 2023 10:26:37 +0100 Subject: improve cmplog --- src/afl-fuzz-redqueen.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 13f164f5..c0ea5005 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -1906,6 +1906,8 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, #endif + if (hshape < 2) { return 0; } + for (i = 0; i < loggeds; ++i) { struct cmp_operands *o = &afl->shm.cmp_map->log[key][i]; @@ -2698,6 +2700,8 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, hshape = SHAPE_BYTES(h->shape); + if (hshape < 2) { return 0; } + if (h->hits > CMP_MAP_RTN_H) { loggeds = CMP_MAP_RTN_H; -- cgit v1.2.3 From 39be50e2a80443224cc781e4630714df977f52c0 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 28 Nov 2023 16:32:36 +0100 Subject: nit --- src/afl-fuzz-redqueen.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index c0ea5005..9e9b3822 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -1379,7 +1379,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, new_vall += (scale_len << 2) + 3; ilen = scale_len + 5; - if (ilen <= its_len) { + if (ilen <= its_len && ilen > 1) { u8 tmpbuf[32]; memcpy(tmpbuf, buf + idx, ilen); @@ -1403,7 +1403,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, if (do_call) { - if (ilen <= its_len) { + if (ilen <= its_len && ilen > 1) { u8 tmpbuf[32]; memcpy(tmpbuf, buf + idx, ilen); @@ -1421,7 +1421,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, } - // here we add and subract 1 from the value, but only if it is not an + // here we add and subtract 1 from the value, but only if it is not an // == or != comparison // Bits: 1 = Equal, 2 = Greater, 4 = Lesser, 8 = Float // 16 = modified float, 32 = modified integer (modified = wont match -- cgit v1.2.3 From 3fc9e680f3f0bcd19372941b88d8dde1e73dbdf3 Mon Sep 17 00:00:00 2001 From: Romain Geissler Date: Fri, 1 Dec 2023 16:28:33 +0000 Subject: Stop hardcoding the path /usr/local/lib/afl in afl-ld-lto.c and respect the configured PREFIX. --- src/afl-ld-lto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c index b1e6c848..7ce5de41 100644 --- a/src/afl-ld-lto.c +++ b/src/afl-ld-lto.c @@ -278,7 +278,7 @@ int main(int argc, char **argv) { if (getenv("AFL_LD_PASSTHROUGH") != NULL) passthrough = 1; if (getenv("AFL_REAL_LD") != NULL) real_ld = getenv("AFL_REAL_LD"); - if (!afl_path || !*afl_path) afl_path = "/usr/local/lib/afl"; + if (!afl_path || !*afl_path) afl_path = AFL_PATH; setenv("AFL_LD_CALLER", "1", 1); -- cgit v1.2.3 From 0e7afb75dd02efebc5518505d06667fde0467c7e Mon Sep 17 00:00:00 2001 From: vincenzo MEZZELA Date: Mon, 4 Dec 2023 16:39:10 +0100 Subject: removing options "-Wl,-rpath" "LLVM_LIBDIR" when using gcc --- src/afl-cc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index c3c677b4..6faed538 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1144,7 +1144,8 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (!have_pic) { cc_params[cc_par_cnt++] = "-fPIC"; } - if (!getenv("AFL_LLVM_NO_RPATH")) { + if (compiler_mode != GCC_PLUGIN && compiler_mode != GCC && + !getenv("AFL_LLVM_NO_RPATH")) { // in case LLVM is installed not via a package manager or "make install" // e.g. compiled download or compiled from github then its ./lib directory -- cgit v1.2.3 From 6c04d4cc80b55efee8bb005bbd616a0aaeede395 Mon Sep 17 00:00:00 2001 From: vincenzo MEZZELA Date: Mon, 4 Dec 2023 16:41:21 +0100 Subject: fixing -Wl,-rpath= --- src/afl-cc.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 6faed538..ceea61f2 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1150,16 +1150,12 @@ static void edit_params(u32 argc, char **argv, char **envp) { // in case LLVM is installed not via a package manager or "make install" // e.g. compiled download or compiled from github then its ./lib directory // might not be in the search path. Add it if so. - u8 *libdir = strdup(LLVM_LIBDIR); + const char *libdir = LLVM_LIBDIR; if (plusplus_mode && strlen(libdir) && strncmp(libdir, "/usr", 4) && strncmp(libdir, "/lib", 4)) { - cc_params[cc_par_cnt++] = "-Wl,-rpath"; - cc_params[cc_par_cnt++] = libdir; - - } else { - - free(libdir); + u8 *libdir_opt = strdup("-Wl,-rpath=" LLVM_LIBDIR); + cc_params[cc_par_cnt++] = libdir_opt; } -- cgit v1.2.3 From bb1d4a24917fd95f5389ed6f406c99811e0ed6eb Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 7 Dec 2023 16:15:18 +0100 Subject: afl-cc fixes --- src/afl-cc.c | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index ceea61f2..6242ece0 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -395,12 +395,16 @@ static void process_params(u32 argc, char **argv) { } + // reset + have_instr_list = 0; + have_c = 0; + if (lto_mode && argc > 1) { u32 idx; for (idx = 1; idx < argc; idx++) { - if (!strncasecmp(argv[idx], "-fpic", 5)) have_pic = 1; + if (!strncasecmp(argv[idx], "-fpic", 5)) { have_pic = 1; } } @@ -689,6 +693,18 @@ static void edit_params(u32 argc, char **argv, char **envp) { cc_params = ck_alloc(MAX_PARAMS_NUM * sizeof(u8 *)); + for (u32 c = 1; c < argc; ++c) { + + if (!strcmp(argv[c], "-c")) have_c = 1; + if (!strncmp(argv[c], "-fsanitize-coverage-", 20) && + strstr(argv[c], "list=")) { + + have_instr_list = 1; + + } + + } + if (lto_mode) { if (lto_flag[0] != '-') @@ -1125,24 +1141,18 @@ static void edit_params(u32 argc, char **argv, char **envp) { // cc_params[cc_par_cnt++] = "-Qunused-arguments"; - if (lto_mode && argc > 1) { - - u32 idx; - for (idx = 1; idx < argc; idx++) { - - if (!strncasecmp(argv[idx], "-fpic", 5)) have_pic = 1; - - } - - } - } /* Inspect the command line parameters. */ process_params(argc, argv); - if (!have_pic) { cc_params[cc_par_cnt++] = "-fPIC"; } + if (!have_pic) { + + cc_params[cc_par_cnt++] = "-fPIC"; + have_pic = 1; + + } if (compiler_mode != GCC_PLUGIN && compiler_mode != GCC && !getenv("AFL_LLVM_NO_RPATH")) { -- cgit v1.2.3 From 520daf5e0f8b6e7df9fa3b77b7c1b8268b0dcd0f Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 10 Dec 2023 13:23:59 +0100 Subject: nit --- src/afl-cc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 6242ece0..22cce2cd 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -2313,7 +2313,7 @@ int main(int argc, char **argv, char **envp) { "0x10000\n" " AFL_LLVM_DOCUMENT_IDS: write all edge IDs and the corresponding " "functions\n" - " into this file\n" + " into this file (LTO mode)\n" " AFL_LLVM_LTO_DONTWRITEID: don't write the highest ID used to a " "global var\n" " AFL_LLVM_LTO_STARTID: from which ID to start counting from for " -- cgit v1.2.3 From a062e84ba60a687b2a0ea390a8b7d9701e1ee27b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 10 Dec 2023 14:05:41 +0100 Subject: add n_fuzz to ignore_timeouts --- src/afl-fuzz-bitmap.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src') diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 568c5274..7c81d01a 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -459,6 +459,17 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { if (unlikely(fault == FSRV_RUN_TMOUT && afl->afl_env.afl_ignore_timeouts)) { + if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) { + + classify_counts(&afl->fsrv); + cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); + + // Saturated increment + if (likely(afl->n_fuzz[cksum % N_FUZZ_SIZE] < 0xFFFFFFFF)) + afl->n_fuzz[cksum % N_FUZZ_SIZE]++; + + } + return 0; } -- cgit v1.2.3 From b2d118f821b9a98b64a955b6dce5785646a8f19e Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 10 Dec 2023 14:07:25 +0100 Subject: fix --- src/afl-fuzz-bitmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 7c81d01a..5f67347c 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -462,7 +462,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) { classify_counts(&afl->fsrv); - cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); + u64 cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); // Saturated increment if (likely(afl->n_fuzz[cksum % N_FUZZ_SIZE] < 0xFFFFFFFF)) -- cgit v1.2.3 From 353ae3682a02634abae0b6590dfb47b762cf6bfa Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 15 Dec 2023 10:24:12 +0100 Subject: switch to explore powerschedule as default --- src/afl-fuzz-state.c | 3 +-- src/afl-fuzz.c | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index db82536d..7d6fdfb9 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -89,9 +89,8 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) { afl->w_end = 0.3; afl->g_max = 5000; afl->period_pilot_tmp = 5000.0; - afl->schedule = FAST; /* Power schedule (default: FAST) */ + afl->schedule = EXPLORE; /* Power schedule (default: EXPLORE)*/ afl->havoc_max_mult = HAVOC_MAX_MULT; - afl->clear_screen = 1; /* Window resized? */ afl->havoc_div = 1; /* Cycle count divisor for havoc */ afl->stage_name = "init"; /* Name of the current fuzz stage */ diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index becad351..dd990e71 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -138,7 +138,7 @@ static void usage(u8 *argv0, int more_help) { "to\n" " exploit mode, and back on new coverage (default: %u)\n" " -p schedule - power schedules compute a seed's performance score:\n" - " fast(default), explore, exploit, seek, rare, mmopt, " + " explore(default), fast, exploit, seek, rare, mmopt, " "coe, lin\n" " quad -- see docs/FAQ.md for more information\n" " -f file - location read by the fuzzed program (default: stdin " -- cgit v1.2.3 From 1fc1b32db261b27cf14f0d1d7f77a06854b7376c Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 27 Dec 2023 13:53:11 +0100 Subject: initial simple injection detection support --- src/afl-cc.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 22cce2cd..a46facc7 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1139,6 +1139,26 @@ static void edit_params(u32 argc, char **argv, char **envp) { } + if (getenv("AFL_LLVM_INJECTIONS_ALL") || + getenv("AFL_LLVM_INJECTIONS_SQL") || + getenv("AFL_LLVM_INJECTIONS_LDAP") || + getenv("AFL_LLVM_INJECTIONS_XSS")) { + +#if LLVM_MAJOR >= 11 + #if LLVM_MAJOR < 16 + cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; + #endif + cc_params[cc_par_cnt++] = + alloc_printf("-fpass-plugin=%s/injection-pass.so", obj_path); +#else + cc_params[cc_par_cnt++] = "-Xclang"; + cc_params[cc_par_cnt++] = "-load"; + cc_params[cc_par_cnt++] = "-Xclang"; + cc_params[cc_par_cnt++] = alloc_printf("%s/injection-pass.so", obj_path); +#endif + + } + // cc_params[cc_par_cnt++] = "-Qunused-arguments"; } -- cgit v1.2.3 From 98a2a334de15ed08d82c76bfa97d1f22c81f9a7d Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 27 Dec 2023 13:58:25 +0100 Subject: inject docs --- src/afl-cc.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index a46facc7..54c733c9 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -2295,6 +2295,10 @@ int main(int argc, char **argv, char **envp) { "comparisons\n" " AFL_LLVM_DICT2FILE_NO_MAIN: skip parsing main() for the " "dictionary\n" + " AFL_LLVM_INJECTIONS_ALL: enables all injections hooking\n" + " AFL_LLVM_INJECTIONS_SQL: enables SQL injections hooking\n" + " AFL_LLVM_INJECTIONS_LDAP: enables LDAP injections hooking\n" + " AFL_LLVM_INJECTIONS_XSS: enables XSS injections hooking\n" " AFL_LLVM_LAF_ALL: enables all LAF splits/transforms\n" " AFL_LLVM_LAF_SPLIT_COMPARES: enable cascaded comparisons\n" " AFL_LLVM_LAF_SPLIT_COMPARES_BITW: size limit (default 8)\n" -- cgit v1.2.3 From 1eb54c4c3eb4ab4bc12f7f1f80f5ece15b238ef0 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 30 Dec 2023 10:49:00 +0100 Subject: finish injection implementation --- src/afl-fuzz.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index dd990e71..17949fd7 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1749,6 +1749,34 @@ int main(int argc, char **argv_orig, char **envp) { } + // Marker: ADD_TO_INJECTIONS + if (getenv("AFL_LLVM_INJECTIONS_ALL") || getenv("AFL_LLVM_INJECTIONS_SQL") || + getenv("AFL_LLVM_INJECTIONS_LDAP") || getenv("AFL_LLVM_INJECTIONS_XSS")) { + + OKF("Adding injection tokens to dictionary."); + if (getenv("AFL_LLVM_INJECTIONS_ALL") || + getenv("AFL_LLVM_INJECTIONS_SQL")) { + + add_extra(afl, "'\"\"'", 4); + + } + + if (getenv("AFL_LLVM_INJECTIONS_ALL") || + getenv("AFL_LLVM_INJECTIONS_LDAP")) { + + add_extra(afl, "*)(1=*))(|", 10); + + } + + if (getenv("AFL_LLVM_INJECTIONS_ALL") || + getenv("AFL_LLVM_INJECTIONS_XSS")) { + + add_extra(afl, "1\"><\"", 5); + + } + + } + OKF("Generating fuzz data with a length of min=%u max=%u", afl->min_length, afl->max_length); u32 min_alloc = MAX(64U, afl->min_length); -- cgit v1.2.3 From aad9ac2b33cc05dc4bc11a3763386c4eb8d5672b Mon Sep 17 00:00:00 2001 From: Sonic <50692172+SonicStark@users.noreply.github.com> Date: Thu, 4 Jan 2024 21:35:25 +0800 Subject: Output afl-clang-fast stuffs only if necessary (#1912) * afl-cc header * afl-cc common declarations - Add afl-cc-state.c - Strip includes, find_object, debug/be_quiet/have_*/callname setting from afl-cc.c - Use debugf_args in main - Modify execvp stuffs to fit new aflcc struct * afl-cc show usage * afl-cc mode selecting 1. compiler_mode by callname in argv[0] 2. compiler_mode by env "AFL_CC_COMPILER" 3. compiler_mode/instrument_mode by command line options "--afl-..." 4. instrument_mode/compiler_mode by various env vars including "AFL_LLVM_INSTRUMENT" 5. final checking steps 6. print "... - mode: %s-%s\n" 7. determine real argv[0] according to compiler_mode * afl-cc macro defs * afl-cc linking behaviors * afl-cc fsanitize behaviors * afl-cc misc * afl-cc body update * afl-cc all-in-one formated with custom-format.py * nits --------- Co-authored-by: vanhauser-thc --- src/afl-cc.c | 3264 +++++++++++++++++++++++++++++++++------------------------- 1 file changed, 1838 insertions(+), 1426 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 54c733c9..08348d2c 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -47,23 +47,22 @@ #define LLVM_MINOR 0 #endif -static u8 *obj_path; /* Path to runtime libraries */ -static u8 **cc_params; /* Parameters passed to the real CC */ -static u32 cc_par_cnt = 1; /* Param count, including argv0 */ -static u8 clang_mode; /* Invoked as afl-clang*? */ -static u8 llvm_fullpath[PATH_MAX]; -static u8 instrument_mode, instrument_opt_mode, ngram_size, ctx_k, lto_mode; -static u8 compiler_mode, plusplus_mode, have_instr_env = 0, need_aflpplib = 0; -static u8 have_gcc, have_llvm, have_gcc_plugin, have_lto, have_instr_list = 0; -static u8 *lto_flag = AFL_CLANG_FLTO, *argvnull; -static u8 debug; -static u8 cwd[4096]; -static u8 cmplog_mode; -u8 use_stdin; /* dummy */ -static int passthrough; -// static u8 *march_opt = CFLAGS_OPT; - -enum { +#ifndef MAX_PARAMS_NUM + #define MAX_PARAMS_NUM 2048 +#endif + +/* Global declarations */ + +typedef enum { + + PARAM_MISS, // not matched + PARAM_SCAN, // scan only + PARAM_KEEP, // kept as-is + PARAM_DROP, // ignored + +} param_st; + +typedef enum { INSTRUMENT_DEFAULT = 0, INSTRUMENT_CLASSIC = 1, @@ -80,7 +79,20 @@ enum { INSTRUMENT_OPT_CTX_K = 64, INSTRUMENT_OPT_CODECOV = 128, -}; +} instrument_mode_id; + +typedef enum { + + UNSET = 0, + LTO = 1, + LLVM = 2, + GCC_PLUGIN = 3, + GCC = 4, + CLANG = 5 + +} compiler_mode_id; + +static u8 cwd[4096]; char instrument_mode_string[18][18] = { @@ -105,17 +117,6 @@ char instrument_mode_string[18][18] = { }; -enum { - - UNSET = 0, - LTO = 1, - LLVM = 2, - GCC_PLUGIN = 3, - GCC = 4, - CLANG = 5 - -}; - char compiler_mode_string[7][12] = { "AUTOSELECT", "LLVM-LTO", "LLVM", "GCC_PLUGIN", @@ -123,6 +124,18 @@ char compiler_mode_string[7][12] = { }; +u8 *instrument_mode_2str(instrument_mode_id i) { + + return instrument_mode_string[i]; + +} + +u8 *compiler_mode_2str(compiler_mode_id i) { + + return compiler_mode_string[i]; + +} + u8 *getthecwd() { if (getcwd(cwd, sizeof(cwd)) == NULL) { @@ -136,26 +149,228 @@ u8 *getthecwd() { } -/* Try to find a specific runtime we need, returns NULL on fail. */ +typedef struct aflcc_state { + + u8 **cc_params; /* Parameters passed to the real CC */ + u32 cc_par_cnt; /* Param count, including argv0 */ + + u8 *argv0; /* Original argv0 (by strdup) */ + u8 *callname; /* Executable file argv0 indicated */ + + u8 debug; + + u8 compiler_mode, plusplus_mode, lto_mode; + + u8 *lto_flag; + + u8 instrument_mode, instrument_opt_mode, ngram_size, ctx_k; + + u8 cmplog_mode; + + u8 have_instr_env, have_gcc, have_llvm, have_gcc_plugin, have_lto, + have_optimized_pcguard, have_instr_list; + + u8 fortify_set, asan_set, x_set, bit_mode, preprocessor_only, have_unroll, + have_o, have_pic, have_c, shared_linking, partial_linking, non_dash; + + // u8 *march_opt; + u8 need_aflpplib; + int passthrough; + + u8 use_stdin; /* dummy */ + u8 *argvnull; /* dummy */ + +} aflcc_state_t; + +void aflcc_state_init(aflcc_state_t *, u8 *argv0); + +/* Try to find a specific runtime we need, the path to obj would be + allocated and returned. Otherwise it returns NULL on fail. */ +u8 *find_object(aflcc_state_t *, u8 *obj); + +void find_built_deps(aflcc_state_t *); + +static inline void limit_params(aflcc_state_t *aflcc, u32 add) { + + if (aflcc->cc_par_cnt + add >= MAX_PARAMS_NUM) + FATAL("Too many command line parameters, please increase MAX_PARAMS_NUM."); + +} + +static inline void insert_param(aflcc_state_t *aflcc, u8 *param) { + + aflcc->cc_params[aflcc->cc_par_cnt++] = param; + +} + +static inline void insert_object(aflcc_state_t *aflcc, u8 *obj, u8 *fmt, + u8 *msg) { + + u8 *_obj_path = find_object(aflcc, obj); + if (!_obj_path) { + + if (msg) + FATAL("%s", msg); + else + FATAL("Unable to find '%s'", obj); + + } else { + + if (fmt) { + + u8 *_obj_path_fmt = alloc_printf(fmt, _obj_path); + ck_free(_obj_path); + aflcc->cc_params[aflcc->cc_par_cnt++] = _obj_path_fmt; + + } else { + + aflcc->cc_params[aflcc->cc_par_cnt++] = _obj_path; + + } + + } + +} + +static inline void load_llvm_pass(aflcc_state_t *aflcc, u8 *pass) { + +#if LLVM_MAJOR >= 11 /* use new pass manager */ + #if LLVM_MAJOR < 16 + insert_param(aflcc, "-fexperimental-new-pass-manager"); + #endif + insert_object(aflcc, pass, "-fpass-plugin=%s", 0); +#else + insert_param(aflcc, "-Xclang"); + insert_param(aflcc, "-load"); + insert_param(aflcc, "-Xclang"); + insert_object(aflcc, pass, 0, 0); +#endif + +} + +static inline void debugf_args(int argc, char **argv) { + + DEBUGF("cd '%s';", getthecwd()); + for (int i = 0; i < argc; i++) + SAYF(" '%s'", argv[i]); + SAYF("\n"); + fflush(stdout); + fflush(stderr); + +} + +void compiler_mode_by_callname(aflcc_state_t *); +void compiler_mode_by_environ(aflcc_state_t *); +void compiler_mode_by_cmdline(aflcc_state_t *, int argc, char **argv); +void instrument_mode_by_environ(aflcc_state_t *); +void mode_final_checkout(aflcc_state_t *, int argc, char **argv); +void mode_notification(aflcc_state_t *); + +void add_real_argv0(aflcc_state_t *); + +void add_defs_common(aflcc_state_t *); +void add_defs_selective_instr(aflcc_state_t *); +void add_defs_persistent_mode(aflcc_state_t *); +void add_defs_fortify(aflcc_state_t *, u8); +void add_defs_lsan_ctrl(aflcc_state_t *); + +param_st parse_fsanitize(aflcc_state_t *, u8 *, u8); +void add_sanitizers(aflcc_state_t *, char **envp); +void add_optimized_pcguard(aflcc_state_t *); +void add_native_pcguard(aflcc_state_t *); + +void add_assembler(aflcc_state_t *); +void add_gcc_plugin(aflcc_state_t *); + +param_st parse_misc_params(aflcc_state_t *, u8 *, u8); +void add_misc_params(aflcc_state_t *); + +param_st parse_linking_params(aflcc_state_t *, u8 *, u8, u8 *skip_next, + char **argv); + +void add_lto_linker(aflcc_state_t *); +void add_lto_passes(aflcc_state_t *); +void add_runtime(aflcc_state_t *); + +/* Working state */ + +void aflcc_state_init(aflcc_state_t *aflcc, u8 *argv0) { + + // Default NULL/0 is a good start + memset(aflcc, 0, sizeof(aflcc_state_t)); + + aflcc->cc_params = ck_alloc(MAX_PARAMS_NUM * sizeof(u8 *)); + aflcc->cc_par_cnt = 1; + + aflcc->lto_flag = AFL_CLANG_FLTO; + + // aflcc->march_opt = CFLAGS_OPT; + + /* callname & if C++ mode */ + + aflcc->argv0 = ck_strdup(argv0); + + char *cname = NULL; + + if ((cname = strrchr(aflcc->argv0, '/')) != NULL) { + + cname++; + + } else { + + cname = aflcc->argv0; + + } + + aflcc->callname = cname; + + if (strlen(cname) > 2 && (strncmp(cname + strlen(cname) - 2, "++", 2) == 0 || + strstr(cname, "-g++") != NULL)) { + + aflcc->plusplus_mode = 1; + + } + + /* debug */ + + if (getenv("AFL_DEBUG")) { + + aflcc->debug = 1; + if (strcmp(getenv("AFL_DEBUG"), "0") == 0) unsetenv("AFL_DEBUG"); + + } else if (getenv("AFL_QUIET")) { + + be_quiet = 1; + + } + + if ((getenv("AFL_PASSTHROUGH") || getenv("AFL_NOOPT")) && (!aflcc->debug)) { + + be_quiet = 1; + + } + +} /* in find_object() we look here: - 1. if obj_path is already set we look there first - 2. then we check the $AFL_PATH environment variable location if set - 3. next we check argv[0] if it has path information and use it + 1. firstly we check the $AFL_PATH environment variable location if set + 2. next we check argv[0] if it has path information and use it a) we also check ../lib/afl - 4. if 3. failed we check /proc (only Linux, Android, NetBSD, DragonFly, and + 3. if 2. failed we check /proc (only Linux, Android, NetBSD, DragonFly, and FreeBSD with procfs) a) and check here in ../lib/afl too - 5. we look into the AFL_PATH define (usually /usr/local/lib/afl) - 6. we finally try the current directory + 4. we look into the AFL_PATH define (usually /usr/local/lib/afl) + 5. we finally try the current directory if all these attempts fail - we return NULL and the caller has to decide - what to do. + what to do. Otherwise the path to obj would be allocated and returned. */ -static u8 *find_object(u8 *obj, u8 *argv0) { +u8 *find_object(aflcc_state_t *aflcc, u8 *obj) { + + u8 *argv0 = aflcc->argv0; u8 *afl_path = getenv("AFL_PATH"); u8 *slash = NULL, *tmp; @@ -164,14 +379,9 @@ static u8 *find_object(u8 *obj, u8 *argv0) { tmp = alloc_printf("%s/%s", afl_path, obj); - if (debug) DEBUGF("Trying %s\n", tmp); - - if (!access(tmp, R_OK)) { - - obj_path = afl_path; - return tmp; + if (aflcc->debug) DEBUGF("Trying %s\n", tmp); - } + if (!access(tmp, R_OK)) { return tmp; } ck_free(tmp); @@ -190,11 +400,11 @@ static u8 *find_object(u8 *obj, u8 *argv0) { tmp = alloc_printf("%s/%s", dir, obj); - if (debug) DEBUGF("Trying %s\n", tmp); + if (aflcc->debug) DEBUGF("Trying %s\n", tmp); if (!access(tmp, R_OK)) { - obj_path = dir; + ck_free(dir); return tmp; } @@ -202,12 +412,10 @@ static u8 *find_object(u8 *obj, u8 *argv0) { ck_free(tmp); tmp = alloc_printf("%s/../lib/afl/%s", dir, obj); - if (debug) DEBUGF("Trying %s\n", tmp); + if (aflcc->debug) DEBUGF("Trying %s\n", tmp); if (!access(tmp, R_OK)) { - u8 *dir2 = alloc_printf("%s/../lib/afl", dir); - obj_path = dir2; ck_free(dir); return tmp; @@ -247,26 +455,16 @@ static u8 *find_object(u8 *obj, u8 *argv0) { *slash = 0; tmp = alloc_printf("%s/%s", exepath, obj); - if (!access(tmp, R_OK)) { - - u8 *dir = alloc_printf("%s", exepath); - obj_path = dir; - return tmp; - - } + if (!access(tmp, R_OK)) { return tmp; } ck_free(tmp); tmp = alloc_printf("%s/../lib/afl/%s", exepath, obj); - if (debug) DEBUGF("Trying %s\n", tmp); - - if (!access(tmp, R_OK)) { + if (aflcc->debug) DEBUGF("Trying %s\n", tmp); - u8 *dir = alloc_printf("%s/../lib/afl/", exepath); - obj_path = dir; - return tmp; + if (!access(tmp, R_OK)) { return tmp; } - } + ck_free(tmp); } @@ -283,1844 +481,1911 @@ static u8 *find_object(u8 *obj, u8 *argv0) { tmp = alloc_printf("%s/%s", AFL_PATH, obj); - if (debug) DEBUGF("Trying %s\n", tmp); + if (aflcc->debug) DEBUGF("Trying %s\n", tmp); - if (!access(tmp, R_OK)) { - - obj_path = AFL_PATH; - return tmp; - - } + if (!access(tmp, R_OK)) { return tmp; } ck_free(tmp); - tmp = alloc_printf("./%s", obj); - if (debug) DEBUGF("Trying %s\n", tmp); + if (aflcc->debug) DEBUGF("Trying %s\n", tmp); - if (!access(tmp, R_OK)) { - - obj_path = "."; - return tmp; - - } + if (!access(tmp, R_OK)) { return tmp; } ck_free(tmp); - if (debug) DEBUGF("Trying ... giving up\n"); + if (aflcc->debug) DEBUGF("Trying ... giving up\n"); return NULL; } -void parse_fsanitize(char *string) { +void find_built_deps(aflcc_state_t *aflcc) { - char *p, *ptr = string + strlen("-fsanitize="); - char *new = malloc(strlen(string) + 1); - char *tmp = malloc(strlen(ptr) + 1); - u32 count = 0, len, ende = 0; + char *ptr = NULL; - if (!new || !tmp) { FATAL("could not acquire memory"); } - strcpy(new, "-fsanitize="); + if ((ptr = find_object(aflcc, "as")) != NULL) { - do { + aflcc->have_gcc = 1; + ck_free(ptr); - p = strchr(ptr, ','); - if (!p) { + } - p = ptr + strlen(ptr) + 1; - ende = 1; + if ((ptr = find_object(aflcc, "SanitizerCoveragePCGUARD.so")) != NULL) { - } + aflcc->have_optimized_pcguard = 1; + ck_free(ptr); - len = p - ptr; - if (len) { + } - strncpy(tmp, ptr, len); - tmp[len] = 0; - // fprintf(stderr, "Found: %s\n", tmp); - ptr += len + 1; - if (*tmp) { +#if (LLVM_MAJOR >= 3) - u32 copy = 1; - if (!strcmp(tmp, "fuzzer")) { + if ((ptr = find_object(aflcc, "SanitizerCoverageLTO.so")) != NULL) { - need_aflpplib = 1; - copy = 0; + aflcc->have_lto = 1; + ck_free(ptr); - } else if (!strncmp(tmp, "fuzzer", 6)) { + } - copy = 0; + if ((ptr = find_object(aflcc, "cmplog-routines-pass.so")) != NULL) { - } + aflcc->have_llvm = 1; + ck_free(ptr); - if (copy) { + } - if (count) { strcat(new, ","); } - strcat(new, tmp); - ++count; +#endif - } +#ifdef __ANDROID__ + aflcc->have_llvm = 1; +#endif - } + if ((ptr = find_object(aflcc, "afl-gcc-pass.so")) != NULL) { - } else { + aflcc->have_gcc_plugin = 1; + ck_free(ptr); - ptr++; /*fprintf(stderr, "NO!\n"); */ + } - } +#if !defined(__ANDROID__) && !defined(ANDROID) + ptr = find_object(aflcc, "afl-compiler-rt.o"); - } while (!ende); + if (!ptr) { - strcpy(string, new); - // fprintf(stderr, "string: %s\n", string); - // fprintf(stderr, "new: %s\n", new); + FATAL( + "Unable to find 'afl-compiler-rt.o'. Please set the AFL_PATH " + "environment variable."); -} + } -static u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0, - shared_linking = 0, preprocessor_only = 0, have_unroll = 0, - have_o = 0, have_pic = 0, have_c = 0, partial_linking = 0, - non_dash = 0; + if (aflcc->debug) { DEBUGF("rt=%s\n", ptr); } -#ifndef MAX_PARAMS_NUM - #define MAX_PARAMS_NUM 2048 + ck_free(ptr); #endif -static void process_params(u32 argc, char **argv) { +} - if (cc_par_cnt + argc >= MAX_PARAMS_NUM) { +/* compiler_mode & instrument_mode selecting */ - FATAL("Too many command line parameters, please increase MAX_PARAMS_NUM."); +void compiler_mode_by_callname(aflcc_state_t *aflcc) { - } + if (strncmp(aflcc->callname, "afl-clang-fast", 14) == 0) { - // reset - have_instr_list = 0; - have_c = 0; + /* afl-clang-fast is always created there by makefile + just like afl-clang, burdened with special purposes: + - If llvm-config is not available (i.e. LLVM_MAJOR is 0), + or too old, it falls back to LLVM-NATIVE mode and let + the actual compiler complain if doesn't work. + - Otherwise try default llvm instruments except LTO. + */ +#if (LLVM_MAJOR >= 3) + aflcc->compiler_mode = LLVM; +#else + aflcc->compiler_mode = CLANG; +#endif - if (lto_mode && argc > 1) { + } else - u32 idx; - for (idx = 1; idx < argc; idx++) { +#if (LLVM_MAJOR >= 3) - if (!strncasecmp(argv[idx], "-fpic", 5)) { have_pic = 1; } + if (strncmp(aflcc->callname, "afl-clang-lto", 13) == 0 || - } + strncmp(aflcc->callname, "afl-lto", 7) == 0) { - } + aflcc->compiler_mode = LTO; - // for (u32 x = 0; x < argc; ++x) fprintf(stderr, "[%u] %s\n", x, argv[x]); + } else - /* Process the argument list. */ +#endif - u8 skip_next = 0; - while (--argc) { + if (strncmp(aflcc->callname, "afl-gcc-fast", 12) == 0 || - u8 *cur = *(++argv); + strncmp(aflcc->callname, "afl-g++-fast", 12) == 0) { - if (skip_next) { + aflcc->compiler_mode = GCC_PLUGIN; - skip_next = 0; - continue; + } else if (strncmp(aflcc->callname, "afl-gcc", 7) == 0 || - } + strncmp(aflcc->callname, "afl-g++", 7) == 0) { - if (cur[0] != '-') { non_dash = 1; } - if (!strncmp(cur, "--afl", 5)) continue; + aflcc->compiler_mode = GCC; - if (lto_mode && !strncmp(cur, "-flto=thin", 10)) { + } else if (strcmp(aflcc->callname, "afl-clang") == 0 || - FATAL( - "afl-clang-lto cannot work with -flto=thin. Switch to -flto=full or " - "use afl-clang-fast!"); + strcmp(aflcc->callname, "afl-clang++") == 0) { - } + aflcc->compiler_mode = CLANG; - if (lto_mode && !strncmp(cur, "-fuse-ld=", 9)) continue; - if (lto_mode && !strncmp(cur, "--ld-path=", 10)) continue; - if (!strncmp(cur, "-fno-unroll", 11)) continue; - if (strstr(cur, "afl-compiler-rt") || strstr(cur, "afl-llvm-rt")) continue; - if (!strcmp(cur, "-Wl,-z,defs") || !strcmp(cur, "-Wl,--no-undefined") || - !strcmp(cur, "--no-undefined")) { + } - continue; +} - } +void compiler_mode_by_environ(aflcc_state_t *aflcc) { - if (compiler_mode == GCC_PLUGIN && !strcmp(cur, "-pipe")) { continue; } + if (getenv("AFL_PASSTHROUGH") || getenv("AFL_NOOPT")) { - if (!strcmp(cur, "-z") || !strcmp(cur, "-Wl,-z")) { + aflcc->passthrough = 1; - u8 *param = *(argv + 1); - if (!strcmp(param, "defs") || !strcmp(param, "-Wl,defs")) { + } - skip_next = 1; - continue; + char *ptr = getenv("AFL_CC_COMPILER"); - } + if (!ptr) { return; } - } + if (aflcc->compiler_mode) { - if ((compiler_mode == GCC || compiler_mode == GCC_PLUGIN) && - !strncmp(cur, "-stdlib=", 8)) { + if (!be_quiet) { - if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); } - continue; + WARNF( + "\"AFL_CC_COMPILER\" is set but a specific compiler was already " + "selected by command line parameter or symlink, ignoring the " + "environment variable!"); } - if (!strncmp(cur, "-fsanitize-coverage-", 20) && strstr(cur, "list=")) { + } else { - have_instr_list = 1; + if (strncasecmp(ptr, "LTO", 3) == 0) { - } + aflcc->compiler_mode = LTO; - if (!strncmp(cur, "-fsanitize=", strlen("-fsanitize=")) && - strchr(cur, ',')) { + } else if (strncasecmp(ptr, "LLVM", 4) == 0) { - parse_fsanitize(cur); - if (!cur || strlen(cur) <= strlen("-fsanitize=")) { continue; } + aflcc->compiler_mode = LLVM; - } else if ((!strncmp(cur, "-fsanitize=fuzzer-", + } else if (strncasecmp(ptr, "GCC_P", 5) == 0 || - strlen("-fsanitize=fuzzer-")) || - !strncmp(cur, "-fsanitize-coverage", - strlen("-fsanitize-coverage"))) && - (strncmp(cur, "sanitize-coverage-allow", - strlen("sanitize-coverage-allow")) && - strncmp(cur, "sanitize-coverage-deny", - strlen("sanitize-coverage-deny")) && - instrument_mode != INSTRUMENT_LLVMNATIVE)) { + strncasecmp(ptr, "GCC-P", 5) == 0 || + strncasecmp(ptr, "GCCP", 4) == 0) { - if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); } - continue; + aflcc->compiler_mode = GCC_PLUGIN; - } + } else if (strcasecmp(ptr, "GCC") == 0) { - if (need_aflpplib || !strcmp(cur, "-fsanitize=fuzzer")) { + aflcc->compiler_mode = GCC; - u8 *afllib = find_object("libAFLDriver.a", argv[0]); + } else if (strcasecmp(ptr, "CLANG") == 0) { - if (!be_quiet) { + aflcc->compiler_mode = CLANG; - OKF("Found '-fsanitize=fuzzer', replacing with libAFLDriver.a"); + } else - } + FATAL("Unknown AFL_CC_COMPILER mode: %s\n", ptr); - if (!afllib) { + } - if (!be_quiet) { +} - WARNF( - "Cannot find 'libAFLDriver.a' to replace '-fsanitize=fuzzer' in " - "the flags - this will fail!"); +// If it can be inferred, instrument_mode would also be set +void compiler_mode_by_cmdline(aflcc_state_t *aflcc, int argc, char **argv) { - } + char *ptr = NULL; - } else { + for (int i = 1; i < argc; i++) { - cc_params[cc_par_cnt++] = afllib; + if (strncmp(argv[i], "--afl", 5) == 0) { -#ifdef __APPLE__ - cc_params[cc_par_cnt++] = "-undefined"; - cc_params[cc_par_cnt++] = "dynamic_lookup"; -#endif - - } + if (!strcmp(argv[i], "--afl_noopt") || !strcmp(argv[i], "--afl-noopt")) { - if (need_aflpplib) { + aflcc->passthrough = 1; + argv[i] = "-g"; // we have to overwrite it, -g is always good + continue; - need_aflpplib = 0; + } - } else { + if (aflcc->compiler_mode && !be_quiet) { - continue; + WARNF( + "--afl-... compiler mode supersedes the AFL_CC_COMPILER and " + "symlink compiler selection!"); } - } + ptr = argv[i]; + ptr += 5; + while (*ptr == '-') + ptr++; - if (!strcmp(cur, "-m32")) bit_mode = 32; - if (!strcmp(cur, "armv7a-linux-androideabi")) bit_mode = 32; - if (!strcmp(cur, "-m64")) bit_mode = 64; + if (strncasecmp(ptr, "LTO", 3) == 0) { - if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory")) - asan_set = 1; + aflcc->compiler_mode = LTO; - if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1; + } else if (strncasecmp(ptr, "LLVM", 4) == 0) { - if (!strcmp(cur, "-x")) x_set = 1; - if (!strcmp(cur, "-E")) preprocessor_only = 1; - if (!strcmp(cur, "-shared")) shared_linking = 1; - if (!strcmp(cur, "-dynamiclib")) shared_linking = 1; - if (!strcmp(cur, "--target=wasm32-wasi")) passthrough = 1; - if (!strcmp(cur, "-Wl,-r")) partial_linking = 1; - if (!strcmp(cur, "-Wl,-i")) partial_linking = 1; - if (!strcmp(cur, "-Wl,--relocatable")) partial_linking = 1; - if (!strcmp(cur, "-r")) partial_linking = 1; - if (!strcmp(cur, "--relocatable")) partial_linking = 1; - if (!strcmp(cur, "-c")) have_c = 1; + aflcc->compiler_mode = LLVM; - if (!strncmp(cur, "-O", 2)) have_o = 1; - if (!strncmp(cur, "-funroll-loop", 13)) have_unroll = 1; + } else if (strncasecmp(ptr, "PCGUARD", 7) == 0 || - if (*cur == '@') { + strncasecmp(ptr, "PC-GUARD", 8) == 0) { - // response file support. - // we have two choices - move everything to the command line or - // rewrite the response files to temporary files and delete them - // afterwards. We choose the first for easiness. - // We do *not* support quotes in the rsp files to cope with spaces in - // filenames etc! If you need that then send a patch! - u8 *filename = cur + 1; - if (debug) { DEBUGF("response file=%s\n", filename); } - FILE *f = fopen(filename, "r"); - struct stat st; + aflcc->compiler_mode = LLVM; + aflcc->instrument_mode = INSTRUMENT_PCGUARD; - // Check not found or empty? let the compiler complain if so. - if (!f || fstat(fileno(f), &st) < 0 || st.st_size < 1) { + } else if (strcasecmp(ptr, "INSTRIM") == 0 || - cc_params[cc_par_cnt++] = cur; - continue; + strcasecmp(ptr, "CFG") == 0) { - } + FATAL( + "InsTrim instrumentation was removed. Use a modern LLVM and " + "PCGUARD (default in afl-cc).\n"); - u8 *tmpbuf = malloc(st.st_size + 2), *ptr; - char **args = malloc(sizeof(char *) * (st.st_size >> 1)); - int count = 1, cont = 0, cont_act = 0; + } else if (strcasecmp(ptr, "AFL") == 0 || - while (fgets(tmpbuf, st.st_size + 1, f)) { + strcasecmp(ptr, "CLASSIC") == 0) { - ptr = tmpbuf; - // fprintf(stderr, "1: %s\n", ptr); - // no leading whitespace - while (isspace(*ptr)) { + aflcc->compiler_mode = LLVM; + aflcc->instrument_mode = INSTRUMENT_CLASSIC; - ++ptr; - cont_act = 0; + } else if (strcasecmp(ptr, "LLVMNATIVE") == 0 || - } + strcasecmp(ptr, "NATIVE") == 0 || + strcasecmp(ptr, "LLVM-NATIVE") == 0) { - // no comments, no empty lines - if (*ptr == '#' || *ptr == '\n' || !*ptr) { continue; } - // remove LF - if (ptr[strlen(ptr) - 1] == '\n') { ptr[strlen(ptr) - 1] = 0; } - // remove CR - if (*ptr && ptr[strlen(ptr) - 1] == '\r') { ptr[strlen(ptr) - 1] = 0; } - // handle \ at end of line - if (*ptr && ptr[strlen(ptr) - 1] == '\\') { + aflcc->compiler_mode = LLVM; + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; - cont = 1; - ptr[strlen(ptr) - 1] = 0; + } else if (strncasecmp(ptr, "GCC_P", 5) == 0 || - } + strncasecmp(ptr, "GCC-P", 5) == 0 || + strncasecmp(ptr, "GCCP", 4) == 0) { - // fprintf(stderr, "2: %s\n", ptr); + aflcc->compiler_mode = GCC_PLUGIN; - // remove whitespace at end - while (*ptr && isspace(ptr[strlen(ptr) - 1])) { + } else if (strcasecmp(ptr, "GCC") == 0) { - ptr[strlen(ptr) - 1] = 0; - cont = 0; + aflcc->compiler_mode = GCC; - } + } else if (strncasecmp(ptr, "CLANG", 5) == 0) { - // fprintf(stderr, "3: %s\n", ptr); - if (*ptr) { + aflcc->compiler_mode = CLANG; - do { + } else - u8 *value = ptr; - while (*ptr && !isspace(*ptr)) { + FATAL("Unknown --afl-... compiler mode: %s\n", argv[i]); - ++ptr; + } - } + } - while (*ptr && isspace(*ptr)) { +} - *ptr++ = 0; +static void instrument_mode_old_environ(aflcc_state_t *aflcc) { - } + if (getenv("AFL_LLVM_INSTRIM") || getenv("INSTRIM") || + getenv("INSTRIM_LIB")) { - if (cont_act) { + FATAL( + "InsTrim instrumentation was removed. Use a modern LLVM and PCGUARD " + "(default in afl-cc).\n"); - u32 len = strlen(args[count - 1]) + strlen(value) + 1; - u8 *tmp = malloc(len); - snprintf(tmp, len, "%s%s", args[count - 1], value); - free(args[count - 1]); - args[count - 1] = tmp; - cont_act = 0; + } - } else { + if (getenv("USE_TRACE_PC") || getenv("AFL_USE_TRACE_PC") || + getenv("AFL_LLVM_USE_TRACE_PC") || getenv("AFL_TRACE_PC")) { - args[count++] = strdup(value); + if (aflcc->instrument_mode == 0) + aflcc->instrument_mode = INSTRUMENT_PCGUARD; + else if (aflcc->instrument_mode != INSTRUMENT_PCGUARD) + FATAL("you cannot set AFL_LLVM_INSTRUMENT and AFL_TRACE_PC together"); - } + } - } while (*ptr); + if (getenv("AFL_LLVM_CTX")) aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CTX; + if (getenv("AFL_LLVM_CALLER")) + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CALLER; - } + if (getenv("AFL_LLVM_NGRAM_SIZE")) { - if (cont) { + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_NGRAM; + aflcc->ngram_size = atoi(getenv("AFL_LLVM_NGRAM_SIZE")); + if (aflcc->ngram_size < 2 || aflcc->ngram_size > NGRAM_SIZE_MAX) + FATAL( + "NGRAM instrumentation mode must be between 2 and NGRAM_SIZE_MAX " + "(%u)", + NGRAM_SIZE_MAX); - cont_act = 1; - cont = 0; + } - } + if (getenv("AFL_LLVM_CTX_K")) { - } + aflcc->ctx_k = atoi(getenv("AFL_LLVM_CTX_K")); + if (aflcc->ctx_k < 1 || aflcc->ctx_k > CTX_MAX_K) + FATAL("K-CTX instrumentation mode must be between 1 and CTX_MAX_K (%u)", + CTX_MAX_K); + if (aflcc->ctx_k == 1) { - if (count) { process_params(count, args); } + setenv("AFL_LLVM_CALLER", "1", 1); + unsetenv("AFL_LLVM_CTX_K"); + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CALLER; - // we cannot free args[] - free(tmpbuf); + } else { - continue; + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CTX_K; } - cc_params[cc_par_cnt++] = cur; - } } -/* Copy argv to cc_params, making the necessary edits. */ - -static void edit_params(u32 argc, char **argv, char **envp) { +// compiler_mode would also be set if depended by the instrument_mode +static void instrument_mode_new_environ(aflcc_state_t *aflcc) { - cc_params = ck_alloc(MAX_PARAMS_NUM * sizeof(u8 *)); + if (!getenv("AFL_LLVM_INSTRUMENT")) { return; } - for (u32 c = 1; c < argc; ++c) { + u8 *ptr2 = strtok(getenv("AFL_LLVM_INSTRUMENT"), ":,;"); - if (!strcmp(argv[c], "-c")) have_c = 1; - if (!strncmp(argv[c], "-fsanitize-coverage-", 20) && - strstr(argv[c], "list=")) { + while (ptr2) { - have_instr_list = 1; - - } + if (strncasecmp(ptr2, "afl", strlen("afl")) == 0 || + strncasecmp(ptr2, "classic", strlen("classic")) == 0) { - } + if (aflcc->instrument_mode == INSTRUMENT_LTO) { - if (lto_mode) { + aflcc->instrument_mode = INSTRUMENT_CLASSIC; + aflcc->lto_mode = 1; - if (lto_flag[0] != '-') - FATAL( - "Using afl-clang-lto is not possible because Makefile magic did not " - "identify the correct -flto flag"); - else - compiler_mode = LTO; + } else if (!aflcc->instrument_mode || - } + aflcc->instrument_mode == INSTRUMENT_AFL) { - if (plusplus_mode) { + aflcc->instrument_mode = INSTRUMENT_AFL; - u8 *alt_cxx = getenv("AFL_CXX"); + } else { - if (!alt_cxx) { + FATAL("main instrumentation mode already set with %s", + instrument_mode_2str(aflcc->instrument_mode)); - if (compiler_mode >= GCC_PLUGIN) { + } - if (compiler_mode == GCC) { + } - alt_cxx = clang_mode ? "clang++" : "g++"; + if (strncasecmp(ptr2, "pc-guard", strlen("pc-guard")) == 0 || + strncasecmp(ptr2, "pcguard", strlen("pcguard")) == 0) { - } else if (compiler_mode == CLANG) { + if (!aflcc->instrument_mode || + aflcc->instrument_mode == INSTRUMENT_PCGUARD) - alt_cxx = "clang++"; + aflcc->instrument_mode = INSTRUMENT_PCGUARD; - } else { + else + FATAL("main instrumentation mode already set with %s", + instrument_mode_2str(aflcc->instrument_mode)); - alt_cxx = "g++"; + } - } + if (strncasecmp(ptr2, "llvmnative", strlen("llvmnative")) == 0 || + strncasecmp(ptr2, "llvm-native", strlen("llvm-native")) == 0 || + strncasecmp(ptr2, "native", strlen("native")) == 0) { - } else { + if (!aflcc->instrument_mode || + aflcc->instrument_mode == INSTRUMENT_LLVMNATIVE) - if (USE_BINDIR) - snprintf(llvm_fullpath, sizeof(llvm_fullpath), "%s/clang++", - LLVM_BINDIR); - else - snprintf(llvm_fullpath, sizeof(llvm_fullpath), CLANGPP_BIN); - alt_cxx = llvm_fullpath; + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; - } + else + FATAL("main instrumentation mode already set with %s", + instrument_mode_2str(aflcc->instrument_mode)); } - cc_params[0] = alt_cxx; - - } else { + if (strncasecmp(ptr2, "llvmcodecov", strlen("llvmcodecov")) == 0 || + strncasecmp(ptr2, "llvm-codecov", strlen("llvm-codecov")) == 0) { - u8 *alt_cc = getenv("AFL_CC"); + if (!aflcc->instrument_mode || + aflcc->instrument_mode == INSTRUMENT_LLVMNATIVE) { - if (!alt_cc) { + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CODECOV; - if (compiler_mode >= GCC_PLUGIN) { + } else { - if (compiler_mode == GCC) { + FATAL("main instrumentation mode already set with %s", + instrument_mode_2str(aflcc->instrument_mode)); - alt_cc = clang_mode ? "clang" : "gcc"; + } - } else if (compiler_mode == CLANG) { + } - alt_cc = "clang"; + if (strncasecmp(ptr2, "cfg", strlen("cfg")) == 0 || + strncasecmp(ptr2, "instrim", strlen("instrim")) == 0) { - } else { + FATAL( + "InsTrim instrumentation was removed. Use a modern LLVM and " + "PCGUARD (default in afl-cc).\n"); - alt_cc = "gcc"; + } - } + if (strncasecmp(ptr2, "lto", strlen("lto")) == 0) { - } else { + aflcc->lto_mode = 1; + if (!aflcc->instrument_mode || aflcc->instrument_mode == INSTRUMENT_LTO) - if (USE_BINDIR) - snprintf(llvm_fullpath, sizeof(llvm_fullpath), "%s/clang", - LLVM_BINDIR); - else - snprintf(llvm_fullpath, sizeof(llvm_fullpath), "%s", CLANG_BIN); - alt_cc = llvm_fullpath; + aflcc->instrument_mode = INSTRUMENT_LTO; - } + else + FATAL("main instrumentation mode already set with %s", + instrument_mode_2str(aflcc->instrument_mode)); } - cc_params[0] = alt_cc; - - } + if (strcasecmp(ptr2, "gcc") == 0) { - if (compiler_mode == GCC || compiler_mode == CLANG) { + if (!aflcc->instrument_mode || aflcc->instrument_mode == INSTRUMENT_GCC) - cc_params[cc_par_cnt++] = "-B"; - cc_params[cc_par_cnt++] = obj_path; + aflcc->instrument_mode = INSTRUMENT_GCC; - if (clang_mode || compiler_mode == CLANG) { + else if (aflcc->instrument_mode != INSTRUMENT_GCC) + FATAL("main instrumentation mode already set with %s", + instrument_mode_2str(aflcc->instrument_mode)); - cc_params[cc_par_cnt++] = "-no-integrated-as"; + aflcc->compiler_mode = GCC; } - } + if (strcasecmp(ptr2, "clang") == 0) { - if (compiler_mode == GCC_PLUGIN) { + if (!aflcc->instrument_mode || aflcc->instrument_mode == INSTRUMENT_CLANG) - char *fplugin_arg; + aflcc->instrument_mode = INSTRUMENT_CLANG; - if (cmplog_mode) { + else if (aflcc->instrument_mode != INSTRUMENT_CLANG) + FATAL("main instrumentation mode already set with %s", + instrument_mode_2str(aflcc->instrument_mode)); - fplugin_arg = - alloc_printf("-fplugin=%s/afl-gcc-cmplog-pass.so", obj_path); - cc_params[cc_par_cnt++] = fplugin_arg; - fplugin_arg = - alloc_printf("-fplugin=%s/afl-gcc-cmptrs-pass.so", obj_path); - cc_params[cc_par_cnt++] = fplugin_arg; + aflcc->compiler_mode = CLANG; } - fplugin_arg = alloc_printf("-fplugin=%s/afl-gcc-pass.so", obj_path); - cc_params[cc_par_cnt++] = fplugin_arg; - cc_params[cc_par_cnt++] = "-fno-if-conversion"; - cc_params[cc_par_cnt++] = "-fno-if-conversion2"; - - } + if (strncasecmp(ptr2, "ctx-", strlen("ctx-")) == 0 || + strncasecmp(ptr2, "kctx-", strlen("c-ctx-")) == 0 || + strncasecmp(ptr2, "k-ctx-", strlen("k-ctx-")) == 0) { - if (compiler_mode == LLVM || compiler_mode == LTO) { + u8 *ptr3 = ptr2; + while (*ptr3 && (*ptr3 < '0' || *ptr3 > '9')) + ptr3++; - cc_params[cc_par_cnt++] = "-Wno-unused-command-line-argument"; + if (!*ptr3) { - if (lto_mode && have_instr_env) { + if ((ptr3 = getenv("AFL_LLVM_CTX_K")) == NULL) + FATAL( + "you must set the K-CTX K with (e.g. for value 2) " + "AFL_LLVM_INSTRUMENT=ctx-2"); -#if LLVM_MAJOR >= 11 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = alloc_printf( - "-fpass-plugin=%s/afl-llvm-lto-instrumentlist.so", obj_path); -#else - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = "-load"; - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-llvm-lto-instrumentlist.so", obj_path); -#endif + } - } + aflcc->ctx_k = atoi(ptr3); + if (aflcc->ctx_k < 1 || aflcc->ctx_k > CTX_MAX_K) + FATAL( + "K-CTX instrumentation option must be between 1 and CTX_MAX_K " + "(%u)", + CTX_MAX_K); - if (getenv("AFL_LLVM_DICT2FILE")) { + if (aflcc->ctx_k == 1) { -#if LLVM_MAJOR >= 11 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/afl-llvm-dict2file.so", obj_path); -#else - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = "-load"; - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-llvm-dict2file.so", obj_path); -#endif + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CALLER; + setenv("AFL_LLVM_CALLER", "1", 1); + unsetenv("AFL_LLVM_CTX_K"); - } + } else { - // laf - if (getenv("LAF_SPLIT_SWITCHES") || getenv("AFL_LLVM_LAF_SPLIT_SWITCHES")) { + aflcc->instrument_opt_mode |= (INSTRUMENT_OPT_CTX_K); + u8 *ptr4 = alloc_printf("%u", aflcc->ctx_k); + setenv("AFL_LLVM_CTX_K", ptr4, 1); -#if LLVM_MAJOR >= 11 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/split-switches-pass.so", obj_path); -#else - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = "-load"; - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = - alloc_printf("%s/split-switches-pass.so", obj_path); -#endif + } } - if (getenv("LAF_TRANSFORM_COMPARES") || - getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES")) { + if (strcasecmp(ptr2, "ctx") == 0) { -#if LLVM_MAJOR >= 11 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/compare-transform-pass.so", obj_path); -#else - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = "-load"; - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = - alloc_printf("%s/compare-transform-pass.so", obj_path); -#endif + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CTX; + setenv("AFL_LLVM_CTX", "1", 1); } - if (getenv("LAF_SPLIT_COMPARES") || getenv("AFL_LLVM_LAF_SPLIT_COMPARES") || - getenv("AFL_LLVM_LAF_SPLIT_FLOATS")) { + if (strncasecmp(ptr2, "caller", strlen("caller")) == 0) { -#if LLVM_MAJOR >= 11 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/split-compares-pass.so", obj_path); -#else - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = "-load"; - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = - alloc_printf("%s/split-compares-pass.so", obj_path); -#endif + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CALLER; + setenv("AFL_LLVM_CALLER", "1", 1); } - // /laf + if (strncasecmp(ptr2, "ngram", strlen("ngram")) == 0) { - unsetenv("AFL_LD"); - unsetenv("AFL_LD_CALLER"); + u8 *ptr3 = ptr2 + strlen("ngram"); + while (*ptr3 && (*ptr3 < '0' || *ptr3 > '9')) { - if (cmplog_mode) { + ptr3++; - cc_params[cc_par_cnt++] = "-fno-inline"; + } -#if LLVM_MAJOR >= 11 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/cmplog-switches-pass.so", obj_path); - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/split-switches-pass.so", obj_path); -#else - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = "-load"; - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = - alloc_printf("%s/cmplog-switches-pass.so", obj_path); + if (!*ptr3) { - // reuse split switches from laf - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = "-load"; - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = - alloc_printf("%s/split-switches-pass.so", obj_path); -#endif + if ((ptr3 = getenv("AFL_LLVM_NGRAM_SIZE")) == NULL) + FATAL( + "you must set the NGRAM size with (e.g. for value 2) " + "AFL_LLVM_INSTRUMENT=ngram-2"); - } + } - // #if LLVM_MAJOR >= 13 - // // Use the old pass manager in LLVM 14 which the AFL++ passes still - // use. cc_params[cc_par_cnt++] = "-flegacy-pass-manager"; - // #endif + aflcc->ngram_size = atoi(ptr3); - if (lto_mode && !have_c) { + if (aflcc->ngram_size < 2 || aflcc->ngram_size > NGRAM_SIZE_MAX) { - u8 *ld_path = NULL; - if (getenv("AFL_REAL_LD")) { + FATAL( + "NGRAM instrumentation option must be between 2 and " + "NGRAM_SIZE_MAX (%u)", + NGRAM_SIZE_MAX); - ld_path = strdup(getenv("AFL_REAL_LD")); + } - } else { + aflcc->instrument_opt_mode |= (INSTRUMENT_OPT_NGRAM); + u8 *ptr4 = alloc_printf("%u", aflcc->ngram_size); + setenv("AFL_LLVM_NGRAM_SIZE", ptr4, 1); - ld_path = strdup(AFL_REAL_LD); + } - } + ptr2 = strtok(NULL, ":,;"); - if (!ld_path || !*ld_path) { + } - if (ld_path) { +} - // Freeing empty string - free(ld_path); +void instrument_mode_by_environ(aflcc_state_t *aflcc) { - } + if (getenv("AFL_LLVM_INSTRUMENT_FILE") || getenv("AFL_LLVM_WHITELIST") || + getenv("AFL_LLVM_ALLOWLIST") || getenv("AFL_LLVM_DENYLIST") || + getenv("AFL_LLVM_BLOCKLIST")) { - ld_path = strdup("ld.lld"); + aflcc->have_instr_env = 1; - } + } - if (!ld_path) { PFATAL("Could not allocate mem for ld_path"); } -#if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 12 - cc_params[cc_par_cnt++] = alloc_printf("--ld-path=%s", ld_path); -#else - cc_params[cc_par_cnt++] = alloc_printf("-fuse-ld=%s", ld_path); -#endif - free(ld_path); - -#if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 15 - // The NewPM implementation only works fully since LLVM 15. - cc_params[cc_par_cnt++] = alloc_printf( - "-Wl,--load-pass-plugin=%s/SanitizerCoverageLTO.so", obj_path); -#elif defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 13 - cc_params[cc_par_cnt++] = "-Wl,--lto-legacy-pass-manager"; - cc_params[cc_par_cnt++] = - alloc_printf("-Wl,-mllvm=-load=%s/SanitizerCoverageLTO.so", obj_path); -#else - cc_params[cc_par_cnt++] = "-fno-experimental-new-pass-manager"; - cc_params[cc_par_cnt++] = - alloc_printf("-Wl,-mllvm=-load=%s/SanitizerCoverageLTO.so", obj_path); -#endif + if (aflcc->have_instr_env && getenv("AFL_DONT_OPTIMIZE") && !be_quiet) { - cc_params[cc_par_cnt++] = "-Wl,--allow-multiple-definition"; - cc_params[cc_par_cnt++] = lto_flag; + WARNF( + "AFL_LLVM_ALLOWLIST/DENYLIST and AFL_DONT_OPTIMIZE cannot be combined " + "for file matching, only function matching!"); - } else { + } - if (instrument_mode == INSTRUMENT_PCGUARD) { + instrument_mode_old_environ(aflcc); + instrument_mode_new_environ(aflcc); -#if LLVM_MAJOR >= 13 - #if defined __ANDROID__ || ANDROID - cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; - instrument_mode = INSTRUMENT_LLVMNATIVE; - #else - if (have_instr_list) { - - if (!be_quiet) - SAYF( - "Using unoptimized trace-pc-guard, due usage of " - "-fsanitize-coverage-allow/denylist, you can use " - "AFL_LLVM_ALLOWLIST/AFL_LLMV_DENYLIST instead.\n"); - cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; - instrument_mode = INSTRUMENT_LLVMNATIVE; - - } else { - - #if LLVM_MAJOR >= 13 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = alloc_printf( - "-fpass-plugin=%s/SanitizerCoveragePCGUARD.so", obj_path); - #else - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = "-load"; - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = - alloc_printf("%s/SanitizerCoveragePCGUARD.so", obj_path); - #endif +} - } +static void instrument_opt_mode_exclude(aflcc_state_t *aflcc) { - #endif -#else - #if LLVM_MAJOR >= 4 - if (!be_quiet) - SAYF( - "Using unoptimized trace-pc-guard, upgrade to LLVM 13+ for " - "enhanced version.\n"); - cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; - instrument_mode = INSTRUMENT_LLVMNATIVE; - #else - FATAL("pcguard instrumentation requires LLVM 4.0.1+"); - #endif -#endif + if ((aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX) && + (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER)) { - } else if (instrument_mode == INSTRUMENT_LLVMNATIVE) { + FATAL("you cannot set CTX and CALLER together"); -#if LLVM_MAJOR >= 4 - if (instrument_opt_mode & INSTRUMENT_OPT_CODECOV) { + } - #if LLVM_MAJOR >= 6 - cc_params[cc_par_cnt++] = - "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table"; - #else - FATAL("pcguard instrumentation with pc-table requires LLVM 6.0.1+"); - #endif + if ((aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX) && + (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX_K)) { - } else { + FATAL("you cannot set CTX and K-CTX together"); - cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; + } - } + if ((aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER) && + (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX_K)) { -#else - FATAL("pcguard instrumentation requires LLVM 4.0.1+"); -#endif + FATAL("you cannot set CALLER and K-CTX together"); - } else { + } -#if LLVM_MAJOR >= 11 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/afl-llvm-pass.so", obj_path); -#else + if (aflcc->instrument_opt_mode && aflcc->compiler_mode != LLVM) + FATAL("CTX, CALLER and NGRAM can only be used in LLVM mode"); - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = "-load"; - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-pass.so", obj_path); -#endif + if (aflcc->instrument_opt_mode && + aflcc->instrument_opt_mode != INSTRUMENT_OPT_CODECOV && + aflcc->instrument_mode != INSTRUMENT_CLASSIC) + FATAL( + "CALLER, CTX and NGRAM instrumentation options can only be used with " + "the LLVM CLASSIC instrumentation mode."); - } +} - } +void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) { - if (cmplog_mode) { + if (aflcc->instrument_opt_mode && + aflcc->instrument_mode == INSTRUMENT_DEFAULT && + (aflcc->compiler_mode == LLVM || aflcc->compiler_mode == UNSET)) { -#if LLVM_MAJOR >= 11 - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = alloc_printf( - "-fpass-plugin=%s/cmplog-instructions-pass.so", obj_path); - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/cmplog-routines-pass.so", obj_path); -#else - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = "-load"; - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = - alloc_printf("%s/cmplog-instructions-pass.so", obj_path); - - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = "-load"; - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = - alloc_printf("%s/cmplog-routines-pass.so", obj_path); -#endif + aflcc->instrument_mode = INSTRUMENT_CLASSIC; + aflcc->compiler_mode = LLVM; - } + } - if (getenv("AFL_LLVM_INJECTIONS_ALL") || - getenv("AFL_LLVM_INJECTIONS_SQL") || - getenv("AFL_LLVM_INJECTIONS_LDAP") || - getenv("AFL_LLVM_INJECTIONS_XSS")) { + if (!aflcc->compiler_mode) { -#if LLVM_MAJOR >= 11 - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/injection-pass.so", obj_path); + // lto is not a default because outside of afl-cc RANLIB and AR have to + // be set to LLVM versions so this would work + if (aflcc->have_llvm) + aflcc->compiler_mode = LLVM; + else if (aflcc->have_gcc_plugin) + aflcc->compiler_mode = GCC_PLUGIN; + else if (aflcc->have_gcc) +#ifdef __APPLE__ + // on OSX clang masquerades as GCC + aflcc->compiler_mode = CLANG; #else - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = "-load"; - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = alloc_printf("%s/injection-pass.so", obj_path); + aflcc->compiler_mode = GCC; #endif - - } - - // cc_params[cc_par_cnt++] = "-Qunused-arguments"; + else if (aflcc->have_lto) + aflcc->compiler_mode = LTO; + else + FATAL("no compiler mode available"); } - /* Inspect the command line parameters. */ - - process_params(argc, argv); - - if (!have_pic) { + if (aflcc->compiler_mode == GCC) { aflcc->instrument_mode = INSTRUMENT_GCC; } - cc_params[cc_par_cnt++] = "-fPIC"; - have_pic = 1; + if (aflcc->compiler_mode == CLANG) { - } + /* if our PCGUARD implementation is not available then silently switch to + native LLVM PCGUARD. Or classic asm instrument is explicitly preferred. */ + if (!aflcc->have_optimized_pcguard && + (aflcc->instrument_mode == INSTRUMENT_DEFAULT || + aflcc->instrument_mode == INSTRUMENT_PCGUARD)) { - if (compiler_mode != GCC_PLUGIN && compiler_mode != GCC && - !getenv("AFL_LLVM_NO_RPATH")) { + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; - // in case LLVM is installed not via a package manager or "make install" - // e.g. compiled download or compiled from github then its ./lib directory - // might not be in the search path. Add it if so. - const char *libdir = LLVM_LIBDIR; - if (plusplus_mode && strlen(libdir) && strncmp(libdir, "/usr", 4) && - strncmp(libdir, "/lib", 4)) { + } else { - u8 *libdir_opt = strdup("-Wl,-rpath=" LLVM_LIBDIR); - cc_params[cc_par_cnt++] = libdir_opt; + aflcc->instrument_mode = INSTRUMENT_CLANG; + setenv(CLANG_ENV_VAR, "1", 1); // used by afl-as } } - if (getenv("AFL_HARDEN")) { - - cc_params[cc_par_cnt++] = "-fstack-protector-all"; - - if (!fortify_set) cc_params[cc_par_cnt++] = "-D_FORTIFY_SOURCE=2"; + if (aflcc->compiler_mode == LTO) { - } + if (aflcc->instrument_mode == 0 || + aflcc->instrument_mode == INSTRUMENT_LTO || + aflcc->instrument_mode == INSTRUMENT_CFG || + aflcc->instrument_mode == INSTRUMENT_PCGUARD) { - if (!asan_set) { + aflcc->lto_mode = 1; + // force CFG + // if (!aflcc->instrument_mode) { - if (getenv("AFL_USE_ASAN")) { + aflcc->instrument_mode = INSTRUMENT_PCGUARD; - if (getenv("AFL_USE_MSAN")) FATAL("ASAN and MSAN are mutually exclusive"); + // } - if (getenv("AFL_HARDEN")) - FATAL("ASAN and AFL_HARDEN are mutually exclusive"); + } else if (aflcc->instrument_mode == INSTRUMENT_CLASSIC) { - cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE"; - cc_params[cc_par_cnt++] = "-fsanitize=address"; + aflcc->lto_mode = 1; - } else if (getenv("AFL_USE_MSAN")) { + } else { - if (getenv("AFL_USE_ASAN")) FATAL("ASAN and MSAN are mutually exclusive"); + if (!be_quiet) { - if (getenv("AFL_HARDEN")) - FATAL("MSAN and AFL_HARDEN are mutually exclusive"); + WARNF("afl-clang-lto called with mode %s, using that mode instead", + instrument_mode_2str(aflcc->instrument_mode)); - cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE"; - cc_params[cc_par_cnt++] = "-fsanitize=memory"; + } } } - if (getenv("AFL_USE_UBSAN")) { + if (aflcc->instrument_mode == 0 && aflcc->compiler_mode < GCC_PLUGIN) { - cc_params[cc_par_cnt++] = "-fsanitize=undefined"; - cc_params[cc_par_cnt++] = "-fsanitize-undefined-trap-on-error"; - cc_params[cc_par_cnt++] = "-fno-sanitize-recover=all"; - cc_params[cc_par_cnt++] = "-fno-omit-frame-pointer"; +#if LLVM_MAJOR >= 7 + #if LLVM_MAJOR < 11 && (LLVM_MAJOR < 10 || LLVM_MINOR < 1) + if (aflcc->have_instr_env) { - } + aflcc->instrument_mode = INSTRUMENT_AFL; + if (!be_quiet) { - if (getenv("AFL_USE_TSAN")) { + WARNF( + "Switching to classic instrumentation because " + "AFL_LLVM_ALLOWLIST/DENYLIST does not work with PCGUARD < 10.0.1."); - cc_params[cc_par_cnt++] = "-fsanitize=thread"; - cc_params[cc_par_cnt++] = "-fno-omit-frame-pointer"; + } - } + } else - if (getenv("AFL_USE_LSAN")) { + #endif + aflcc->instrument_mode = INSTRUMENT_PCGUARD; - cc_params[cc_par_cnt++] = "-fsanitize=leak"; - cc_params[cc_par_cnt++] = "-includesanitizer/lsan_interface.h"; - cc_params[cc_par_cnt++] = - "-D__AFL_LEAK_CHECK()={if(__lsan_do_recoverable_leak_check() > 0) " - "_exit(23); }"; - cc_params[cc_par_cnt++] = "-D__AFL_LSAN_OFF()=__lsan_disable();"; - cc_params[cc_par_cnt++] = "-D__AFL_LSAN_ON()=__lsan_enable();"; +#else + aflcc->instrument_mode = INSTRUMENT_AFL; +#endif } - if (getenv("AFL_USE_CFISAN")) { - - if (compiler_mode == GCC_PLUGIN || compiler_mode == GCC) { - - cc_params[cc_par_cnt++] = "-fcf-protection=full"; + if (!aflcc->instrument_opt_mode && aflcc->lto_mode && + aflcc->instrument_mode == INSTRUMENT_CFG) { - } else { - - if (!lto_mode) { + aflcc->instrument_mode = INSTRUMENT_PCGUARD; - uint32_t i = 0, found = 0; - while (envp[i] != NULL && !found) - if (strncmp("-flto", envp[i++], 5) == 0) found = 1; - if (!found) cc_params[cc_par_cnt++] = "-flto"; + } - } +#ifndef AFL_CLANG_FLTO + if (aflcc->lto_mode) + FATAL( + "instrumentation mode LTO specified but LLVM support not available " + "(requires LLVM 11 or higher)"); +#endif - cc_params[cc_par_cnt++] = "-fsanitize=cfi"; - cc_params[cc_par_cnt++] = "-fvisibility=hidden"; + if (aflcc->lto_mode) { - } + if (aflcc->lto_flag[0] != '-') + FATAL( + "Using afl-clang-lto is not possible because Makefile magic did not " + "identify the correct -flto flag"); + else + aflcc->compiler_mode = LTO; } - if (!getenv("AFL_DONT_OPTIMIZE")) { - - cc_params[cc_par_cnt++] = "-g"; - if (!have_o) cc_params[cc_par_cnt++] = "-O3"; - if (!have_unroll) cc_params[cc_par_cnt++] = "-funroll-loops"; - // if (strlen(march_opt) > 1 && march_opt[0] == '-') - // cc_params[cc_par_cnt++] = march_opt; + if (getenv("AFL_LLVM_SKIP_NEVERZERO") && getenv("AFL_LLVM_NOT_ZERO")) + FATAL( + "AFL_LLVM_NOT_ZERO and AFL_LLVM_SKIP_NEVERZERO can not be set " + "together"); - } +#if LLVM_MAJOR < 11 && (LLVM_MAJOR < 10 || LLVM_MINOR < 1) - if (getenv("AFL_NO_BUILTIN") || getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES") || - getenv("LAF_TRANSFORM_COMPARES") || getenv("AFL_LLVM_LAF_ALL") || - lto_mode) { + if (aflcc->instrument_mode == INSTRUMENT_PCGUARD && aflcc->have_instr_env) { - cc_params[cc_par_cnt++] = "-fno-builtin-strcmp"; - cc_params[cc_par_cnt++] = "-fno-builtin-strncmp"; - cc_params[cc_par_cnt++] = "-fno-builtin-strcasecmp"; - cc_params[cc_par_cnt++] = "-fno-builtin-strncasecmp"; - cc_params[cc_par_cnt++] = "-fno-builtin-memcmp"; - cc_params[cc_par_cnt++] = "-fno-builtin-bcmp"; - cc_params[cc_par_cnt++] = "-fno-builtin-strstr"; - cc_params[cc_par_cnt++] = "-fno-builtin-strcasestr"; + FATAL( + "Instrumentation type PCGUARD does not support " + "AFL_LLVM_ALLOWLIST/DENYLIST! Use LLVM 10.0.1+ instead."); } -#if defined(USEMMAP) && !defined(__HAIKU__) && !__APPLE__ - if (!have_c) cc_params[cc_par_cnt++] = "-lrt"; #endif - cc_params[cc_par_cnt++] = "-D__AFL_COMPILER=1"; - cc_params[cc_par_cnt++] = "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1"; - - /* As documented in instrumentation/README.persistent_mode.md, deferred - forkserver initialization and persistent mode are not available in afl-gcc - and afl-clang. */ - if (compiler_mode != GCC && compiler_mode != CLANG) { - - cc_params[cc_par_cnt++] = "-D__AFL_HAVE_MANUAL_CONTROL=1"; + instrument_opt_mode_exclude(aflcc); - /* When the user tries to use persistent or deferred forkserver modes by - appending a single line to the program, we want to reliably inject a - signature into the binary (to be picked up by afl-fuzz) and we want - to call a function from the runtime .o file. This is unnecessarily - painful for three reasons: - - 1) We need to convince the compiler not to optimize out the signature. - This is done with __attribute__((used)). - - 2) We need to convince the linker, when called with -Wl,--gc-sections, - not to do the same. This is done by forcing an assignment to a - 'volatile' pointer. + u8 *ptr2; - 3) We need to declare __afl_persistent_loop() in the global namespace, - but doing this within a method in a class is hard - :: and extern "C" - are forbidden and __attribute__((alias(...))) doesn't work. Hence the - __asm__ aliasing trick. + if ((ptr2 = getenv("AFL_LLVM_DICT2FILE")) != NULL && *ptr2 != '/') + FATAL("AFL_LLVM_DICT2FILE must be set to an absolute file path"); - */ + if (getenv("AFL_LLVM_LAF_ALL")) { - cc_params[cc_par_cnt++] = - "-D__AFL_FUZZ_INIT()=" - "int __afl_sharedmem_fuzzing = 1;" - "extern unsigned int *__afl_fuzz_len;" - "extern unsigned char *__afl_fuzz_ptr;" - "unsigned char __afl_fuzz_alt[1048576];" - "unsigned char *__afl_fuzz_alt_ptr = __afl_fuzz_alt;"; + setenv("AFL_LLVM_LAF_SPLIT_SWITCHES", "1", 1); + setenv("AFL_LLVM_LAF_SPLIT_COMPARES", "1", 1); + setenv("AFL_LLVM_LAF_SPLIT_FLOATS", "1", 1); + setenv("AFL_LLVM_LAF_TRANSFORM_COMPARES", "1", 1); } - if (plusplus_mode) { + aflcc->cmplog_mode = getenv("AFL_CMPLOG") || getenv("AFL_LLVM_CMPLOG") || + getenv("AFL_GCC_CMPLOG"); - cc_params[cc_par_cnt++] = - "-D__AFL_COVERAGE()=int __afl_selective_coverage = 1;" - "extern \"C\" void __afl_coverage_discard();" - "extern \"C\" void __afl_coverage_skip();" - "extern \"C\" void __afl_coverage_on();" - "extern \"C\" void __afl_coverage_off();"; +} - } else { +void mode_notification(aflcc_state_t *aflcc) { - cc_params[cc_par_cnt++] = - "-D__AFL_COVERAGE()=int __afl_selective_coverage = 1;" - "void __afl_coverage_discard();" - "void __afl_coverage_skip();" - "void __afl_coverage_on();" - "void __afl_coverage_off();"; + char *ptr2 = alloc_printf(" + NGRAM-%u", aflcc->ngram_size); + char *ptr3 = alloc_printf(" + K-CTX-%u", aflcc->ctx_k); - } + char *ptr1 = alloc_printf( + "%s%s%s%s%s", instrument_mode_2str(aflcc->instrument_mode), + (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX) ? " + CTX" : "", + (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER) ? " + CALLER" : "", + (aflcc->instrument_opt_mode & INSTRUMENT_OPT_NGRAM) ? ptr2 : "", + (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX_K) ? ptr3 : ""); - cc_params[cc_par_cnt++] = - "-D__AFL_COVERAGE_START_OFF()=int __afl_selective_coverage_start_off = " - "1;"; - cc_params[cc_par_cnt++] = "-D__AFL_COVERAGE_ON()=__afl_coverage_on()"; - cc_params[cc_par_cnt++] = "-D__AFL_COVERAGE_OFF()=__afl_coverage_off()"; - cc_params[cc_par_cnt++] = - "-D__AFL_COVERAGE_DISCARD()=__afl_coverage_discard()"; - cc_params[cc_par_cnt++] = "-D__AFL_COVERAGE_SKIP()=__afl_coverage_skip()"; - cc_params[cc_par_cnt++] = - "-D__AFL_FUZZ_TESTCASE_BUF=(__afl_fuzz_ptr ? __afl_fuzz_ptr : " - "__afl_fuzz_alt_ptr)"; - cc_params[cc_par_cnt++] = - "-D__AFL_FUZZ_TESTCASE_LEN=(__afl_fuzz_ptr ? *__afl_fuzz_len : " - "(*__afl_fuzz_len = read(0, __afl_fuzz_alt_ptr, 1048576)) == 0xffffffff " - "? 0 : *__afl_fuzz_len)"; + ck_free(ptr2); + ck_free(ptr3); - if (compiler_mode != GCC && compiler_mode != CLANG) { + if ((isatty(2) && !be_quiet) || aflcc->debug) { - cc_params[cc_par_cnt++] = - "-D__AFL_LOOP(_A)=" - "({ static volatile const char *_B __attribute__((used,unused)); " - " _B = (const char*)\"" PERSIST_SIG - "\"; " - "extern int __afl_connected;" -#ifdef __APPLE__ - "__attribute__((visibility(\"default\"))) " - "int _L(unsigned int) __asm__(\"___afl_persistent_loop\"); " -#else - "__attribute__((visibility(\"default\"))) " - "int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); " -#endif /* ^__APPLE__ */ - // if afl is connected, we run _A times, else once. - "_L(__afl_connected ? _A : 1); })"; - - cc_params[cc_par_cnt++] = - "-D__AFL_INIT()=" - "do { static volatile const char *_A __attribute__((used,unused)); " - " _A = (const char*)\"" DEFER_SIG - "\"; " -#ifdef __APPLE__ - "__attribute__((visibility(\"default\"))) " - "void _I(void) __asm__(\"___afl_manual_init\"); " -#else - "__attribute__((visibility(\"default\"))) " - "void _I(void) __asm__(\"__afl_manual_init\"); " -#endif /* ^__APPLE__ */ - "_I(); } while (0)"; + SAYF(cCYA + "afl-cc" VERSION cRST + " by Michal Zalewski, Laszlo Szekeres, Marc Heuse - mode: %s-%s\n", + compiler_mode_2str(aflcc->compiler_mode), ptr1); } - if (x_set) { - - cc_params[cc_par_cnt++] = "-x"; - cc_params[cc_par_cnt++] = "none"; - - } + ck_free(ptr1); - // prevent unnecessary build errors - if (compiler_mode != GCC_PLUGIN && compiler_mode != GCC) { + if (!be_quiet && + (aflcc->compiler_mode == GCC || aflcc->compiler_mode == CLANG)) { - cc_params[cc_par_cnt++] = "-Wno-unused-command-line-argument"; + WARNF( + "You are using outdated instrumentation, install LLVM and/or " + "gcc-plugin and use afl-clang-fast/afl-clang-lto/afl-gcc-fast " + "instead!"); } - if (preprocessor_only || have_c || !non_dash) { +} - /* In the preprocessor_only case (-E), we are not actually compiling at - all but requesting the compiler to output preprocessed sources only. - We must not add the runtime in this case because the compiler will - simply output its binary content back on stdout, breaking any build - systems that rely on a separate source preprocessing step. */ - cc_params[cc_par_cnt] = NULL; - return; +void add_real_argv0(aflcc_state_t *aflcc) { - } + static u8 llvm_fullpath[PATH_MAX]; -#ifndef __ANDROID__ + if (aflcc->plusplus_mode) { - if (compiler_mode != GCC && compiler_mode != CLANG) { + u8 *alt_cxx = getenv("AFL_CXX"); - switch (bit_mode) { + if (!alt_cxx) { - case 0: - if (!shared_linking && !partial_linking) - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-compiler-rt.o", obj_path); - if (lto_mode) - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-llvm-rt-lto.o", obj_path); - break; + if (aflcc->compiler_mode == GCC || aflcc->compiler_mode == GCC_PLUGIN) { - case 32: - if (!shared_linking && !partial_linking) { + alt_cxx = "g++"; - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-compiler-rt-32.o", obj_path); - if (access(cc_params[cc_par_cnt - 1], R_OK)) - FATAL("-m32 is not supported by your compiler"); + } else if (aflcc->compiler_mode == CLANG) { - } + alt_cxx = "clang++"; - if (lto_mode) { + } else { - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-llvm-rt-lto-32.o", obj_path); - if (access(cc_params[cc_par_cnt - 1], R_OK)) - FATAL("-m32 is not supported by your compiler"); + if (USE_BINDIR) + snprintf(llvm_fullpath, sizeof(llvm_fullpath), "%s/clang++", + LLVM_BINDIR); + else + snprintf(llvm_fullpath, sizeof(llvm_fullpath), CLANGPP_BIN); + alt_cxx = llvm_fullpath; - } + } - break; + } - case 64: - if (!shared_linking && !partial_linking) { + aflcc->cc_params[0] = alt_cxx; - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-compiler-rt-64.o", obj_path); - if (access(cc_params[cc_par_cnt - 1], R_OK)) - FATAL("-m64 is not supported by your compiler"); + } else { - } + u8 *alt_cc = getenv("AFL_CC"); - if (lto_mode) { + if (!alt_cc) { - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-llvm-rt-lto-64.o", obj_path); - if (access(cc_params[cc_par_cnt - 1], R_OK)) - FATAL("-m64 is not supported by your compiler"); + if (aflcc->compiler_mode == GCC || aflcc->compiler_mode == GCC_PLUGIN) { - } + alt_cc = "gcc"; - break; + } else if (aflcc->compiler_mode == CLANG) { - } + alt_cc = "clang"; - #if !defined(__APPLE__) && !defined(__sun) - if (!shared_linking && !partial_linking) - cc_params[cc_par_cnt++] = - alloc_printf("-Wl,--dynamic-list=%s/dynamic_list.txt", obj_path); - #endif + } else { - #if defined(__APPLE__) - if (shared_linking || partial_linking) { + if (USE_BINDIR) + snprintf(llvm_fullpath, sizeof(llvm_fullpath), "%s/clang", + LLVM_BINDIR); + else + snprintf(llvm_fullpath, sizeof(llvm_fullpath), CLANG_BIN); + alt_cc = llvm_fullpath; - cc_params[cc_par_cnt++] = "-Wl,-U"; - cc_params[cc_par_cnt++] = "-Wl,___afl_area_ptr"; - cc_params[cc_par_cnt++] = "-Wl,-U"; - cc_params[cc_par_cnt++] = "-Wl,___sanitizer_cov_trace_pc_guard_init"; + } } - #endif + aflcc->cc_params[0] = alt_cc; } - #if defined(USEMMAP) && !defined(__HAIKU__) && !__APPLE__ - cc_params[cc_par_cnt++] = "-lrt"; - #endif - -#endif - - cc_params[cc_par_cnt] = NULL; - } -/* Main entry point */ +/* Macro defs for the preprocessor */ -int main(int argc, char **argv, char **envp) { +void add_defs_common(aflcc_state_t *aflcc) { - int i; - char *callname = argv[0], *ptr = NULL; + insert_param(aflcc, "-D__AFL_COMPILER=1"); + insert_param(aflcc, "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1"); - if (getenv("AFL_DEBUG")) { +} - debug = 1; - if (strcmp(getenv("AFL_DEBUG"), "0") == 0) unsetenv("AFL_DEBUG"); +/* See instrumentation/README.instrument_list.md# + 2-selective-instrumentation-with-_afl_coverage-directives */ +void add_defs_selective_instr(aflcc_state_t *aflcc) { - } else if (getenv("AFL_QUIET")) + if (aflcc->plusplus_mode) { - be_quiet = 1; + insert_param(aflcc, + "-D__AFL_COVERAGE()=int __afl_selective_coverage = 1;" + "extern \"C\" void __afl_coverage_discard();" + "extern \"C\" void __afl_coverage_skip();" + "extern \"C\" void __afl_coverage_on();" + "extern \"C\" void __afl_coverage_off();"); - if (getenv("AFL_LLVM_INSTRUMENT_FILE") || getenv("AFL_LLVM_WHITELIST") || - getenv("AFL_LLVM_ALLOWLIST") || getenv("AFL_LLVM_DENYLIST") || - getenv("AFL_LLVM_BLOCKLIST")) { + } else { - have_instr_env = 1; + insert_param(aflcc, + "-D__AFL_COVERAGE()=int __afl_selective_coverage = 1;" + "void __afl_coverage_discard();" + "void __afl_coverage_skip();" + "void __afl_coverage_on();" + "void __afl_coverage_off();"); } - if (getenv("AFL_PASSTHROUGH") || getenv("AFL_NOOPT")) { + insert_param( + aflcc, + "-D__AFL_COVERAGE_START_OFF()=int __afl_selective_coverage_start_off = " + "1;"); + insert_param(aflcc, "-D__AFL_COVERAGE_ON()=__afl_coverage_on()"); + insert_param(aflcc, "-D__AFL_COVERAGE_OFF()=__afl_coverage_off()"); + insert_param(aflcc, "-D__AFL_COVERAGE_DISCARD()=__afl_coverage_discard()"); + insert_param(aflcc, "-D__AFL_COVERAGE_SKIP()=__afl_coverage_skip()"); - passthrough = 1; - if (!debug) { be_quiet = 1; } +} - } +/* As documented in instrumentation/README.persistent_mode.md, deferred + forkserver initialization and persistent mode are not available in afl-gcc + and afl-clang. */ +void add_defs_persistent_mode(aflcc_state_t *aflcc) { - if ((ptr = strrchr(callname, '/')) != NULL) callname = ptr + 1; - argvnull = (u8 *)argv[0]; - check_environment_vars(envp); + if (aflcc->compiler_mode == GCC || aflcc->compiler_mode == CLANG) return; - if ((ptr = find_object("as", argv[0])) != NULL) { + insert_param(aflcc, "-D__AFL_HAVE_MANUAL_CONTROL=1"); - have_gcc = 1; - ck_free(ptr); + /* When the user tries to use persistent or deferred forkserver modes by + appending a single line to the program, we want to reliably inject a + signature into the binary (to be picked up by afl-fuzz) and we want + to call a function from the runtime .o file. This is unnecessarily + painful for three reasons: - } + 1) We need to convince the compiler not to optimize out the signature. + This is done with __attribute__((used)). -#if (LLVM_MAJOR >= 3) + 2) We need to convince the linker, when called with -Wl,--gc-sections, + not to do the same. This is done by forcing an assignment to a + 'volatile' pointer. - if ((ptr = find_object("SanitizerCoverageLTO.so", argv[0])) != NULL) { + 3) We need to declare __afl_persistent_loop() in the global namespace, + but doing this within a method in a class is hard - :: and extern "C" + are forbidden and __attribute__((alias(...))) doesn't work. Hence the + __asm__ aliasing trick. - have_lto = 1; - ck_free(ptr); + */ - } + insert_param(aflcc, + "-D__AFL_FUZZ_INIT()=" + "int __afl_sharedmem_fuzzing = 1;" + "extern unsigned int *__afl_fuzz_len;" + "extern unsigned char *__afl_fuzz_ptr;" + "unsigned char __afl_fuzz_alt[1048576];" + "unsigned char *__afl_fuzz_alt_ptr = __afl_fuzz_alt;"); - if ((ptr = find_object("cmplog-routines-pass.so", argv[0])) != NULL) { + insert_param(aflcc, + "-D__AFL_FUZZ_TESTCASE_BUF=(__afl_fuzz_ptr ? __afl_fuzz_ptr : " + "__afl_fuzz_alt_ptr)"); - have_llvm = 1; - ck_free(ptr); + insert_param( + aflcc, + "-D__AFL_FUZZ_TESTCASE_LEN=(__afl_fuzz_ptr ? *__afl_fuzz_len : " + "(*__afl_fuzz_len = read(0, __afl_fuzz_alt_ptr, 1048576)) == 0xffffffff " + "? 0 : *__afl_fuzz_len)"); + + insert_param( + aflcc, + "-D__AFL_LOOP(_A)=" + "({ static volatile const char *_B __attribute__((used,unused)); " + " _B = (const char*)\"" PERSIST_SIG + "\"; " + "extern int __afl_connected;" +#ifdef __APPLE__ + "__attribute__((visibility(\"default\"))) " + "int _L(unsigned int) __asm__(\"___afl_persistent_loop\"); " +#else + "__attribute__((visibility(\"default\"))) " + "int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); " +#endif /* ^__APPLE__ */ + // if afl is connected, we run _A times, else once. + "_L(__afl_connected ? _A : 1); })"); + + insert_param( + aflcc, + "-D__AFL_INIT()=" + "do { static volatile const char *_A __attribute__((used,unused)); " + " _A = (const char*)\"" DEFER_SIG + "\"; " +#ifdef __APPLE__ + "__attribute__((visibility(\"default\"))) " + "void _I(void) __asm__(\"___afl_manual_init\"); " +#else + "__attribute__((visibility(\"default\"))) " + "void _I(void) __asm__(\"__afl_manual_init\"); " +#endif /* ^__APPLE__ */ + "_I(); } while (0)"); - } +} -#endif +/* Control _FORTIFY_SOURCE */ +void add_defs_fortify(aflcc_state_t *aflcc, u8 action) { -#ifdef __ANDROID__ - have_llvm = 1; -#endif + switch (action) { - if ((ptr = find_object("afl-gcc-pass.so", argv[0])) != NULL) { + case 1: + insert_param(aflcc, "-D_FORTIFY_SOURCE=1"); + break; - have_gcc_plugin = 1; - ck_free(ptr); + case 2: + insert_param(aflcc, "-D_FORTIFY_SOURCE=2"); + break; + + default: // OFF + insert_param(aflcc, "-U_FORTIFY_SOURCE"); + break; } -#if (LLVM_MAJOR >= 3) +} - if (strncmp(callname, "afl-clang-fast", 14) == 0) { +void add_defs_lsan_ctrl(aflcc_state_t *aflcc) { - compiler_mode = LLVM; + insert_param(aflcc, "-includesanitizer/lsan_interface.h"); + insert_param( + aflcc, + "-D__AFL_LEAK_CHECK()={if(__lsan_do_recoverable_leak_check() > 0) " + "_exit(23); }"); + insert_param(aflcc, "-D__AFL_LSAN_OFF()=__lsan_disable();"); + insert_param(aflcc, "-D__AFL_LSAN_ON()=__lsan_enable();"); - } else if (strncmp(callname, "afl-clang-lto", 13) == 0 || +} - strncmp(callname, "afl-lto", 7) == 0) { +/* About fsanitize (including PCGUARD features) */ - compiler_mode = LTO; +/* For input "-fsanitize=...", it: - } else + 1. may have various OOB traps :) if ... doesn't contain ',' or + the input has bad syntax such as "-fsantiz=," + 2. strips any fuzzer* in ... and writes back (may result in "-fsanitize=") + 3. rets 1 if exactly "fuzzer" found, otherwise rets 0 +*/ +static u8 fsanitize_fuzzer_comma(char *string) { -#endif - if (strncmp(callname, "afl-gcc-fast", 12) == 0 || + u8 detect_single_fuzzer = 0; + + char *p, *ptr = string + strlen("-fsanitize="); + // ck_alloc will check alloc failure + char *new = ck_alloc(strlen(string) + 1); + char *tmp = ck_alloc(strlen(ptr) + 1); + u32 count = 0, len, ende = 0; - strncmp(callname, "afl-g++-fast", 12) == 0) { + strcpy(new, "-fsanitize="); + + do { + + p = strchr(ptr, ','); + if (!p) { - compiler_mode = GCC_PLUGIN; + p = ptr + strlen(ptr) + 1; + ende = 1; - } else if (strncmp(callname, "afl-gcc", 7) == 0 || + } - strncmp(callname, "afl-g++", 7) == 0) { + len = p - ptr; + if (len) { - compiler_mode = GCC; + strncpy(tmp, ptr, len); + tmp[len] = 0; + // fprintf(stderr, "Found: %s\n", tmp); + ptr += len + 1; + if (*tmp) { - } else if (strcmp(callname, "afl-clang") == 0 || + u32 copy = 1; + if (!strcmp(tmp, "fuzzer")) { - strcmp(callname, "afl-clang++") == 0) { + detect_single_fuzzer = 1; + copy = 0; - compiler_mode = CLANG; + } else if (!strncmp(tmp, "fuzzer", 6)) { - } + copy = 0; - if ((ptr = getenv("AFL_CC_COMPILER"))) { + } - if (compiler_mode) { + if (copy) { - if (!be_quiet) { + if (count) { strcat(new, ","); } + strcat(new, tmp); + ++count; - WARNF( - "\"AFL_CC_COMPILER\" is set but a specific compiler was already " - "selected by command line parameter or symlink, ignoring the " - "environment variable!"); + } } } else { - if (strncasecmp(ptr, "LTO", 3) == 0) { + ptr++; - compiler_mode = LTO; + } - } else if (strncasecmp(ptr, "LLVM", 4) == 0) { + } while (!ende); - compiler_mode = LLVM; + strcpy(string, new); + // fprintf(stderr, "string: %s\n", string); + // fprintf(stderr, "new: %s\n", new); - } else if (strncasecmp(ptr, "GCC_P", 5) == 0 || + ck_free(tmp); + ck_free(new); - strncasecmp(ptr, "GCC-P", 5) == 0 || - strncasecmp(ptr, "GCCP", 4) == 0) { + return detect_single_fuzzer; - compiler_mode = GCC_PLUGIN; +} - } else if (strcasecmp(ptr, "GCC") == 0) { +param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { - compiler_mode = GCC; + param_st final_ = PARAM_MISS; - } else + if (!strncmp(cur_argv, "-fsanitize-coverage-", 20) && + strstr(cur_argv, "list=")) { + + if (scan) { + + aflcc->have_instr_list = 1; + final_ = PARAM_SCAN; + + } else { - FATAL("Unknown AFL_CC_COMPILER mode: %s\n", ptr); + final_ = PARAM_KEEP; // may be set to DROP next } } - if (strcmp(callname, "afl-clang") == 0 || - strcmp(callname, "afl-clang++") == 0) { + if (!strcmp(cur_argv, "-fsanitize=fuzzer")) { - clang_mode = 1; - compiler_mode = CLANG; + if (scan) { - if (strcmp(callname, "afl-clang++") == 0) { plusplus_mode = 1; } + aflcc->need_aflpplib = 1; + final_ = PARAM_SCAN; - } + } else { - for (i = 1; i < argc; i++) { + final_ = PARAM_DROP; - if (strncmp(argv[i], "--afl", 5) == 0) { + } - if (!strcmp(argv[i], "--afl_noopt") || !strcmp(argv[i], "--afl-noopt")) { + } else if (!strncmp(cur_argv, "-fsanitize=", strlen("-fsanitize=")) && - passthrough = 1; - argv[i] = "-g"; // we have to overwrite it, -g is always good - continue; + strchr(cur_argv, ',') && + !strstr(cur_argv, "=,")) { // avoid OOB errors - } + if (scan) { - if (compiler_mode && !be_quiet) { + u8 *cur_argv_ = ck_strdup(cur_argv); - WARNF( - "--afl-... compiler mode supersedes the AFL_CC_COMPILER and " - "symlink compiler selection!"); + if (fsanitize_fuzzer_comma(cur_argv_)) { + + aflcc->need_aflpplib = 1; + final_ = PARAM_SCAN; } - ptr = argv[i]; - ptr += 5; - while (*ptr == '-') - ptr++; + ck_free(cur_argv_); - if (strncasecmp(ptr, "LTO", 3) == 0) { + } else { - compiler_mode = LTO; + fsanitize_fuzzer_comma(cur_argv); + if (!cur_argv || strlen(cur_argv) <= strlen("-fsanitize=")) + final_ = PARAM_DROP; // this means it only has "fuzzer" previously. - } else if (strncasecmp(ptr, "LLVM", 4) == 0) { + } - compiler_mode = LLVM; + } else if ((!strncmp(cur_argv, "-fsanitize=fuzzer-", - } else if (strncasecmp(ptr, "PCGUARD", 7) == 0 || + strlen("-fsanitize=fuzzer-")) || + !strncmp(cur_argv, "-fsanitize-coverage", + strlen("-fsanitize-coverage"))) && + (strncmp(cur_argv, "sanitize-coverage-allow", + strlen("sanitize-coverage-allow")) && + strncmp(cur_argv, "sanitize-coverage-deny", + strlen("sanitize-coverage-deny")) && + aflcc->instrument_mode != INSTRUMENT_LLVMNATIVE)) { - strncasecmp(ptr, "PC-GUARD", 8) == 0) { + if (scan) { - compiler_mode = LLVM; - instrument_mode = INSTRUMENT_PCGUARD; + final_ = PARAM_SCAN; - } else if (strcasecmp(ptr, "INSTRIM") == 0 || + } else { - strcasecmp(ptr, "CFG") == 0) { + if (!be_quiet) { WARNF("Found '%s' - stripping!", cur_argv); } + final_ = PARAM_DROP; - FATAL( - "InsTrim instrumentation was removed. Use a modern LLVM and " - "PCGUARD (default in afl-cc).\n"); + } - } else if (strcasecmp(ptr, "AFL") == 0 || + } - strcasecmp(ptr, "CLASSIC") == 0) { + if (!strcmp(cur_argv, "-fsanitize=address") || + !strcmp(cur_argv, "-fsanitize=memory")) { - compiler_mode = LLVM; - instrument_mode = INSTRUMENT_CLASSIC; + if (scan) { - } else if (strcasecmp(ptr, "LLVMNATIVE") == 0 || + // "-fsanitize=undefined,address" may be un-treated, but it's OK. + aflcc->asan_set = 1; + final_ = PARAM_SCAN; - strcasecmp(ptr, "NATIVE") == 0 || - strcasecmp(ptr, "LLVM-NATIVE") == 0) { + } else { - compiler_mode = LLVM; - instrument_mode = INSTRUMENT_LLVMNATIVE; + // It's impossible that final_ is PARAM_DROP before, + // so no checks are needed here. + final_ = PARAM_KEEP; - } else if (strncasecmp(ptr, "GCC_P", 5) == 0 || + } - strncasecmp(ptr, "GCC-P", 5) == 0 || - strncasecmp(ptr, "GCCP", 4) == 0) { + } - compiler_mode = GCC_PLUGIN; + if (final_ == PARAM_KEEP) insert_param(aflcc, cur_argv); - } else if (strcasecmp(ptr, "GCC") == 0) { + return final_; - compiler_mode = GCC; +} - } else if (strncasecmp(ptr, "CLANG", 5) == 0) { +void add_sanitizers(aflcc_state_t *aflcc, char **envp) { - compiler_mode = CLANG; + if (!aflcc->asan_set) { - } else + if (getenv("AFL_USE_ASAN")) { - FATAL("Unknown --afl-... compiler mode: %s\n", argv[i]); + if (getenv("AFL_USE_MSAN")) FATAL("ASAN and MSAN are mutually exclusive"); - } + if (getenv("AFL_HARDEN")) + FATAL("ASAN and AFL_HARDEN are mutually exclusive"); - } + add_defs_fortify(aflcc, 0); + insert_param(aflcc, "-fsanitize=address"); - if (strlen(callname) > 2 && - (strncmp(callname + strlen(callname) - 2, "++", 2) == 0 || - strstr(callname, "-g++") != NULL)) - plusplus_mode = 1; + } else if (getenv("AFL_USE_MSAN")) { - if (getenv("USE_TRACE_PC") || getenv("AFL_USE_TRACE_PC") || - getenv("AFL_LLVM_USE_TRACE_PC") || getenv("AFL_TRACE_PC")) { + if (getenv("AFL_USE_ASAN")) FATAL("ASAN and MSAN are mutually exclusive"); - if (instrument_mode == 0) - instrument_mode = INSTRUMENT_PCGUARD; - else if (instrument_mode != INSTRUMENT_PCGUARD) - FATAL("you cannot set AFL_LLVM_INSTRUMENT and AFL_TRACE_PC together"); + if (getenv("AFL_HARDEN")) + FATAL("MSAN and AFL_HARDEN are mutually exclusive"); + + add_defs_fortify(aflcc, 0); + insert_param(aflcc, "-fsanitize=memory"); + + } } - if (have_instr_env && getenv("AFL_DONT_OPTIMIZE") && !be_quiet) { + if (getenv("AFL_USE_UBSAN")) { - WARNF( - "AFL_LLVM_ALLOWLIST/DENYLIST and AFL_DONT_OPTIMIZE cannot be combined " - "for file matching, only function matching!"); + insert_param(aflcc, "-fsanitize=undefined"); + insert_param(aflcc, "-fsanitize-undefined-trap-on-error"); + insert_param(aflcc, "-fno-sanitize-recover=all"); + insert_param(aflcc, "-fno-omit-frame-pointer"); } - if (getenv("AFL_LLVM_INSTRIM") || getenv("INSTRIM") || - getenv("INSTRIM_LIB")) { + if (getenv("AFL_USE_TSAN")) { - FATAL( - "InsTrim instrumentation was removed. Use a modern LLVM and PCGUARD " - "(default in afl-cc).\n"); + insert_param(aflcc, "-fsanitize=thread"); + insert_param(aflcc, "-fno-omit-frame-pointer"); } - if (getenv("AFL_LLVM_CTX")) instrument_opt_mode |= INSTRUMENT_OPT_CTX; - if (getenv("AFL_LLVM_CALLER")) instrument_opt_mode |= INSTRUMENT_OPT_CALLER; - - if (getenv("AFL_LLVM_NGRAM_SIZE")) { + if (getenv("AFL_USE_LSAN")) { - instrument_opt_mode |= INSTRUMENT_OPT_NGRAM; - ngram_size = atoi(getenv("AFL_LLVM_NGRAM_SIZE")); - if (ngram_size < 2 || ngram_size > NGRAM_SIZE_MAX) - FATAL( - "NGRAM instrumentation mode must be between 2 and NGRAM_SIZE_MAX " - "(%u)", - NGRAM_SIZE_MAX); + insert_param(aflcc, "-fsanitize=leak"); + add_defs_lsan_ctrl(aflcc); } - if (getenv("AFL_LLVM_CTX_K")) { + if (getenv("AFL_USE_CFISAN")) { - ctx_k = atoi(getenv("AFL_LLVM_CTX_K")); - if (ctx_k < 1 || ctx_k > CTX_MAX_K) - FATAL("K-CTX instrumentation mode must be between 1 and CTX_MAX_K (%u)", - CTX_MAX_K); - if (ctx_k == 1) { + if (aflcc->compiler_mode == GCC_PLUGIN || aflcc->compiler_mode == GCC) { - setenv("AFL_LLVM_CALLER", "1", 1); - unsetenv("AFL_LLVM_CTX_K"); - instrument_opt_mode |= INSTRUMENT_OPT_CALLER; + insert_param(aflcc, "-fcf-protection=full"); } else { - instrument_opt_mode |= INSTRUMENT_OPT_CTX_K; + if (!aflcc->lto_mode) { + + uint32_t i = 0, found = 0; + while (envp[i] != NULL && !found) + if (strncmp("-flto", envp[i++], 5) == 0) found = 1; + if (!found) insert_param(aflcc, "-flto"); + + } + + insert_param(aflcc, "-fsanitize=cfi"); + insert_param(aflcc, "-fvisibility=hidden"); } } - if (getenv("AFL_LLVM_INSTRUMENT")) { +} - u8 *ptr2 = strtok(getenv("AFL_LLVM_INSTRUMENT"), ":,;"); +void add_native_pcguard(aflcc_state_t *aflcc) { - while (ptr2) { + /* If llvm-config doesn't figure out LLVM_MAJOR, just + go on anyway and let compiler complain if doesn't work. */ - if (strncasecmp(ptr2, "afl", strlen("afl")) == 0 || - strncasecmp(ptr2, "classic", strlen("classic")) == 0) { + if (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CODECOV) { - if (instrument_mode == INSTRUMENT_LTO) { +#if LLVM_MAJOR > 0 && LLVM_MAJOR < 6 + FATAL("pcguard instrumentation with pc-table requires LLVM 6.0.1+"); +#else + #if LLVM_MAJOR == 0 + WARNF( + "pcguard instrumentation with pc-table requires LLVM 6.0.1+" + " otherwise the compiler will fail"); + #endif + insert_param(aflcc, + "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table"); +#endif - instrument_mode = INSTRUMENT_CLASSIC; - lto_mode = 1; + } else { - } else if (!instrument_mode || instrument_mode == INSTRUMENT_AFL) { +#if LLVM_MAJOR > 0 && LLVM_MAJOR < 4 + FATAL("pcguard instrumentation requires LLVM 4.0.1+"); +#else + #if LLVM_MAJOR == 0 + WARNF( + "pcguard instrumentation requires LLVM 4.0.1+" + " otherwise the compiler will fail"); + #endif + insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); +#endif - instrument_mode = INSTRUMENT_AFL; + } - } else { +} - FATAL("main instrumentation mode already set with %s", - instrument_mode_string[instrument_mode]); +void add_optimized_pcguard(aflcc_state_t *aflcc) { - } +#if LLVM_MAJOR >= 13 + #if defined __ANDROID__ || ANDROID - } + insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; - if (strncasecmp(ptr2, "pc-guard", strlen("pc-guard")) == 0 || - strncasecmp(ptr2, "pcguard", strlen("pcguard")) == 0) { + #else - if (!instrument_mode || instrument_mode == INSTRUMENT_PCGUARD) - instrument_mode = INSTRUMENT_PCGUARD; - else - FATAL("main instrumentation mode already set with %s", - instrument_mode_string[instrument_mode]); + if (aflcc->have_instr_list) { - } + if (!be_quiet) + SAYF( + "Using unoptimized trace-pc-guard, due usage of " + "-fsanitize-coverage-allow/denylist, you can use " + "AFL_LLVM_ALLOWLIST/AFL_LLMV_DENYLIST instead.\n"); - if (strncasecmp(ptr2, "llvmnative", strlen("llvmnative")) == 0 || - strncasecmp(ptr2, "llvm-native", strlen("llvm-native")) == 0 || - strncasecmp(ptr2, "native", strlen("native")) == 0) { + insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; - if (!instrument_mode || instrument_mode == INSTRUMENT_LLVMNATIVE) - instrument_mode = INSTRUMENT_LLVMNATIVE; - else - FATAL("main instrumentation mode already set with %s", - instrument_mode_string[instrument_mode]); + } else { - } + /* Since LLVM_MAJOR >= 13 we use new pass manager */ + #if LLVM_MAJOR < 16 + insert_param(aflcc, "-fexperimental-new-pass-manager"); + #endif + insert_object(aflcc, "SanitizerCoveragePCGUARD.so", "-fpass-plugin=%s", 0); - if (strncasecmp(ptr2, "llvmcodecov", strlen("llvmcodecov")) == 0 || - strncasecmp(ptr2, "llvm-codecov", strlen("llvm-codecov")) == 0) { + } - if (!instrument_mode || instrument_mode == INSTRUMENT_LLVMNATIVE) { + #endif // defined __ANDROID__ || ANDROID +#else // LLVM_MAJOR < 13 + #if LLVM_MAJOR >= 4 - instrument_mode = INSTRUMENT_LLVMNATIVE; - instrument_opt_mode |= INSTRUMENT_OPT_CODECOV; + if (!be_quiet) + SAYF( + "Using unoptimized trace-pc-guard, upgrade to LLVM 13+ for " + "enhanced version.\n"); + insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; - } else { + #else - FATAL("main instrumentation mode already set with %s", - instrument_mode_string[instrument_mode]); + FATAL("pcguard instrumentation requires LLVM 4.0.1+"); - } + #endif +#endif - } +} - if (strncasecmp(ptr2, "cfg", strlen("cfg")) == 0 || - strncasecmp(ptr2, "instrim", strlen("instrim")) == 0) { +/* Linking behaviors */ - FATAL( - "InsTrim instrumentation was removed. Use a modern LLVM and " - "PCGUARD (default in afl-cc).\n"); +param_st parse_linking_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan, + u8 *skip_next, char **argv) { - } + if (aflcc->lto_mode && !strncmp(cur_argv, "-flto=thin", 10)) { - if (strncasecmp(ptr2, "lto", strlen("lto")) == 0) { + FATAL( + "afl-clang-lto cannot work with -flto=thin. Switch to -flto=full or " + "use afl-clang-fast!"); - lto_mode = 1; - if (!instrument_mode || instrument_mode == INSTRUMENT_LTO) - instrument_mode = INSTRUMENT_LTO; - else - FATAL("main instrumentation mode already set with %s", - instrument_mode_string[instrument_mode]); + } - } + param_st final_ = PARAM_MISS; - if (strcasecmp(ptr2, "gcc") == 0) { + if (!strcmp(cur_argv, "-shared") || !strcmp(cur_argv, "-dynamiclib")) { - if (!instrument_mode || instrument_mode == INSTRUMENT_GCC) - instrument_mode = INSTRUMENT_GCC; - else if (instrument_mode != INSTRUMENT_GCC) - FATAL("main instrumentation mode already set with %s", - instrument_mode_string[instrument_mode]); - compiler_mode = GCC; + if (scan) { - } + aflcc->shared_linking = 1; + final_ = PARAM_SCAN; - if (strcasecmp(ptr2, "clang") == 0) { + } else { - if (!instrument_mode || instrument_mode == INSTRUMENT_CLANG) - instrument_mode = INSTRUMENT_CLANG; - else if (instrument_mode != INSTRUMENT_CLANG) - FATAL("main instrumentation mode already set with %s", - instrument_mode_string[instrument_mode]); - compiler_mode = CLANG; + final_ = PARAM_KEEP; - } + } - if (strncasecmp(ptr2, "ctx-", strlen("ctx-")) == 0 || - strncasecmp(ptr2, "kctx-", strlen("c-ctx-")) == 0 || - strncasecmp(ptr2, "k-ctx-", strlen("k-ctx-")) == 0) { + } else if (!strcmp(cur_argv, "-Wl,-r") || !strcmp(cur_argv, "-Wl,-i") || - u8 *ptr3 = ptr2; - while (*ptr3 && (*ptr3 < '0' || *ptr3 > '9')) - ptr3++; + !strcmp(cur_argv, "-Wl,--relocatable") || + !strcmp(cur_argv, "-r") || !strcmp(cur_argv, "--relocatable")) { - if (!*ptr3) { + if (scan) { - if ((ptr3 = getenv("AFL_LLVM_CTX_K")) == NULL) - FATAL( - "you must set the K-CTX K with (e.g. for value 2) " - "AFL_LLVM_INSTRUMENT=ctx-2"); + aflcc->partial_linking = 1; + final_ = PARAM_SCAN; - } + } else { - ctx_k = atoi(ptr3); - if (ctx_k < 1 || ctx_k > CTX_MAX_K) - FATAL( - "K-CTX instrumentation option must be between 1 and CTX_MAX_K " - "(%u)", - CTX_MAX_K); + final_ = PARAM_KEEP; - if (ctx_k == 1) { + } - instrument_opt_mode |= INSTRUMENT_OPT_CALLER; - setenv("AFL_LLVM_CALLER", "1", 1); - unsetenv("AFL_LLVM_CTX_K"); + } else if (!strncmp(cur_argv, "-fuse-ld=", 9) || - } else { + !strncmp(cur_argv, "--ld-path=", 10)) { - instrument_opt_mode |= (INSTRUMENT_OPT_CTX_K); - u8 *ptr4 = alloc_printf("%u", ctx_k); - setenv("AFL_LLVM_CTX_K", ptr4, 1); + if (scan) { - } + final_ = PARAM_SCAN; - } + } else { - if (strcasecmp(ptr2, "ctx") == 0) { + if (aflcc->lto_mode) + final_ = PARAM_DROP; + else + final_ = PARAM_KEEP; - instrument_opt_mode |= INSTRUMENT_OPT_CTX; - setenv("AFL_LLVM_CTX", "1", 1); + } - } + } else if (!strcmp(cur_argv, "-Wl,-z,defs") || - if (strncasecmp(ptr2, "caller", strlen("caller")) == 0) { + !strcmp(cur_argv, "-Wl,--no-undefined") || + !strcmp(cur_argv, "--no-undefined") || + strstr(cur_argv, "afl-compiler-rt") || + strstr(cur_argv, "afl-llvm-rt")) { - instrument_opt_mode |= INSTRUMENT_OPT_CALLER; - setenv("AFL_LLVM_CALLER", "1", 1); + if (scan) { - } + final_ = PARAM_SCAN; - if (strncasecmp(ptr2, "ngram", strlen("ngram")) == 0) { + } else { - u8 *ptr3 = ptr2 + strlen("ngram"); - while (*ptr3 && (*ptr3 < '0' || *ptr3 > '9')) - ptr3++; + final_ = PARAM_DROP; - if (!*ptr3) { + } - if ((ptr3 = getenv("AFL_LLVM_NGRAM_SIZE")) == NULL) - FATAL( - "you must set the NGRAM size with (e.g. for value 2) " - "AFL_LLVM_INSTRUMENT=ngram-2"); + } else if (!strcmp(cur_argv, "-z") || !strcmp(cur_argv, "-Wl,-z")) { - } + u8 *param = *(argv + 1); + if (!strcmp(param, "defs") || !strcmp(param, "-Wl,defs")) { - ngram_size = atoi(ptr3); - if (ngram_size < 2 || ngram_size > NGRAM_SIZE_MAX) - FATAL( - "NGRAM instrumentation option must be between 2 and " - "NGRAM_SIZE_MAX (%u)", - NGRAM_SIZE_MAX); - instrument_opt_mode |= (INSTRUMENT_OPT_NGRAM); - u8 *ptr4 = alloc_printf("%u", ngram_size); - setenv("AFL_LLVM_NGRAM_SIZE", ptr4, 1); + *skip_next = 1; - } + if (scan) { - ptr2 = strtok(NULL, ":,;"); + final_ = PARAM_SCAN; - } + } else { - } + final_ = PARAM_DROP; - if ((instrument_opt_mode & INSTRUMENT_OPT_CTX) && - (instrument_opt_mode & INSTRUMENT_OPT_CALLER)) { + } - FATAL("you cannot set CTX and CALLER together"); + } } - if ((instrument_opt_mode & INSTRUMENT_OPT_CTX) && - (instrument_opt_mode & INSTRUMENT_OPT_CTX_K)) { + if (final_ == PARAM_KEEP) insert_param(aflcc, cur_argv); - FATAL("you cannot set CTX and K-CTX together"); + return final_; - } +} - if ((instrument_opt_mode & INSTRUMENT_OPT_CALLER) && - (instrument_opt_mode & INSTRUMENT_OPT_CTX_K)) { +void add_lto_linker(aflcc_state_t *aflcc) { - FATAL("you cannot set CALLER and K-CTX together"); + unsetenv("AFL_LD"); + unsetenv("AFL_LD_CALLER"); - } + u8 *ld_path = NULL; + if (getenv("AFL_REAL_LD")) { - if (instrument_opt_mode && instrument_mode == INSTRUMENT_DEFAULT && - (compiler_mode == LLVM || compiler_mode == UNSET)) { + ld_path = strdup(getenv("AFL_REAL_LD")); - instrument_mode = INSTRUMENT_CLASSIC; - compiler_mode = LLVM; + } else { + + ld_path = strdup(AFL_REAL_LD); } - if (!compiler_mode) { + if (!ld_path || !*ld_path) { - // lto is not a default because outside of afl-cc RANLIB and AR have to - // be set to LLVM versions so this would work - if (have_llvm) - compiler_mode = LLVM; - else if (have_gcc_plugin) - compiler_mode = GCC_PLUGIN; - else if (have_gcc) -#ifdef __APPLE__ - // on OSX clang masquerades as GCC - compiler_mode = CLANG; -#else - compiler_mode = GCC; -#endif - else if (have_lto) - compiler_mode = LTO; - else - FATAL("no compiler mode available"); + if (ld_path) { - } + // Freeing empty string + free(ld_path); - /* if our PCGUARD implementation is not available then silently switch to - native LLVM PCGUARD */ - if (compiler_mode == CLANG && - (instrument_mode == INSTRUMENT_DEFAULT || - instrument_mode == INSTRUMENT_PCGUARD) && - find_object("SanitizerCoveragePCGUARD.so", argv[0]) == NULL) { + } - instrument_mode = INSTRUMENT_LLVMNATIVE; + ld_path = strdup("ld.lld"); } - if (compiler_mode == GCC) { - - if (clang_mode) { - - instrument_mode = INSTRUMENT_CLANG; + if (!ld_path) { PFATAL("Could not allocate mem for ld_path"); } +#if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 12 + insert_param(aflcc, alloc_printf("--ld-path=%s", ld_path)); +#else + insert_param(aflcc, alloc_printf("-fuse-ld=%s", ld_path)); +#endif + free(ld_path); - } else { +} - instrument_mode = INSTRUMENT_GCC; +void add_lto_passes(aflcc_state_t *aflcc) { + +#if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 15 + // The NewPM implementation only works fully since LLVM 15. + insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,--load-pass-plugin=%s", + 0); +#elif defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 13 + insert_param(aflcc, "-Wl,--lto-legacy-pass-manager"); + insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,-mllvm=-load=%s", 0); +#else + insert_param(aflcc, "-fno-experimental-new-pass-manager"); + insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,-mllvm=-load=%s", 0); +#endif + + insert_param(aflcc, "-Wl,--allow-multiple-definition"); + insert_param(aflcc, aflcc->lto_flag); + +} + +static void add_aflpplib(aflcc_state_t *aflcc) { + + if (!aflcc->need_aflpplib) return; + + u8 *afllib = find_object(aflcc, "libAFLDriver.a"); + + if (!be_quiet) { + + OKF("Found '-fsanitize=fuzzer', replacing with libAFLDriver.a"); + + } + + if (!afllib) { + + if (!be_quiet) { + + WARNF( + "Cannot find 'libAFLDriver.a' to replace '-fsanitize=fuzzer' in " + "the flags - this will fail!"); } + } else { + + insert_param(aflcc, afllib); + +#ifdef __APPLE__ + insert_param(aflcc, "-Wl,-undefined"); + insert_param(aflcc, "dynamic_lookup"); +#endif + + } + +} + +void add_runtime(aflcc_state_t *aflcc) { + + if (aflcc->preprocessor_only || aflcc->have_c || !aflcc->non_dash) { + + /* In the preprocessor_only case (-E), we are not actually compiling at + all but requesting the compiler to output preprocessed sources only. + We must not add the runtime in this case because the compiler will + simply output its binary content back on stdout, breaking any build + systems that rely on a separate source preprocessing step. */ + return; + + } + + if (aflcc->compiler_mode != GCC_PLUGIN && aflcc->compiler_mode != GCC && + !getenv("AFL_LLVM_NO_RPATH")) { + + // in case LLVM is installed not via a package manager or "make install" + // e.g. compiled download or compiled from github then its ./lib directory + // might not be in the search path. Add it if so. + const char *libdir = LLVM_LIBDIR; + if (aflcc->plusplus_mode && strlen(libdir) && strncmp(libdir, "/usr", 4) && + strncmp(libdir, "/lib", 4)) { + + u8 *libdir_opt = strdup("-Wl,-rpath=" LLVM_LIBDIR); + insert_param(aflcc, libdir_opt); + + } + + } + +#ifndef __ANDROID__ + + #define M32_ERR_MSG "-m32 is not supported by your compiler" + #define M64_ERR_MSG "-m64 is not supported by your compiler" + + if (aflcc->compiler_mode != GCC && aflcc->compiler_mode != CLANG) { + + switch (aflcc->bit_mode) { + + case 0: + if (!aflcc->shared_linking && !aflcc->partial_linking) + insert_object(aflcc, "afl-compiler-rt.o", 0, 0); + if (aflcc->lto_mode) insert_object(aflcc, "afl-llvm-rt-lto.o", 0, 0); + break; + + case 32: + if (!aflcc->shared_linking && !aflcc->partial_linking) + insert_object(aflcc, "afl-compiler-rt-32.o", 0, M32_ERR_MSG); + if (aflcc->lto_mode) + insert_object(aflcc, "afl-llvm-rt-lto-32.o", 0, M32_ERR_MSG); + break; + + case 64: + if (!aflcc->shared_linking && !aflcc->partial_linking) + insert_object(aflcc, "afl-compiler-rt-64.o", 0, M64_ERR_MSG); + if (aflcc->lto_mode) + insert_object(aflcc, "afl-llvm-rt-lto-64.o", 0, M64_ERR_MSG); + break; + + } + + #if !defined(__APPLE__) && !defined(__sun) + if (!aflcc->shared_linking && !aflcc->partial_linking) + insert_object(aflcc, "dynamic_list.txt", "-Wl,--dynamic-list=%s", 0); + #endif + + #if defined(__APPLE__) + if (aflcc->shared_linking || aflcc->partial_linking) { + + insert_param(aflcc, "-Wl,-U"); + insert_param(aflcc, "-Wl,___afl_area_ptr"); + insert_param(aflcc, "-Wl,-U"); + insert_param(aflcc, "-Wl,___sanitizer_cov_trace_pc_guard_init"); + + } + + #endif + + } + +#endif + + add_aflpplib(aflcc); + +#if defined(USEMMAP) && !defined(__HAIKU__) && !__APPLE__ + insert_param(aflcc, "-Wl,-lrt"); +#endif + +} + +/* Misc */ + +void add_assembler(aflcc_state_t *aflcc) { + + u8 *afl_as = find_object(aflcc, "as"); + + if (!afl_as) FATAL("Cannot find 'as' (symlink to 'afl-as')."); + + u8 *slash = strrchr(afl_as, '/'); + if (slash) *slash = 0; + + insert_param(aflcc, "-B"); + insert_param(aflcc, afl_as); + + if (aflcc->compiler_mode == CLANG) insert_param(aflcc, "-no-integrated-as"); + +} + +void add_gcc_plugin(aflcc_state_t *aflcc) { + + if (aflcc->cmplog_mode) { + + insert_object(aflcc, "afl-gcc-cmplog-pass.so", "-fplugin=%s", 0); + insert_object(aflcc, "afl-gcc-cmptrs-pass.so", "-fplugin=%s", 0); + + } + + insert_object(aflcc, "afl-gcc-pass.so", "-fplugin=%s", 0); + + insert_param(aflcc, "-fno-if-conversion"); + insert_param(aflcc, "-fno-if-conversion2"); + +} + +void add_misc_params(aflcc_state_t *aflcc) { + + if (getenv("AFL_NO_BUILTIN") || getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES") || + getenv("AFL_LLVM_LAF_ALL") || getenv("AFL_LLVM_CMPLOG") || + aflcc->lto_mode) { + + insert_param(aflcc, "-fno-builtin-strcmp"); + insert_param(aflcc, "-fno-builtin-strncmp"); + insert_param(aflcc, "-fno-builtin-strcasecmp"); + insert_param(aflcc, "-fno-builtin-strncasecmp"); + insert_param(aflcc, "-fno-builtin-memcmp"); + insert_param(aflcc, "-fno-builtin-bcmp"); + insert_param(aflcc, "-fno-builtin-strstr"); + insert_param(aflcc, "-fno-builtin-strcasestr"); + + } + + if (!aflcc->have_pic) { insert_param(aflcc, "-fPIC"); } + + if (getenv("AFL_HARDEN")) { + + insert_param(aflcc, "-fstack-protector-all"); + + if (!aflcc->fortify_set) add_defs_fortify(aflcc, 2); + + } + + if (!getenv("AFL_DONT_OPTIMIZE")) { + + insert_param(aflcc, "-g"); + if (!aflcc->have_o) insert_param(aflcc, "-O3"); + if (!aflcc->have_unroll) insert_param(aflcc, "-funroll-loops"); + // if (strlen(aflcc->march_opt) > 1 && aflcc->march_opt[0] == '-') + // insert_param(aflcc, aflcc->march_opt); + } - if (compiler_mode == CLANG) { + if (aflcc->x_set) { - instrument_mode = INSTRUMENT_CLANG; - setenv(CLANG_ENV_VAR, "1", 1); // used by afl-as + insert_param(aflcc, "-x"); + insert_param(aflcc, "none"); } +} + +param_st parse_misc_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { + + param_st final_ = PARAM_MISS; + +// MACRO START +#define SCAN_KEEP(dst, src) \ + do { \ + \ + if (scan) { \ + \ + dst = src; \ + final_ = PARAM_SCAN; \ + \ + } else { \ + \ + final_ = PARAM_KEEP; \ + \ + } \ + \ + } while (0) + + // MACRO END + + if (!strncasecmp(cur_argv, "-fpic", 5)) { + + SCAN_KEEP(aflcc->have_pic, 1); + + } else if (cur_argv[0] != '-') { + + SCAN_KEEP(aflcc->non_dash, 1); + + } else if (!strcmp(cur_argv, "-m32") || + + !strcmp(cur_argv, "armv7a-linux-androideabi")) { + + SCAN_KEEP(aflcc->bit_mode, 32); + + } else if (!strcmp(cur_argv, "-m64")) { + + SCAN_KEEP(aflcc->bit_mode, 64); + + } else if (strstr(cur_argv, "FORTIFY_SOURCE")) { + + SCAN_KEEP(aflcc->fortify_set, 1); + + } else if (!strcmp(cur_argv, "-x")) { + + SCAN_KEEP(aflcc->x_set, 1); + + } else if (!strcmp(cur_argv, "-E")) { + + SCAN_KEEP(aflcc->preprocessor_only, 1); + + } else if (!strcmp(cur_argv, "--target=wasm32-wasi")) { + + SCAN_KEEP(aflcc->passthrough, 1); + + } else if (!strcmp(cur_argv, "-c")) { + + SCAN_KEEP(aflcc->have_c, 1); + + } else if (!strncmp(cur_argv, "-O", 2)) { + + SCAN_KEEP(aflcc->have_o, 1); + + } else if (!strncmp(cur_argv, "-funroll-loop", 13)) { + + SCAN_KEEP(aflcc->have_unroll, 1); + + } else if (!strncmp(cur_argv, "--afl", 5)) { + + if (scan) + final_ = PARAM_SCAN; + else + final_ = PARAM_DROP; + + } else if (!strncmp(cur_argv, "-fno-unroll", 11)) { + + if (scan) + final_ = PARAM_SCAN; + else + final_ = PARAM_DROP; + + } else if (!strcmp(cur_argv, "-pipe") && aflcc->compiler_mode == GCC_PLUGIN) { + + if (scan) + final_ = PARAM_SCAN; + else + final_ = PARAM_DROP; + + } else if (!strncmp(cur_argv, "-stdlib=", 8) && + + (aflcc->compiler_mode == GCC || + aflcc->compiler_mode == GCC_PLUGIN)) { + + if (scan) { + + final_ = PARAM_SCAN; + + } else { + + if (!be_quiet) WARNF("Found '%s' - stripping!", cur_argv); + final_ = PARAM_DROP; + + } + + } + +#undef SCAN_KEEP + + if (final_ == PARAM_KEEP) insert_param(aflcc, cur_argv); + + return final_; + +} + +static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { + if (argc < 2 || strncmp(argv[1], "-h", 2) == 0) { printf("afl-cc" VERSION @@ -2168,16 +2433,18 @@ int main(int argc, char **argv, char **envp) { " [GCC/CLANG] simple gcc/clang: %s%s\n" " CLASSIC DEFAULT no no no no no " "no\n\n", - have_llvm ? "AVAILABLE" : "unavailable!", - compiler_mode == LLVM ? " [SELECTED]" : "", - have_llvm ? "AVAILABLE" : "unavailable!", - have_llvm ? "AVAILABLE" : "unavailable!", - have_lto ? "AVAILABLE" : "unavailable!", - compiler_mode == LTO ? " [SELECTED]" : "", - have_gcc_plugin ? "AVAILABLE" : "unavailable!", - compiler_mode == GCC_PLUGIN ? " [SELECTED]" : "", - have_gcc ? "AVAILABLE" : "unavailable!", - (compiler_mode == GCC || compiler_mode == CLANG) ? " [SELECTED]" : ""); + aflcc->have_llvm ? "AVAILABLE" : "unavailable!", + aflcc->compiler_mode == LLVM ? " [SELECTED]" : "", + aflcc->have_llvm ? "AVAILABLE" : "unavailable!", + aflcc->have_llvm ? "AVAILABLE" : "unavailable!", + aflcc->have_lto ? "AVAILABLE" : "unavailable!", + aflcc->compiler_mode == LTO ? " [SELECTED]" : "", + aflcc->have_gcc_plugin ? "AVAILABLE" : "unavailable!", + aflcc->compiler_mode == GCC_PLUGIN ? " [SELECTED]" : "", + aflcc->have_gcc ? "AVAILABLE" : "unavailable!", + (aflcc->compiler_mode == GCC || aflcc->compiler_mode == CLANG) + ? " [SELECTED]" + : ""); SAYF( "Modes:\n" @@ -2266,7 +2533,7 @@ int main(int argc, char **argv, char **envp) { " AFL_USE_TSAN: activate thread sanitizer\n" " AFL_USE_LSAN: activate leak-checker sanitizer\n"); - if (have_gcc_plugin) + if (aflcc->have_gcc_plugin) SAYF( "\nGCC Plugin-specific environment variables:\n" " AFL_GCC_CMPLOG: log operands of comparisons (RedQueen mutator)\n" @@ -2282,7 +2549,7 @@ int main(int argc, char **argv, char **envp) { #define COUNTER_BEHAVIOUR \ " AFL_LLVM_NOT_ZERO: use cycling trace counters that skip zero\n" #endif - if (have_llvm) + if (aflcc->have_llvm) SAYF( "\nLLVM/LTO/afl-clang-fast/afl-clang-lto specific environment " "variables:\n" @@ -2310,7 +2577,7 @@ int main(int argc, char **argv, char **envp) { "instrument allow/\n" " deny listing (selective instrumentation)\n"); - if (have_llvm) + if (aflcc->have_llvm) SAYF( " AFL_LLVM_CMPLOG: log operands of comparisons (RedQueen " "mutator)\n" @@ -2329,7 +2596,7 @@ int main(int argc, char **argv, char **envp) { "locations\n"); #ifdef AFL_CLANG_FLTO - if (have_lto) + if (aflcc->have_lto) SAYF( "\nLTO/afl-clang-lto specific environment variables:\n" " AFL_LLVM_MAP_ADDR: use a fixed coverage map address (speed), " @@ -2365,9 +2632,9 @@ int main(int argc, char **argv, char **envp) { "targets.\n\n"); #if (LLVM_MAJOR >= 3) - if (have_lto) + if (aflcc->have_lto) SAYF("afl-cc LTO with ld=%s %s\n", AFL_REAL_LD, AFL_CLANG_FLTO); - if (have_llvm) + if (aflcc->have_llvm) SAYF("afl-cc LLVM version %d using the binary path \"%s\".\n", LLVM_MAJOR, LLVM_BINDIR); #endif @@ -2406,205 +2673,350 @@ int main(int argc, char **argv, char **envp) { } - if (compiler_mode == LTO) { - - if (instrument_mode == 0 || instrument_mode == INSTRUMENT_LTO || - instrument_mode == INSTRUMENT_CFG || - instrument_mode == INSTRUMENT_PCGUARD) { +} - lto_mode = 1; - // force CFG - // if (!instrument_mode) { +static void process_params(aflcc_state_t *aflcc, u8 scan, u32 argc, + char **argv) { - instrument_mode = INSTRUMENT_PCGUARD; - // ptr = instrument_mode_string[instrument_mode]; - // } + limit_params(aflcc, argc); - } else if (instrument_mode == INSTRUMENT_CLASSIC) { + // for (u32 x = 0; x < argc; ++x) fprintf(stderr, "[%u] %s\n", x, argv[x]); - lto_mode = 1; + /* Process the argument list. */ - } else { + u8 skip_next = 0; + while (--argc) { - if (!be_quiet) { + u8 *cur = *(++argv); - WARNF("afl-clang-lto called with mode %s, using that mode instead", - instrument_mode_string[instrument_mode]); + if (skip_next > 0) { - } + skip_next--; + continue; } - } + if (PARAM_MISS != parse_misc_params(aflcc, cur, scan)) continue; - if (instrument_mode == 0 && compiler_mode < GCC_PLUGIN) { + if (PARAM_MISS != parse_fsanitize(aflcc, cur, scan)) continue; -#if LLVM_MAJOR >= 7 - #if LLVM_MAJOR < 11 && (LLVM_MAJOR < 10 || LLVM_MINOR < 1) - if (have_instr_env) { + if (PARAM_MISS != parse_linking_params(aflcc, cur, scan, &skip_next, argv)) + continue; - instrument_mode = INSTRUMENT_AFL; - if (!be_quiet) { + if (*cur == '@') { - WARNF( - "Switching to classic instrumentation because " - "AFL_LLVM_ALLOWLIST/DENYLIST does not work with PCGUARD < 10.0.1."); + // response file support. + // we have two choices - move everything to the command line or + // rewrite the response files to temporary files and delete them + // afterwards. We choose the first for easiness. + // We do *not* support quotes in the rsp files to cope with spaces in + // filenames etc! If you need that then send a patch! + u8 *filename = cur + 1; + if (aflcc->debug) { DEBUGF("response file=%s\n", filename); } + FILE *f = fopen(filename, "r"); + struct stat st; + + // Check not found or empty? let the compiler complain if so. + if (!f || fstat(fileno(f), &st) < 0 || st.st_size < 1) { + + if (!scan) insert_param(aflcc, cur); + continue; } - } else + u8 *tmpbuf = malloc(st.st_size + 2), *ptr; + char **args = malloc(sizeof(char *) * (st.st_size >> 1)); + int count = 1, cont = 0, cont_act = 0; - #endif - instrument_mode = INSTRUMENT_PCGUARD; + while (fgets(tmpbuf, st.st_size + 1, f)) { -#else - instrument_mode = INSTRUMENT_AFL; -#endif + ptr = tmpbuf; + // fprintf(stderr, "1: %s\n", ptr); + // no leading whitespace + while (isspace(*ptr)) { - } + ++ptr; + cont_act = 0; - if (instrument_opt_mode && compiler_mode != LLVM) - FATAL("CTX, CALLER and NGRAM can only be used in LLVM mode"); + } - if (!instrument_opt_mode) { + // no comments, no empty lines + if (*ptr == '#' || *ptr == '\n' || !*ptr) { continue; } + // remove LF + if (ptr[strlen(ptr) - 1] == '\n') { ptr[strlen(ptr) - 1] = 0; } + // remove CR + if (*ptr && ptr[strlen(ptr) - 1] == '\r') { ptr[strlen(ptr) - 1] = 0; } + // handle \ at end of line + if (*ptr && ptr[strlen(ptr) - 1] == '\\') { - if (lto_mode && instrument_mode == INSTRUMENT_CFG) - instrument_mode = INSTRUMENT_PCGUARD; - ptr = instrument_mode_string[instrument_mode]; + cont = 1; + ptr[strlen(ptr) - 1] = 0; - } else { + } - char *ptr2 = alloc_printf(" + NGRAM-%u", ngram_size); - char *ptr3 = alloc_printf(" + K-CTX-%u", ctx_k); + // fprintf(stderr, "2: %s\n", ptr); - ptr = alloc_printf( - "%s%s%s%s%s", instrument_mode_string[instrument_mode], - (instrument_opt_mode & INSTRUMENT_OPT_CTX) ? " + CTX" : "", - (instrument_opt_mode & INSTRUMENT_OPT_CALLER) ? " + CALLER" : "", - (instrument_opt_mode & INSTRUMENT_OPT_NGRAM) ? ptr2 : "", - (instrument_opt_mode & INSTRUMENT_OPT_CTX_K) ? ptr3 : ""); + // remove whitespace at end + while (*ptr && isspace(ptr[strlen(ptr) - 1])) { - ck_free(ptr2); - ck_free(ptr3); + ptr[strlen(ptr) - 1] = 0; + cont = 0; - } + } -#ifndef AFL_CLANG_FLTO - if (lto_mode) - FATAL( - "instrumentation mode LTO specified but LLVM support not available " - "(requires LLVM 11 or higher)"); -#endif + // fprintf(stderr, "3: %s\n", ptr); + if (*ptr) { - if (instrument_opt_mode && instrument_opt_mode != INSTRUMENT_OPT_CODECOV && - instrument_mode != INSTRUMENT_CLASSIC) - FATAL( - "CALLER, CTX and NGRAM instrumentation options can only be used with " - "the LLVM CLASSIC instrumentation mode."); + do { - if (getenv("AFL_LLVM_SKIP_NEVERZERO") && getenv("AFL_LLVM_NOT_ZERO")) - FATAL( - "AFL_LLVM_NOT_ZERO and AFL_LLVM_SKIP_NEVERZERO can not be set " - "together"); + u8 *value = ptr; + while (*ptr && !isspace(*ptr)) { -#if LLVM_MAJOR < 11 && (LLVM_MAJOR < 10 || LLVM_MINOR < 1) - if (instrument_mode == INSTRUMENT_PCGUARD && have_instr_env) { + ++ptr; - FATAL( - "Instrumentation type PCGUARD does not support " - "AFL_LLVM_ALLOWLIST/DENYLIST! Use LLVM 10.0.1+ instead."); + } - } + while (*ptr && isspace(*ptr)) { -#endif + *ptr++ = 0; - u8 *ptr2; + } - if ((ptr2 = getenv("AFL_LLVM_DICT2FILE")) != NULL && *ptr2 != '/') - FATAL("AFL_LLVM_DICT2FILE must be set to an absolute file path"); + if (cont_act) { - if ((isatty(2) && !be_quiet) || debug) { + u32 len = strlen(args[count - 1]) + strlen(value) + 1; + u8 *tmp = malloc(len); + snprintf(tmp, len, "%s%s", args[count - 1], value); + free(args[count - 1]); + args[count - 1] = tmp; + cont_act = 0; - SAYF(cCYA - "afl-cc" VERSION cRST - " by Michal Zalewski, Laszlo Szekeres, Marc Heuse - mode: %s-%s\n", - compiler_mode_string[compiler_mode], ptr); + } else { - } + args[count++] = strdup(value); - if (!be_quiet && (compiler_mode == GCC || compiler_mode == CLANG)) { + } - WARNF( - "You are using outdated instrumentation, install LLVM and/or " - "gcc-plugin and use afl-clang-fast/afl-clang-lto/afl-gcc-fast " - "instead!"); + } while (*ptr); + + } + + if (cont) { + + cont_act = 1; + cont = 0; + + } + + } + + if (count) { process_params(aflcc, scan, count, args); } + + // we cannot free args[] unless we don't need + // to keep any reference in cc_params + if (scan) { + + if (count) do { + + free(args[--count]); + + } while (count); + + free(args); + + } + + free(tmpbuf); + + continue; + + } + + if (!scan) insert_param(aflcc, cur); } - if (debug) { +} - DEBUGF("cd '%s';", getthecwd()); - for (i = 0; i < argc; i++) - SAYF(" '%s'", argv[i]); - SAYF("\n"); - fflush(stdout); - fflush(stderr); +/* Copy argv to cc_params, making the necessary edits. */ + +static void edit_params(aflcc_state_t *aflcc, u32 argc, char **argv, + char **envp) { + + add_real_argv0(aflcc); + + // prevent unnecessary build errors + if (aflcc->compiler_mode != GCC_PLUGIN && aflcc->compiler_mode != GCC) { + + insert_param(aflcc, "-Wno-unused-command-line-argument"); } - if (getenv("AFL_LLVM_LAF_ALL")) { + if (aflcc->compiler_mode == GCC || aflcc->compiler_mode == CLANG) { - setenv("AFL_LLVM_LAF_SPLIT_SWITCHES", "1", 1); - setenv("AFL_LLVM_LAF_SPLIT_COMPARES", "1", 1); - setenv("AFL_LLVM_LAF_SPLIT_FLOATS", "1", 1); - setenv("AFL_LLVM_LAF_TRANSFORM_COMPARES", "1", 1); + add_assembler(aflcc); } - cmplog_mode = getenv("AFL_CMPLOG") || getenv("AFL_LLVM_CMPLOG") || - getenv("AFL_GCC_CMPLOG"); + if (aflcc->compiler_mode == GCC_PLUGIN) { add_gcc_plugin(aflcc); } -#if !defined(__ANDROID__) && !defined(ANDROID) - ptr = find_object("afl-compiler-rt.o", argv[0]); + if (aflcc->compiler_mode == LLVM || aflcc->compiler_mode == LTO) { - if (!ptr) { + if (aflcc->lto_mode && aflcc->have_instr_env) { - FATAL( - "Unable to find 'afl-compiler-rt.o'. Please set the AFL_PATH " - "environment variable."); + load_llvm_pass(aflcc, "afl-llvm-lto-instrumentlist.so"); - } + } - if (debug) { DEBUGF("rt=%s obj_path=%s\n", ptr, obj_path); } + if (getenv("AFL_LLVM_DICT2FILE")) { - ck_free(ptr); -#endif + load_llvm_pass(aflcc, "afl-llvm-dict2file.so"); - edit_params(argc, argv, envp); + } - if (debug) { + // laf + if (getenv("LAF_SPLIT_SWITCHES") || getenv("AFL_LLVM_LAF_SPLIT_SWITCHES")) { - DEBUGF("cd '%s';", getthecwd()); - for (i = 0; i < (s32)cc_par_cnt; i++) - SAYF(" '%s'", cc_params[i]); - SAYF("\n"); - fflush(stdout); - fflush(stderr); + load_llvm_pass(aflcc, "split-switches-pass.so"); + + } + + if (getenv("LAF_TRANSFORM_COMPARES") || + getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES")) { + + load_llvm_pass(aflcc, "compare-transform-pass.so"); + + } + + if (getenv("LAF_SPLIT_COMPARES") || getenv("AFL_LLVM_LAF_SPLIT_COMPARES") || + getenv("AFL_LLVM_LAF_SPLIT_FLOATS")) { + + load_llvm_pass(aflcc, "split-compares-pass.so"); + + } + + // /laf + + if (aflcc->cmplog_mode) { + + insert_param(aflcc, "-fno-inline"); + + load_llvm_pass(aflcc, "cmplog-switches-pass.so"); + // reuse split switches from laf + load_llvm_pass(aflcc, "split-switches-pass.so"); + + } + + // #if LLVM_MAJOR >= 13 + // // Use the old pass manager in LLVM 14 which the AFL++ passes still + // use. insert_param(aflcc, "-flegacy-pass-manager"); + // #endif + + if (aflcc->lto_mode && !aflcc->have_c) { + + add_lto_linker(aflcc); + add_lto_passes(aflcc); + + } else { + + if (aflcc->instrument_mode == INSTRUMENT_PCGUARD) { + + add_optimized_pcguard(aflcc); + + } else if (aflcc->instrument_mode == INSTRUMENT_LLVMNATIVE) { + + add_native_pcguard(aflcc); + + } else { + + load_llvm_pass(aflcc, "afl-llvm-pass.so"); + + } + + } + + if (aflcc->cmplog_mode) { + + load_llvm_pass(aflcc, "cmplog-instructions-pass.so"); + load_llvm_pass(aflcc, "cmplog-routines-pass.so"); + + } + + if (getenv("AFL_LLVM_INJECTIONS_ALL") || + getenv("AFL_LLVM_INJECTIONS_SQL") || + getenv("AFL_LLVM_INJECTIONS_LDAP") || + getenv("AFL_LLVM_INJECTIONS_XSS")) { + + load_llvm_pass(aflcc, "injection-pass.so"); + + } + + // insert_param(aflcc, "-Qunused-arguments"); } - if (passthrough) { + /* Inspect the command line parameters. */ + + process_params(aflcc, 0, argc, argv); + + add_sanitizers(aflcc, envp); + + add_misc_params(aflcc); + + add_defs_common(aflcc); + add_defs_selective_instr(aflcc); + add_defs_persistent_mode(aflcc); + + add_runtime(aflcc); + + insert_param(aflcc, NULL); + +} + +/* Main entry point */ + +int main(int argc, char **argv, char **envp) { + + aflcc_state_t *aflcc = malloc(sizeof(aflcc_state_t)); + aflcc_state_init(aflcc, (u8 *)argv[0]); + + check_environment_vars(envp); + + find_built_deps(aflcc); + + compiler_mode_by_callname(aflcc); + compiler_mode_by_environ(aflcc); + compiler_mode_by_cmdline(aflcc, argc, argv); + + instrument_mode_by_environ(aflcc); + + mode_final_checkout(aflcc, argc, argv); + + process_params(aflcc, 1, argc, argv); + + maybe_usage(aflcc, argc, argv); + + mode_notification(aflcc); + + if (aflcc->debug) debugf_args(argc, argv); + + edit_params(aflcc, argc, argv, envp); + + if (aflcc->debug) + debugf_args((s32)aflcc->cc_par_cnt, (char **)aflcc->cc_params); + + if (aflcc->passthrough) { - argv[0] = cc_params[0]; - execvp(cc_params[0], (char **)argv); + argv[0] = aflcc->cc_params[0]; + execvp(aflcc->cc_params[0], (char **)argv); } else { - execvp(cc_params[0], (char **)cc_params); + execvp(aflcc->cc_params[0], (char **)aflcc->cc_params); } - FATAL("Oops, failed to execute '%s' - check your PATH", cc_params[0]); + FATAL("Oops, failed to execute '%s' - check your PATH", aflcc->cc_params[0]); return 0; -- cgit v1.2.3 From 4e9c6050d038c852db4f1a22fad2e8c678c9f053 Mon Sep 17 00:00:00 2001 From: Sonic <50692172+SonicStark@users.noreply.github.com> Date: Thu, 11 Jan 2024 18:44:40 +0800 Subject: Fix broken LTO mode and response file support (#1948) --- src/afl-cc.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 08348d2c..5ee19e42 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -2059,7 +2059,6 @@ void add_lto_passes(aflcc_state_t *aflcc) { #endif insert_param(aflcc, "-Wl,--allow-multiple-definition"); - insert_param(aflcc, aflcc->lto_flag); } @@ -2295,10 +2294,6 @@ param_st parse_misc_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { SCAN_KEEP(aflcc->have_pic, 1); - } else if (cur_argv[0] != '-') { - - SCAN_KEEP(aflcc->non_dash, 1); - } else if (!strcmp(cur_argv, "-m32") || !strcmp(cur_argv, "armv7a-linux-androideabi")) { @@ -2374,6 +2369,14 @@ param_st parse_misc_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { } + } else if (cur_argv[0] != '-') { + + /* It's a weak, loose pattern, with very different purpose + than others. We handle it at last, cautiously and robustly. */ + + if (scan && cur_argv[0] != '@') // response file support + aflcc->non_dash = 1; + } #undef SCAN_KEEP @@ -2912,10 +2915,16 @@ static void edit_params(aflcc_state_t *aflcc, u32 argc, char **argv, // use. insert_param(aflcc, "-flegacy-pass-manager"); // #endif - if (aflcc->lto_mode && !aflcc->have_c) { + if (aflcc->lto_mode) { + + insert_param(aflcc, aflcc->lto_flag); + + if (!aflcc->have_c) { - add_lto_linker(aflcc); - add_lto_passes(aflcc); + add_lto_linker(aflcc); + add_lto_passes(aflcc); + + } } else { -- cgit v1.2.3 From 9d3c25ac8103d79217f89d79dcc7dc20873222f4 Mon Sep 17 00:00:00 2001 From: Nils Bars Date: Thu, 11 Jan 2024 11:45:26 +0100 Subject: Strip `-Wl,-no-undefined` during compilation (#1952) Make the compiler wrapper stripping `-Wl,-no-undefined` in addition to `-Wl,--no-undefined`. Both versions of the flag are accepted by clang and, therefore, used by building systems in the wild (e.g., samba will not build without this fix). --- src/afl-cc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 5ee19e42..f39dfdcc 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1962,8 +1962,8 @@ param_st parse_linking_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan, } } else if (!strcmp(cur_argv, "-Wl,-z,defs") || - !strcmp(cur_argv, "-Wl,--no-undefined") || + !strcmp(cur_argv, "-Wl,-no-undefined") || !strcmp(cur_argv, "--no-undefined") || strstr(cur_argv, "afl-compiler-rt") || strstr(cur_argv, "afl-llvm-rt")) { @@ -3030,4 +3030,3 @@ int main(int argc, char **argv, char **envp) { return 0; } - -- cgit v1.2.3 From b99bbf671b7469a5aad29898fe28489004c4cbe7 Mon Sep 17 00:00:00 2001 From: Xeonacid Date: Thu, 11 Jan 2024 21:13:47 +0800 Subject: Remove dead code in write_to_testcase (#1955) The custom_mutators_count check in if case is duplicate with if condition. The else case is custom_mutators_count == 0, neither custom_mutator_list iteration nor sent check needed. Signed-off-by: Xeonacid --- src/afl-fuzz-run.c | 41 +++++++++-------------------------------- 1 file changed, 9 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 34a5ff81..1ee8ebe7 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -169,20 +169,16 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) { } - if (unlikely(afl->custom_mutators_count)) { - - LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { - - if (el->afl_custom_fuzz_send) { + LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { - el->afl_custom_fuzz_send(el->data, *mem, new_size); - sent = 1; + if (el->afl_custom_fuzz_send) { - } + el->afl_custom_fuzz_send(el->data, *mem, new_size); + sent = 1; - }); + } - } + }); if (likely(!sent)) { @@ -203,7 +199,7 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) { } - } else { + } else { /* !afl->custom_mutators_count */ if (unlikely(len < afl->min_length && !fix)) { @@ -215,27 +211,8 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) { } - if (unlikely(afl->custom_mutators_count)) { - - LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { - - if (el->afl_custom_fuzz_send) { - - el->afl_custom_fuzz_send(el->data, *mem, len); - sent = 1; - - } - - }); - - } - - if (likely(!sent)) { - - /* boring uncustom. */ - afl_fsrv_write_to_testcase(&afl->fsrv, *mem, len); - - } + /* boring uncustom. */ + afl_fsrv_write_to_testcase(&afl->fsrv, *mem, len); } -- cgit v1.2.3 From 46ef6a54e1395b3b03923848967e2b2eb7f37022 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 12 Jan 2024 15:43:09 +0100 Subject: code format --- src/afl-cc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index f39dfdcc..41cdc13d 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1962,6 +1962,7 @@ param_st parse_linking_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan, } } else if (!strcmp(cur_argv, "-Wl,-z,defs") || + !strcmp(cur_argv, "-Wl,--no-undefined") || !strcmp(cur_argv, "-Wl,-no-undefined") || !strcmp(cur_argv, "--no-undefined") || @@ -3030,3 +3031,4 @@ int main(int argc, char **argv, char **envp) { return 0; } + -- cgit v1.2.3 From 8412b17d799ee011507fa0bde21f3cb34fafad6a Mon Sep 17 00:00:00 2001 From: Sonic <50692172+SonicStark@users.noreply.github.com> Date: Thu, 18 Jan 2024 15:56:28 +0800 Subject: fix segv about skip_next, warn on unsupported cases of linking options (#1958) --- src/afl-cc.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 41cdc13d..748fbdfc 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1982,7 +1982,7 @@ param_st parse_linking_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan, } else if (!strcmp(cur_argv, "-z") || !strcmp(cur_argv, "-Wl,-z")) { u8 *param = *(argv + 1); - if (!strcmp(param, "defs") || !strcmp(param, "-Wl,defs")) { + if (param && (!strcmp(param, "defs") || !strcmp(param, "-Wl,defs"))) { *skip_next = 1; @@ -2000,6 +2000,64 @@ param_st parse_linking_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan, } + // Try to warn user for some unsupported cases + if (scan && final_ == PARAM_MISS) { + + u8 *ptr_ = NULL; + + if (!strcmp(cur_argv, "-Xlinker") && (ptr_ = *(argv + 1))) { + + if (!strcmp(ptr_, "defs")) { + + WARNF("'-Xlinker' 'defs' detected. This may result in a bad link."); + + } else if (strstr(ptr_, "-no-undefined")) { + + WARNF( + "'-Xlinker' '%s' detected. The latter option may be dropped and " + "result in a bad link.", + ptr_); + + } + + } else if (!strncmp(cur_argv, "-Wl,", 4) && + + (u8 *)strrchr(cur_argv, ',') != (cur_argv + 3)) { + + ptr_ = cur_argv + 4; + + if (strstr(ptr_, "-shared") || strstr(ptr_, "-dynamiclib")) { + + WARNF( + "'%s': multiple link options after '-Wl,' may break shared " + "linking.", + ptr_); + + } + + if (strstr(ptr_, "-r,") || strstr(ptr_, "-i,") || strstr(ptr_, ",-r") || + strstr(ptr_, ",-i") || strstr(ptr_, "--relocatable")) { + + WARNF( + "'%s': multiple link options after '-Wl,' may break partial " + "linking.", + ptr_); + + } + + if (strstr(ptr_, "defs") || strstr(ptr_, "no-undefined")) { + + WARNF( + "'%s': multiple link options after '-Wl,' may enable report " + "unresolved symbol references and result in a bad link.", + ptr_); + + } + + } + + } + if (final_ == PARAM_KEEP) insert_param(aflcc, cur_argv); return final_; -- cgit v1.2.3 From 136febaf6855ac1e04c8ea4ecbcb84eb42de2143 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 18 Jan 2024 09:17:25 +0100 Subject: ensure afl-cc only allows available compiler modes --- src/afl-cc.c | 140 ++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 104 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 748fbdfc..3377b42f 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -167,7 +167,7 @@ typedef struct aflcc_state { u8 cmplog_mode; - u8 have_instr_env, have_gcc, have_llvm, have_gcc_plugin, have_lto, + u8 have_instr_env, have_gcc, have_clang, have_llvm, have_gcc_plugin, have_lto, have_optimized_pcguard, have_instr_list; u8 fortify_set, asan_set, x_set, bit_mode, preprocessor_only, have_unroll, @@ -504,13 +504,20 @@ void find_built_deps(aflcc_state_t *aflcc) { char *ptr = NULL; +#if defined(__x86_64__) if ((ptr = find_object(aflcc, "as")) != NULL) { + #ifndef __APPLE__ + // on OSX clang masquerades as GCC aflcc->have_gcc = 1; + #endif + aflcc->have_clang = 1; ck_free(ptr); } +#endif + if ((ptr = find_object(aflcc, "SanitizerCoveragePCGUARD.so")) != NULL) { aflcc->have_optimized_pcguard = 1; @@ -604,12 +611,18 @@ void compiler_mode_by_callname(aflcc_state_t *aflcc) { aflcc->compiler_mode = GCC_PLUGIN; +#if defined(__x86_64__) + } else if (strncmp(aflcc->callname, "afl-gcc", 7) == 0 || strncmp(aflcc->callname, "afl-g++", 7) == 0) { aflcc->compiler_mode = GCC; +#endif + +#if defined(__x86_64__) + } else if (strcmp(aflcc->callname, "afl-clang") == 0 || strcmp(aflcc->callname, "afl-clang++") == 0) { @@ -618,6 +631,8 @@ void compiler_mode_by_callname(aflcc_state_t *aflcc) { } +#endif + } void compiler_mode_by_environ(aflcc_state_t *aflcc) { @@ -660,14 +675,22 @@ void compiler_mode_by_environ(aflcc_state_t *aflcc) { aflcc->compiler_mode = GCC_PLUGIN; +#if defined(__x86_64__) + } else if (strcasecmp(ptr, "GCC") == 0) { aflcc->compiler_mode = GCC; +#endif + +#if defined(__x86_64__) + } else if (strcasecmp(ptr, "CLANG") == 0) { aflcc->compiler_mode = CLANG; +#endif + } else FATAL("Unknown AFL_CC_COMPILER mode: %s\n", ptr); @@ -751,14 +774,22 @@ void compiler_mode_by_cmdline(aflcc_state_t *aflcc, int argc, char **argv) { aflcc->compiler_mode = GCC_PLUGIN; +#if defined(__x86_64__) + } else if (strcasecmp(ptr, "GCC") == 0) { aflcc->compiler_mode = GCC; +#endif + +#if defined(__x86_64__) + } else if (strncasecmp(ptr, "CLANG", 5) == 0) { aflcc->compiler_mode = CLANG; +#endif + } else FATAL("Unknown --afl-... compiler mode: %s\n", argv[i]); @@ -929,6 +960,7 @@ static void instrument_mode_new_environ(aflcc_state_t *aflcc) { } +#if defined(__x86_64__) if (strcasecmp(ptr2, "gcc") == 0) { if (!aflcc->instrument_mode || aflcc->instrument_mode == INSTRUMENT_GCC) @@ -943,6 +975,9 @@ static void instrument_mode_new_environ(aflcc_state_t *aflcc) { } +#endif + +#if defined(__x86_64__) if (strcasecmp(ptr2, "clang") == 0) { if (!aflcc->instrument_mode || aflcc->instrument_mode == INSTRUMENT_CLANG) @@ -957,6 +992,8 @@ static void instrument_mode_new_environ(aflcc_state_t *aflcc) { } +#endif + if (strncasecmp(ptr2, "ctx-", strlen("ctx-")) == 0 || strncasecmp(ptr2, "kctx-", strlen("c-ctx-")) == 0 || strncasecmp(ptr2, "k-ctx-", strlen("k-ctx-")) == 0) { @@ -1130,12 +1167,9 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) { else if (aflcc->have_gcc_plugin) aflcc->compiler_mode = GCC_PLUGIN; else if (aflcc->have_gcc) -#ifdef __APPLE__ - // on OSX clang masquerades as GCC - aflcc->compiler_mode = CLANG; -#else aflcc->compiler_mode = GCC; -#endif + else if (aflcc->have_clang) + aflcc->compiler_mode = CLANG; else if (aflcc->have_lto) aflcc->compiler_mode = LTO; else @@ -1143,6 +1177,38 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) { } + switch (aflcc->compiler_mode) { + + case GCC: + if (!aflcc->have_gcc) FATAL("afl-gcc not available on your platform!"); + break; + case CLANG: + if (!aflcc->have_clang) + FATAL("afl-clang not available on your platform!"); + break; + case LLVM: + if (!aflcc->have_llvm) + FATAL( + "LLVM mode is not available, please install LLVM 13+ and recompile " + "AFL++"); + break; + case GCC_PLUGIN: + if (!aflcc->have_gcc_plugin) + FATAL( + "GCC_PLUGIN mode is not available, install gcc plugin support and " + "recompile AFL++"); + break; + case LTO: + if (!aflcc->have_lto) + FATAL( + "LTO mode is not available, please install LLVM 13+ and lld of the " + "same version and recompile AFL++"); + break; + default: + FATAL("no compiler mode available"); + + } + if (aflcc->compiler_mode == GCC) { aflcc->instrument_mode = INSTRUMENT_GCC; } if (aflcc->compiler_mode == CLANG) { @@ -1217,7 +1283,7 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) { aflcc->instrument_mode = INSTRUMENT_PCGUARD; #else - aflcc->instrument_mode = INSTRUMENT_AFL; + aflcc->instrument_mode = INSTRUMENT_AFL; #endif } @@ -1491,8 +1557,8 @@ void add_defs_persistent_mode(aflcc_state_t *aflcc) { "__attribute__((visibility(\"default\"))) " "int _L(unsigned int) __asm__(\"___afl_persistent_loop\"); " #else - "__attribute__((visibility(\"default\"))) " - "int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); " + "__attribute__((visibility(\"default\"))) " + "int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); " #endif /* ^__APPLE__ */ // if afl is connected, we run _A times, else once. "_L(__afl_connected ? _A : 1); })"); @@ -1507,8 +1573,8 @@ void add_defs_persistent_mode(aflcc_state_t *aflcc) { "__attribute__((visibility(\"default\"))) " "void _I(void) __asm__(\"___afl_manual_init\"); " #else - "__attribute__((visibility(\"default\"))) " - "void _I(void) __asm__(\"__afl_manual_init\"); " + "__attribute__((visibility(\"default\"))) " + "void _I(void) __asm__(\"__afl_manual_init\"); " #endif /* ^__APPLE__ */ "_I(); } while (0)"); @@ -1618,8 +1684,6 @@ static u8 fsanitize_fuzzer_comma(char *string) { } while (!ende); strcpy(string, new); - // fprintf(stderr, "string: %s\n", string); - // fprintf(stderr, "new: %s\n", new); ck_free(tmp); ck_free(new); @@ -1824,12 +1888,12 @@ void add_native_pcguard(aflcc_state_t *aflcc) { FATAL("pcguard instrumentation with pc-table requires LLVM 6.0.1+"); #else #if LLVM_MAJOR == 0 - WARNF( - "pcguard instrumentation with pc-table requires LLVM 6.0.1+" - " otherwise the compiler will fail"); + WARNF( + "pcguard instrumentation with pc-table requires LLVM 6.0.1+" + " otherwise the compiler will fail"); #endif - insert_param(aflcc, - "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table"); + insert_param(aflcc, + "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table"); #endif } else { @@ -1838,11 +1902,11 @@ void add_native_pcguard(aflcc_state_t *aflcc) { FATAL("pcguard instrumentation requires LLVM 4.0.1+"); #else #if LLVM_MAJOR == 0 - WARNF( - "pcguard instrumentation requires LLVM 4.0.1+" - " otherwise the compiler will fail"); + WARNF( + "pcguard instrumentation requires LLVM 4.0.1+" + " otherwise the compiler will fail"); #endif - insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); + insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); #endif } @@ -1884,16 +1948,16 @@ void add_optimized_pcguard(aflcc_state_t *aflcc) { #else // LLVM_MAJOR < 13 #if LLVM_MAJOR >= 4 - if (!be_quiet) - SAYF( - "Using unoptimized trace-pc-guard, upgrade to LLVM 13+ for " - "enhanced version.\n"); - insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); - aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; + if (!be_quiet) + SAYF( + "Using unoptimized trace-pc-guard, upgrade to LLVM 13+ for " + "enhanced version.\n"); + insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; #else - FATAL("pcguard instrumentation requires LLVM 4.0.1+"); + FATAL("pcguard instrumentation requires LLVM 4.0.1+"); #endif #endif @@ -2097,7 +2161,7 @@ void add_lto_linker(aflcc_state_t *aflcc) { #if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 12 insert_param(aflcc, alloc_printf("--ld-path=%s", ld_path)); #else - insert_param(aflcc, alloc_printf("-fuse-ld=%s", ld_path)); + insert_param(aflcc, alloc_printf("-fuse-ld=%s", ld_path)); #endif free(ld_path); @@ -2110,11 +2174,11 @@ void add_lto_passes(aflcc_state_t *aflcc) { insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,--load-pass-plugin=%s", 0); #elif defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 13 - insert_param(aflcc, "-Wl,--lto-legacy-pass-manager"); - insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,-mllvm=-load=%s", 0); + insert_param(aflcc, "-Wl,--lto-legacy-pass-manager"); + insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,-mllvm=-load=%s", 0); #else - insert_param(aflcc, "-fno-experimental-new-pass-manager"); - insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,-mllvm=-load=%s", 0); + insert_param(aflcc, "-fno-experimental-new-pass-manager"); + insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,-mllvm=-load=%s", 0); #endif insert_param(aflcc, "-Wl,--allow-multiple-definition"); @@ -2503,7 +2567,11 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { aflcc->compiler_mode == LTO ? " [SELECTED]" : "", aflcc->have_gcc_plugin ? "AVAILABLE" : "unavailable!", aflcc->compiler_mode == GCC_PLUGIN ? " [SELECTED]" : "", - aflcc->have_gcc ? "AVAILABLE" : "unavailable!", + aflcc->have_gcc && aflcc->have_clang + ? "AVAILABLE" + : (aflcc->have_gcc + ? "GCC ONLY " + : (aflcc->have_clang ? "CLANG ONLY" : "unavailable!")), (aflcc->compiler_mode == GCC || aflcc->compiler_mode == CLANG) ? " [SELECTED]" : ""); @@ -2708,7 +2776,7 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { SAYF("Compiled with shm_open support (adds -lrt when linking).\n"); #endif #else - SAYF("Compiled with shmat support.\n"); + SAYF("Compiled with shmat support.\n"); #endif SAYF("\n"); -- cgit v1.2.3 From 523ce154c3cda758f234cadf76c73663b21e105f Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 18 Jan 2024 11:22:06 +0100 Subject: disable aslr on apple --- src/afl-fuzz.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 17949fd7..2d5787e8 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1812,6 +1812,10 @@ int main(int argc, char **argv_orig, char **envp) { check_cpu_governor(afl); #endif + #ifdef __APPLE__ + setenv("DYLD_NO_PIE", "1", 0); + #endif + if (getenv("LD_PRELOAD")) { WARNF( -- cgit v1.2.3 From e731a1c1ab48dbc9a70a9e5680f00aab307abfa1 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 18 Jan 2024 12:01:26 +0100 Subject: fix for arm64 --- src/afl-cc.c | 58 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 3377b42f..192c5423 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -629,10 +629,10 @@ void compiler_mode_by_callname(aflcc_state_t *aflcc) { aflcc->compiler_mode = CLANG; - } - #endif + } + } void compiler_mode_by_environ(aflcc_state_t *aflcc) { @@ -1283,7 +1283,7 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) { aflcc->instrument_mode = INSTRUMENT_PCGUARD; #else - aflcc->instrument_mode = INSTRUMENT_AFL; + aflcc->instrument_mode = INSTRUMENT_AFL; #endif } @@ -1557,8 +1557,8 @@ void add_defs_persistent_mode(aflcc_state_t *aflcc) { "__attribute__((visibility(\"default\"))) " "int _L(unsigned int) __asm__(\"___afl_persistent_loop\"); " #else - "__attribute__((visibility(\"default\"))) " - "int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); " + "__attribute__((visibility(\"default\"))) " + "int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); " #endif /* ^__APPLE__ */ // if afl is connected, we run _A times, else once. "_L(__afl_connected ? _A : 1); })"); @@ -1573,8 +1573,8 @@ void add_defs_persistent_mode(aflcc_state_t *aflcc) { "__attribute__((visibility(\"default\"))) " "void _I(void) __asm__(\"___afl_manual_init\"); " #else - "__attribute__((visibility(\"default\"))) " - "void _I(void) __asm__(\"__afl_manual_init\"); " + "__attribute__((visibility(\"default\"))) " + "void _I(void) __asm__(\"__afl_manual_init\"); " #endif /* ^__APPLE__ */ "_I(); } while (0)"); @@ -1888,12 +1888,12 @@ void add_native_pcguard(aflcc_state_t *aflcc) { FATAL("pcguard instrumentation with pc-table requires LLVM 6.0.1+"); #else #if LLVM_MAJOR == 0 - WARNF( - "pcguard instrumentation with pc-table requires LLVM 6.0.1+" - " otherwise the compiler will fail"); + WARNF( + "pcguard instrumentation with pc-table requires LLVM 6.0.1+" + " otherwise the compiler will fail"); #endif - insert_param(aflcc, - "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table"); + insert_param(aflcc, + "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table"); #endif } else { @@ -1902,11 +1902,11 @@ void add_native_pcguard(aflcc_state_t *aflcc) { FATAL("pcguard instrumentation requires LLVM 4.0.1+"); #else #if LLVM_MAJOR == 0 - WARNF( - "pcguard instrumentation requires LLVM 4.0.1+" - " otherwise the compiler will fail"); + WARNF( + "pcguard instrumentation requires LLVM 4.0.1+" + " otherwise the compiler will fail"); #endif - insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); + insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); #endif } @@ -1948,16 +1948,16 @@ void add_optimized_pcguard(aflcc_state_t *aflcc) { #else // LLVM_MAJOR < 13 #if LLVM_MAJOR >= 4 - if (!be_quiet) - SAYF( - "Using unoptimized trace-pc-guard, upgrade to LLVM 13+ for " - "enhanced version.\n"); - insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); - aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; + if (!be_quiet) + SAYF( + "Using unoptimized trace-pc-guard, upgrade to LLVM 13+ for " + "enhanced version.\n"); + insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; #else - FATAL("pcguard instrumentation requires LLVM 4.0.1+"); + FATAL("pcguard instrumentation requires LLVM 4.0.1+"); #endif #endif @@ -2161,7 +2161,7 @@ void add_lto_linker(aflcc_state_t *aflcc) { #if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 12 insert_param(aflcc, alloc_printf("--ld-path=%s", ld_path)); #else - insert_param(aflcc, alloc_printf("-fuse-ld=%s", ld_path)); + insert_param(aflcc, alloc_printf("-fuse-ld=%s", ld_path)); #endif free(ld_path); @@ -2174,11 +2174,11 @@ void add_lto_passes(aflcc_state_t *aflcc) { insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,--load-pass-plugin=%s", 0); #elif defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 13 - insert_param(aflcc, "-Wl,--lto-legacy-pass-manager"); - insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,-mllvm=-load=%s", 0); + insert_param(aflcc, "-Wl,--lto-legacy-pass-manager"); + insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,-mllvm=-load=%s", 0); #else - insert_param(aflcc, "-fno-experimental-new-pass-manager"); - insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,-mllvm=-load=%s", 0); + insert_param(aflcc, "-fno-experimental-new-pass-manager"); + insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,-mllvm=-load=%s", 0); #endif insert_param(aflcc, "-Wl,--allow-multiple-definition"); @@ -2776,7 +2776,7 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { SAYF("Compiled with shm_open support (adds -lrt when linking).\n"); #endif #else - SAYF("Compiled with shmat support.\n"); + SAYF("Compiled with shmat support.\n"); #endif SAYF("\n"); -- cgit v1.2.3 From 0c054f520eda67b7bb15f95ca58c028e9b68131f Mon Sep 17 00:00:00 2001 From: van Hauser Date: Thu, 18 Jan 2024 16:17:48 +0100 Subject: push to stable (#1960) * Output afl-clang-fast stuffs only if necessary (#1912) * afl-cc header * afl-cc common declarations - Add afl-cc-state.c - Strip includes, find_object, debug/be_quiet/have_*/callname setting from afl-cc.c - Use debugf_args in main - Modify execvp stuffs to fit new aflcc struct * afl-cc show usage * afl-cc mode selecting 1. compiler_mode by callname in argv[0] 2. compiler_mode by env "AFL_CC_COMPILER" 3. compiler_mode/instrument_mode by command line options "--afl-..." 4. instrument_mode/compiler_mode by various env vars including "AFL_LLVM_INSTRUMENT" 5. final checking steps 6. print "... - mode: %s-%s\n" 7. determine real argv[0] according to compiler_mode * afl-cc macro defs * afl-cc linking behaviors * afl-cc fsanitize behaviors * afl-cc misc * afl-cc body update * afl-cc all-in-one formated with custom-format.py * nits --------- Co-authored-by: vanhauser-thc * changelog * update grammar mutator * lto llvm 12+ * docs(custom_mutators): fix missing ':' (#1953) * Fix broken LTO mode and response file support (#1948) * Strip `-Wl,-no-undefined` during compilation (#1952) Make the compiler wrapper stripping `-Wl,-no-undefined` in addition to `-Wl,--no-undefined`. Both versions of the flag are accepted by clang and, therefore, used by building systems in the wild (e.g., samba will not build without this fix). * Remove dead code in write_to_testcase (#1955) The custom_mutators_count check in if case is duplicate with if condition. The else case is custom_mutators_count == 0, neither custom_mutator_list iteration nor sent check needed. Signed-off-by: Xeonacid * update qemuafl * WIP: Add ability to generate drcov trace using QEMU backend (#1956) * Document new drcov QEMU plugin * Add link to lightkeeper for QEMU drcov file loading --------- Co-authored-by: Jean-Romain Garnier * code format * changelog * sleep on uid != 0 afl-system-config * fix segv about skip_next, warn on unsupported cases of linking options (#1958) * todos * ensure afl-cc only allows available compiler modes * update grammar mutator * disable aslr on apple * fix for arm64 --------- Signed-off-by: Xeonacid Co-authored-by: Sonic <50692172+SonicStark@users.noreply.github.com> Co-authored-by: Xeonacid Co-authored-by: Nils Bars Co-authored-by: Jean-Romain Garnier <7504819+JRomainG@users.noreply.github.com> Co-authored-by: Jean-Romain Garnier --- src/afl-cc.c | 3378 ++++++++++++++++++++++++++++++---------------------- src/afl-fuzz-run.c | 41 +- src/afl-fuzz.c | 4 + 3 files changed, 1976 insertions(+), 1447 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 54c733c9..192c5423 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -47,23 +47,22 @@ #define LLVM_MINOR 0 #endif -static u8 *obj_path; /* Path to runtime libraries */ -static u8 **cc_params; /* Parameters passed to the real CC */ -static u32 cc_par_cnt = 1; /* Param count, including argv0 */ -static u8 clang_mode; /* Invoked as afl-clang*? */ -static u8 llvm_fullpath[PATH_MAX]; -static u8 instrument_mode, instrument_opt_mode, ngram_size, ctx_k, lto_mode; -static u8 compiler_mode, plusplus_mode, have_instr_env = 0, need_aflpplib = 0; -static u8 have_gcc, have_llvm, have_gcc_plugin, have_lto, have_instr_list = 0; -static u8 *lto_flag = AFL_CLANG_FLTO, *argvnull; -static u8 debug; -static u8 cwd[4096]; -static u8 cmplog_mode; -u8 use_stdin; /* dummy */ -static int passthrough; -// static u8 *march_opt = CFLAGS_OPT; - -enum { +#ifndef MAX_PARAMS_NUM + #define MAX_PARAMS_NUM 2048 +#endif + +/* Global declarations */ + +typedef enum { + + PARAM_MISS, // not matched + PARAM_SCAN, // scan only + PARAM_KEEP, // kept as-is + PARAM_DROP, // ignored + +} param_st; + +typedef enum { INSTRUMENT_DEFAULT = 0, INSTRUMENT_CLASSIC = 1, @@ -80,7 +79,20 @@ enum { INSTRUMENT_OPT_CTX_K = 64, INSTRUMENT_OPT_CODECOV = 128, -}; +} instrument_mode_id; + +typedef enum { + + UNSET = 0, + LTO = 1, + LLVM = 2, + GCC_PLUGIN = 3, + GCC = 4, + CLANG = 5 + +} compiler_mode_id; + +static u8 cwd[4096]; char instrument_mode_string[18][18] = { @@ -105,17 +117,6 @@ char instrument_mode_string[18][18] = { }; -enum { - - UNSET = 0, - LTO = 1, - LLVM = 2, - GCC_PLUGIN = 3, - GCC = 4, - CLANG = 5 - -}; - char compiler_mode_string[7][12] = { "AUTOSELECT", "LLVM-LTO", "LLVM", "GCC_PLUGIN", @@ -123,6 +124,18 @@ char compiler_mode_string[7][12] = { }; +u8 *instrument_mode_2str(instrument_mode_id i) { + + return instrument_mode_string[i]; + +} + +u8 *compiler_mode_2str(compiler_mode_id i) { + + return compiler_mode_string[i]; + +} + u8 *getthecwd() { if (getcwd(cwd, sizeof(cwd)) == NULL) { @@ -136,26 +149,228 @@ u8 *getthecwd() { } -/* Try to find a specific runtime we need, returns NULL on fail. */ +typedef struct aflcc_state { + + u8 **cc_params; /* Parameters passed to the real CC */ + u32 cc_par_cnt; /* Param count, including argv0 */ + + u8 *argv0; /* Original argv0 (by strdup) */ + u8 *callname; /* Executable file argv0 indicated */ + + u8 debug; + + u8 compiler_mode, plusplus_mode, lto_mode; + + u8 *lto_flag; + + u8 instrument_mode, instrument_opt_mode, ngram_size, ctx_k; + + u8 cmplog_mode; + + u8 have_instr_env, have_gcc, have_clang, have_llvm, have_gcc_plugin, have_lto, + have_optimized_pcguard, have_instr_list; + + u8 fortify_set, asan_set, x_set, bit_mode, preprocessor_only, have_unroll, + have_o, have_pic, have_c, shared_linking, partial_linking, non_dash; + + // u8 *march_opt; + u8 need_aflpplib; + int passthrough; + + u8 use_stdin; /* dummy */ + u8 *argvnull; /* dummy */ + +} aflcc_state_t; + +void aflcc_state_init(aflcc_state_t *, u8 *argv0); + +/* Try to find a specific runtime we need, the path to obj would be + allocated and returned. Otherwise it returns NULL on fail. */ +u8 *find_object(aflcc_state_t *, u8 *obj); + +void find_built_deps(aflcc_state_t *); + +static inline void limit_params(aflcc_state_t *aflcc, u32 add) { + + if (aflcc->cc_par_cnt + add >= MAX_PARAMS_NUM) + FATAL("Too many command line parameters, please increase MAX_PARAMS_NUM."); + +} + +static inline void insert_param(aflcc_state_t *aflcc, u8 *param) { + + aflcc->cc_params[aflcc->cc_par_cnt++] = param; + +} + +static inline void insert_object(aflcc_state_t *aflcc, u8 *obj, u8 *fmt, + u8 *msg) { + + u8 *_obj_path = find_object(aflcc, obj); + if (!_obj_path) { + + if (msg) + FATAL("%s", msg); + else + FATAL("Unable to find '%s'", obj); + + } else { + + if (fmt) { + + u8 *_obj_path_fmt = alloc_printf(fmt, _obj_path); + ck_free(_obj_path); + aflcc->cc_params[aflcc->cc_par_cnt++] = _obj_path_fmt; + + } else { + + aflcc->cc_params[aflcc->cc_par_cnt++] = _obj_path; + + } + + } + +} + +static inline void load_llvm_pass(aflcc_state_t *aflcc, u8 *pass) { + +#if LLVM_MAJOR >= 11 /* use new pass manager */ + #if LLVM_MAJOR < 16 + insert_param(aflcc, "-fexperimental-new-pass-manager"); + #endif + insert_object(aflcc, pass, "-fpass-plugin=%s", 0); +#else + insert_param(aflcc, "-Xclang"); + insert_param(aflcc, "-load"); + insert_param(aflcc, "-Xclang"); + insert_object(aflcc, pass, 0, 0); +#endif + +} + +static inline void debugf_args(int argc, char **argv) { + + DEBUGF("cd '%s';", getthecwd()); + for (int i = 0; i < argc; i++) + SAYF(" '%s'", argv[i]); + SAYF("\n"); + fflush(stdout); + fflush(stderr); + +} + +void compiler_mode_by_callname(aflcc_state_t *); +void compiler_mode_by_environ(aflcc_state_t *); +void compiler_mode_by_cmdline(aflcc_state_t *, int argc, char **argv); +void instrument_mode_by_environ(aflcc_state_t *); +void mode_final_checkout(aflcc_state_t *, int argc, char **argv); +void mode_notification(aflcc_state_t *); + +void add_real_argv0(aflcc_state_t *); + +void add_defs_common(aflcc_state_t *); +void add_defs_selective_instr(aflcc_state_t *); +void add_defs_persistent_mode(aflcc_state_t *); +void add_defs_fortify(aflcc_state_t *, u8); +void add_defs_lsan_ctrl(aflcc_state_t *); + +param_st parse_fsanitize(aflcc_state_t *, u8 *, u8); +void add_sanitizers(aflcc_state_t *, char **envp); +void add_optimized_pcguard(aflcc_state_t *); +void add_native_pcguard(aflcc_state_t *); + +void add_assembler(aflcc_state_t *); +void add_gcc_plugin(aflcc_state_t *); + +param_st parse_misc_params(aflcc_state_t *, u8 *, u8); +void add_misc_params(aflcc_state_t *); + +param_st parse_linking_params(aflcc_state_t *, u8 *, u8, u8 *skip_next, + char **argv); + +void add_lto_linker(aflcc_state_t *); +void add_lto_passes(aflcc_state_t *); +void add_runtime(aflcc_state_t *); + +/* Working state */ + +void aflcc_state_init(aflcc_state_t *aflcc, u8 *argv0) { + + // Default NULL/0 is a good start + memset(aflcc, 0, sizeof(aflcc_state_t)); + + aflcc->cc_params = ck_alloc(MAX_PARAMS_NUM * sizeof(u8 *)); + aflcc->cc_par_cnt = 1; + + aflcc->lto_flag = AFL_CLANG_FLTO; + + // aflcc->march_opt = CFLAGS_OPT; + + /* callname & if C++ mode */ + + aflcc->argv0 = ck_strdup(argv0); + + char *cname = NULL; + + if ((cname = strrchr(aflcc->argv0, '/')) != NULL) { + + cname++; + + } else { + + cname = aflcc->argv0; + + } + + aflcc->callname = cname; + + if (strlen(cname) > 2 && (strncmp(cname + strlen(cname) - 2, "++", 2) == 0 || + strstr(cname, "-g++") != NULL)) { + + aflcc->plusplus_mode = 1; + + } + + /* debug */ + + if (getenv("AFL_DEBUG")) { + + aflcc->debug = 1; + if (strcmp(getenv("AFL_DEBUG"), "0") == 0) unsetenv("AFL_DEBUG"); + + } else if (getenv("AFL_QUIET")) { + + be_quiet = 1; + + } + + if ((getenv("AFL_PASSTHROUGH") || getenv("AFL_NOOPT")) && (!aflcc->debug)) { + + be_quiet = 1; + + } + +} /* in find_object() we look here: - 1. if obj_path is already set we look there first - 2. then we check the $AFL_PATH environment variable location if set - 3. next we check argv[0] if it has path information and use it + 1. firstly we check the $AFL_PATH environment variable location if set + 2. next we check argv[0] if it has path information and use it a) we also check ../lib/afl - 4. if 3. failed we check /proc (only Linux, Android, NetBSD, DragonFly, and + 3. if 2. failed we check /proc (only Linux, Android, NetBSD, DragonFly, and FreeBSD with procfs) a) and check here in ../lib/afl too - 5. we look into the AFL_PATH define (usually /usr/local/lib/afl) - 6. we finally try the current directory + 4. we look into the AFL_PATH define (usually /usr/local/lib/afl) + 5. we finally try the current directory if all these attempts fail - we return NULL and the caller has to decide - what to do. + what to do. Otherwise the path to obj would be allocated and returned. */ -static u8 *find_object(u8 *obj, u8 *argv0) { +u8 *find_object(aflcc_state_t *aflcc, u8 *obj) { + + u8 *argv0 = aflcc->argv0; u8 *afl_path = getenv("AFL_PATH"); u8 *slash = NULL, *tmp; @@ -164,14 +379,9 @@ static u8 *find_object(u8 *obj, u8 *argv0) { tmp = alloc_printf("%s/%s", afl_path, obj); - if (debug) DEBUGF("Trying %s\n", tmp); - - if (!access(tmp, R_OK)) { - - obj_path = afl_path; - return tmp; + if (aflcc->debug) DEBUGF("Trying %s\n", tmp); - } + if (!access(tmp, R_OK)) { return tmp; } ck_free(tmp); @@ -190,11 +400,11 @@ static u8 *find_object(u8 *obj, u8 *argv0) { tmp = alloc_printf("%s/%s", dir, obj); - if (debug) DEBUGF("Trying %s\n", tmp); + if (aflcc->debug) DEBUGF("Trying %s\n", tmp); if (!access(tmp, R_OK)) { - obj_path = dir; + ck_free(dir); return tmp; } @@ -202,12 +412,10 @@ static u8 *find_object(u8 *obj, u8 *argv0) { ck_free(tmp); tmp = alloc_printf("%s/../lib/afl/%s", dir, obj); - if (debug) DEBUGF("Trying %s\n", tmp); + if (aflcc->debug) DEBUGF("Trying %s\n", tmp); if (!access(tmp, R_OK)) { - u8 *dir2 = alloc_printf("%s/../lib/afl", dir); - obj_path = dir2; ck_free(dir); return tmp; @@ -247,26 +455,16 @@ static u8 *find_object(u8 *obj, u8 *argv0) { *slash = 0; tmp = alloc_printf("%s/%s", exepath, obj); - if (!access(tmp, R_OK)) { - - u8 *dir = alloc_printf("%s", exepath); - obj_path = dir; - return tmp; - - } + if (!access(tmp, R_OK)) { return tmp; } ck_free(tmp); tmp = alloc_printf("%s/../lib/afl/%s", exepath, obj); - if (debug) DEBUGF("Trying %s\n", tmp); - - if (!access(tmp, R_OK)) { + if (aflcc->debug) DEBUGF("Trying %s\n", tmp); - u8 *dir = alloc_printf("%s/../lib/afl/", exepath); - obj_path = dir; - return tmp; + if (!access(tmp, R_OK)) { return tmp; } - } + ck_free(tmp); } @@ -283,1843 +481,2036 @@ static u8 *find_object(u8 *obj, u8 *argv0) { tmp = alloc_printf("%s/%s", AFL_PATH, obj); - if (debug) DEBUGF("Trying %s\n", tmp); + if (aflcc->debug) DEBUGF("Trying %s\n", tmp); - if (!access(tmp, R_OK)) { - - obj_path = AFL_PATH; - return tmp; - - } + if (!access(tmp, R_OK)) { return tmp; } ck_free(tmp); - tmp = alloc_printf("./%s", obj); - if (debug) DEBUGF("Trying %s\n", tmp); + if (aflcc->debug) DEBUGF("Trying %s\n", tmp); - if (!access(tmp, R_OK)) { - - obj_path = "."; - return tmp; - - } + if (!access(tmp, R_OK)) { return tmp; } ck_free(tmp); - if (debug) DEBUGF("Trying ... giving up\n"); + if (aflcc->debug) DEBUGF("Trying ... giving up\n"); return NULL; } -void parse_fsanitize(char *string) { +void find_built_deps(aflcc_state_t *aflcc) { - char *p, *ptr = string + strlen("-fsanitize="); - char *new = malloc(strlen(string) + 1); - char *tmp = malloc(strlen(ptr) + 1); - u32 count = 0, len, ende = 0; + char *ptr = NULL; - if (!new || !tmp) { FATAL("could not acquire memory"); } - strcpy(new, "-fsanitize="); +#if defined(__x86_64__) + if ((ptr = find_object(aflcc, "as")) != NULL) { - do { + #ifndef __APPLE__ + // on OSX clang masquerades as GCC + aflcc->have_gcc = 1; + #endif + aflcc->have_clang = 1; + ck_free(ptr); - p = strchr(ptr, ','); - if (!p) { + } - p = ptr + strlen(ptr) + 1; - ende = 1; +#endif - } + if ((ptr = find_object(aflcc, "SanitizerCoveragePCGUARD.so")) != NULL) { - len = p - ptr; - if (len) { + aflcc->have_optimized_pcguard = 1; + ck_free(ptr); - strncpy(tmp, ptr, len); - tmp[len] = 0; - // fprintf(stderr, "Found: %s\n", tmp); - ptr += len + 1; - if (*tmp) { + } - u32 copy = 1; - if (!strcmp(tmp, "fuzzer")) { +#if (LLVM_MAJOR >= 3) - need_aflpplib = 1; - copy = 0; + if ((ptr = find_object(aflcc, "SanitizerCoverageLTO.so")) != NULL) { - } else if (!strncmp(tmp, "fuzzer", 6)) { + aflcc->have_lto = 1; + ck_free(ptr); - copy = 0; + } - } + if ((ptr = find_object(aflcc, "cmplog-routines-pass.so")) != NULL) { - if (copy) { + aflcc->have_llvm = 1; + ck_free(ptr); - if (count) { strcat(new, ","); } - strcat(new, tmp); - ++count; + } - } +#endif - } +#ifdef __ANDROID__ + aflcc->have_llvm = 1; +#endif - } else { + if ((ptr = find_object(aflcc, "afl-gcc-pass.so")) != NULL) { - ptr++; /*fprintf(stderr, "NO!\n"); */ + aflcc->have_gcc_plugin = 1; + ck_free(ptr); - } + } - } while (!ende); +#if !defined(__ANDROID__) && !defined(ANDROID) + ptr = find_object(aflcc, "afl-compiler-rt.o"); - strcpy(string, new); - // fprintf(stderr, "string: %s\n", string); - // fprintf(stderr, "new: %s\n", new); + if (!ptr) { -} + FATAL( + "Unable to find 'afl-compiler-rt.o'. Please set the AFL_PATH " + "environment variable."); -static u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0, - shared_linking = 0, preprocessor_only = 0, have_unroll = 0, - have_o = 0, have_pic = 0, have_c = 0, partial_linking = 0, - non_dash = 0; + } -#ifndef MAX_PARAMS_NUM - #define MAX_PARAMS_NUM 2048 + if (aflcc->debug) { DEBUGF("rt=%s\n", ptr); } + + ck_free(ptr); #endif -static void process_params(u32 argc, char **argv) { +} - if (cc_par_cnt + argc >= MAX_PARAMS_NUM) { +/* compiler_mode & instrument_mode selecting */ - FATAL("Too many command line parameters, please increase MAX_PARAMS_NUM."); +void compiler_mode_by_callname(aflcc_state_t *aflcc) { - } + if (strncmp(aflcc->callname, "afl-clang-fast", 14) == 0) { - // reset - have_instr_list = 0; - have_c = 0; + /* afl-clang-fast is always created there by makefile + just like afl-clang, burdened with special purposes: + - If llvm-config is not available (i.e. LLVM_MAJOR is 0), + or too old, it falls back to LLVM-NATIVE mode and let + the actual compiler complain if doesn't work. + - Otherwise try default llvm instruments except LTO. + */ +#if (LLVM_MAJOR >= 3) + aflcc->compiler_mode = LLVM; +#else + aflcc->compiler_mode = CLANG; +#endif - if (lto_mode && argc > 1) { + } else - u32 idx; - for (idx = 1; idx < argc; idx++) { +#if (LLVM_MAJOR >= 3) - if (!strncasecmp(argv[idx], "-fpic", 5)) { have_pic = 1; } + if (strncmp(aflcc->callname, "afl-clang-lto", 13) == 0 || - } + strncmp(aflcc->callname, "afl-lto", 7) == 0) { - } + aflcc->compiler_mode = LTO; - // for (u32 x = 0; x < argc; ++x) fprintf(stderr, "[%u] %s\n", x, argv[x]); + } else - /* Process the argument list. */ +#endif - u8 skip_next = 0; - while (--argc) { + if (strncmp(aflcc->callname, "afl-gcc-fast", 12) == 0 || - u8 *cur = *(++argv); + strncmp(aflcc->callname, "afl-g++-fast", 12) == 0) { - if (skip_next) { + aflcc->compiler_mode = GCC_PLUGIN; - skip_next = 0; - continue; +#if defined(__x86_64__) - } + } else if (strncmp(aflcc->callname, "afl-gcc", 7) == 0 || - if (cur[0] != '-') { non_dash = 1; } - if (!strncmp(cur, "--afl", 5)) continue; + strncmp(aflcc->callname, "afl-g++", 7) == 0) { - if (lto_mode && !strncmp(cur, "-flto=thin", 10)) { + aflcc->compiler_mode = GCC; - FATAL( - "afl-clang-lto cannot work with -flto=thin. Switch to -flto=full or " - "use afl-clang-fast!"); +#endif - } +#if defined(__x86_64__) - if (lto_mode && !strncmp(cur, "-fuse-ld=", 9)) continue; - if (lto_mode && !strncmp(cur, "--ld-path=", 10)) continue; - if (!strncmp(cur, "-fno-unroll", 11)) continue; - if (strstr(cur, "afl-compiler-rt") || strstr(cur, "afl-llvm-rt")) continue; - if (!strcmp(cur, "-Wl,-z,defs") || !strcmp(cur, "-Wl,--no-undefined") || - !strcmp(cur, "--no-undefined")) { + } else if (strcmp(aflcc->callname, "afl-clang") == 0 || - continue; + strcmp(aflcc->callname, "afl-clang++") == 0) { - } + aflcc->compiler_mode = CLANG; + +#endif - if (compiler_mode == GCC_PLUGIN && !strcmp(cur, "-pipe")) { continue; } + } - if (!strcmp(cur, "-z") || !strcmp(cur, "-Wl,-z")) { +} - u8 *param = *(argv + 1); - if (!strcmp(param, "defs") || !strcmp(param, "-Wl,defs")) { +void compiler_mode_by_environ(aflcc_state_t *aflcc) { - skip_next = 1; - continue; + if (getenv("AFL_PASSTHROUGH") || getenv("AFL_NOOPT")) { - } + aflcc->passthrough = 1; - } + } - if ((compiler_mode == GCC || compiler_mode == GCC_PLUGIN) && - !strncmp(cur, "-stdlib=", 8)) { + char *ptr = getenv("AFL_CC_COMPILER"); - if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); } - continue; + if (!ptr) { return; } - } + if (aflcc->compiler_mode) { - if (!strncmp(cur, "-fsanitize-coverage-", 20) && strstr(cur, "list=")) { + if (!be_quiet) { - have_instr_list = 1; + WARNF( + "\"AFL_CC_COMPILER\" is set but a specific compiler was already " + "selected by command line parameter or symlink, ignoring the " + "environment variable!"); } - if (!strncmp(cur, "-fsanitize=", strlen("-fsanitize=")) && - strchr(cur, ',')) { + } else { - parse_fsanitize(cur); - if (!cur || strlen(cur) <= strlen("-fsanitize=")) { continue; } + if (strncasecmp(ptr, "LTO", 3) == 0) { - } else if ((!strncmp(cur, "-fsanitize=fuzzer-", + aflcc->compiler_mode = LTO; - strlen("-fsanitize=fuzzer-")) || - !strncmp(cur, "-fsanitize-coverage", - strlen("-fsanitize-coverage"))) && - (strncmp(cur, "sanitize-coverage-allow", - strlen("sanitize-coverage-allow")) && - strncmp(cur, "sanitize-coverage-deny", - strlen("sanitize-coverage-deny")) && - instrument_mode != INSTRUMENT_LLVMNATIVE)) { + } else if (strncasecmp(ptr, "LLVM", 4) == 0) { - if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); } - continue; + aflcc->compiler_mode = LLVM; - } + } else if (strncasecmp(ptr, "GCC_P", 5) == 0 || - if (need_aflpplib || !strcmp(cur, "-fsanitize=fuzzer")) { + strncasecmp(ptr, "GCC-P", 5) == 0 || + strncasecmp(ptr, "GCCP", 4) == 0) { - u8 *afllib = find_object("libAFLDriver.a", argv[0]); + aflcc->compiler_mode = GCC_PLUGIN; - if (!be_quiet) { +#if defined(__x86_64__) - OKF("Found '-fsanitize=fuzzer', replacing with libAFLDriver.a"); + } else if (strcasecmp(ptr, "GCC") == 0) { - } + aflcc->compiler_mode = GCC; - if (!afllib) { +#endif - if (!be_quiet) { +#if defined(__x86_64__) - WARNF( - "Cannot find 'libAFLDriver.a' to replace '-fsanitize=fuzzer' in " - "the flags - this will fail!"); + } else if (strcasecmp(ptr, "CLANG") == 0) { - } + aflcc->compiler_mode = CLANG; - } else { - - cc_params[cc_par_cnt++] = afllib; - -#ifdef __APPLE__ - cc_params[cc_par_cnt++] = "-undefined"; - cc_params[cc_par_cnt++] = "dynamic_lookup"; #endif - } + } else - if (need_aflpplib) { + FATAL("Unknown AFL_CC_COMPILER mode: %s\n", ptr); - need_aflpplib = 0; + } - } else { +} - continue; +// If it can be inferred, instrument_mode would also be set +void compiler_mode_by_cmdline(aflcc_state_t *aflcc, int argc, char **argv) { - } + char *ptr = NULL; - } + for (int i = 1; i < argc; i++) { - if (!strcmp(cur, "-m32")) bit_mode = 32; - if (!strcmp(cur, "armv7a-linux-androideabi")) bit_mode = 32; - if (!strcmp(cur, "-m64")) bit_mode = 64; + if (strncmp(argv[i], "--afl", 5) == 0) { - if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory")) - asan_set = 1; + if (!strcmp(argv[i], "--afl_noopt") || !strcmp(argv[i], "--afl-noopt")) { - if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1; + aflcc->passthrough = 1; + argv[i] = "-g"; // we have to overwrite it, -g is always good + continue; - if (!strcmp(cur, "-x")) x_set = 1; - if (!strcmp(cur, "-E")) preprocessor_only = 1; - if (!strcmp(cur, "-shared")) shared_linking = 1; - if (!strcmp(cur, "-dynamiclib")) shared_linking = 1; - if (!strcmp(cur, "--target=wasm32-wasi")) passthrough = 1; - if (!strcmp(cur, "-Wl,-r")) partial_linking = 1; - if (!strcmp(cur, "-Wl,-i")) partial_linking = 1; - if (!strcmp(cur, "-Wl,--relocatable")) partial_linking = 1; - if (!strcmp(cur, "-r")) partial_linking = 1; - if (!strcmp(cur, "--relocatable")) partial_linking = 1; - if (!strcmp(cur, "-c")) have_c = 1; + } - if (!strncmp(cur, "-O", 2)) have_o = 1; - if (!strncmp(cur, "-funroll-loop", 13)) have_unroll = 1; + if (aflcc->compiler_mode && !be_quiet) { - if (*cur == '@') { + WARNF( + "--afl-... compiler mode supersedes the AFL_CC_COMPILER and " + "symlink compiler selection!"); - // response file support. - // we have two choices - move everything to the command line or - // rewrite the response files to temporary files and delete them - // afterwards. We choose the first for easiness. - // We do *not* support quotes in the rsp files to cope with spaces in - // filenames etc! If you need that then send a patch! - u8 *filename = cur + 1; - if (debug) { DEBUGF("response file=%s\n", filename); } - FILE *f = fopen(filename, "r"); - struct stat st; + } - // Check not found or empty? let the compiler complain if so. - if (!f || fstat(fileno(f), &st) < 0 || st.st_size < 1) { + ptr = argv[i]; + ptr += 5; + while (*ptr == '-') + ptr++; - cc_params[cc_par_cnt++] = cur; - continue; + if (strncasecmp(ptr, "LTO", 3) == 0) { - } + aflcc->compiler_mode = LTO; - u8 *tmpbuf = malloc(st.st_size + 2), *ptr; - char **args = malloc(sizeof(char *) * (st.st_size >> 1)); - int count = 1, cont = 0, cont_act = 0; + } else if (strncasecmp(ptr, "LLVM", 4) == 0) { - while (fgets(tmpbuf, st.st_size + 1, f)) { + aflcc->compiler_mode = LLVM; - ptr = tmpbuf; - // fprintf(stderr, "1: %s\n", ptr); - // no leading whitespace - while (isspace(*ptr)) { + } else if (strncasecmp(ptr, "PCGUARD", 7) == 0 || - ++ptr; - cont_act = 0; + strncasecmp(ptr, "PC-GUARD", 8) == 0) { - } + aflcc->compiler_mode = LLVM; + aflcc->instrument_mode = INSTRUMENT_PCGUARD; - // no comments, no empty lines - if (*ptr == '#' || *ptr == '\n' || !*ptr) { continue; } - // remove LF - if (ptr[strlen(ptr) - 1] == '\n') { ptr[strlen(ptr) - 1] = 0; } - // remove CR - if (*ptr && ptr[strlen(ptr) - 1] == '\r') { ptr[strlen(ptr) - 1] = 0; } - // handle \ at end of line - if (*ptr && ptr[strlen(ptr) - 1] == '\\') { + } else if (strcasecmp(ptr, "INSTRIM") == 0 || - cont = 1; - ptr[strlen(ptr) - 1] = 0; + strcasecmp(ptr, "CFG") == 0) { - } + FATAL( + "InsTrim instrumentation was removed. Use a modern LLVM and " + "PCGUARD (default in afl-cc).\n"); - // fprintf(stderr, "2: %s\n", ptr); + } else if (strcasecmp(ptr, "AFL") == 0 || - // remove whitespace at end - while (*ptr && isspace(ptr[strlen(ptr) - 1])) { + strcasecmp(ptr, "CLASSIC") == 0) { - ptr[strlen(ptr) - 1] = 0; - cont = 0; + aflcc->compiler_mode = LLVM; + aflcc->instrument_mode = INSTRUMENT_CLASSIC; - } + } else if (strcasecmp(ptr, "LLVMNATIVE") == 0 || - // fprintf(stderr, "3: %s\n", ptr); - if (*ptr) { + strcasecmp(ptr, "NATIVE") == 0 || + strcasecmp(ptr, "LLVM-NATIVE") == 0) { - do { + aflcc->compiler_mode = LLVM; + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; - u8 *value = ptr; - while (*ptr && !isspace(*ptr)) { + } else if (strncasecmp(ptr, "GCC_P", 5) == 0 || - ++ptr; + strncasecmp(ptr, "GCC-P", 5) == 0 || + strncasecmp(ptr, "GCCP", 4) == 0) { - } + aflcc->compiler_mode = GCC_PLUGIN; - while (*ptr && isspace(*ptr)) { +#if defined(__x86_64__) - *ptr++ = 0; + } else if (strcasecmp(ptr, "GCC") == 0) { - } + aflcc->compiler_mode = GCC; - if (cont_act) { +#endif - u32 len = strlen(args[count - 1]) + strlen(value) + 1; - u8 *tmp = malloc(len); - snprintf(tmp, len, "%s%s", args[count - 1], value); - free(args[count - 1]); - args[count - 1] = tmp; - cont_act = 0; +#if defined(__x86_64__) - } else { + } else if (strncasecmp(ptr, "CLANG", 5) == 0) { - args[count++] = strdup(value); + aflcc->compiler_mode = CLANG; - } +#endif - } while (*ptr); + } else - } + FATAL("Unknown --afl-... compiler mode: %s\n", argv[i]); - if (cont) { + } - cont_act = 1; - cont = 0; + } - } +} - } +static void instrument_mode_old_environ(aflcc_state_t *aflcc) { - if (count) { process_params(count, args); } + if (getenv("AFL_LLVM_INSTRIM") || getenv("INSTRIM") || + getenv("INSTRIM_LIB")) { - // we cannot free args[] - free(tmpbuf); + FATAL( + "InsTrim instrumentation was removed. Use a modern LLVM and PCGUARD " + "(default in afl-cc).\n"); - continue; + } - } + if (getenv("USE_TRACE_PC") || getenv("AFL_USE_TRACE_PC") || + getenv("AFL_LLVM_USE_TRACE_PC") || getenv("AFL_TRACE_PC")) { - cc_params[cc_par_cnt++] = cur; + if (aflcc->instrument_mode == 0) + aflcc->instrument_mode = INSTRUMENT_PCGUARD; + else if (aflcc->instrument_mode != INSTRUMENT_PCGUARD) + FATAL("you cannot set AFL_LLVM_INSTRUMENT and AFL_TRACE_PC together"); } -} - -/* Copy argv to cc_params, making the necessary edits. */ + if (getenv("AFL_LLVM_CTX")) aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CTX; + if (getenv("AFL_LLVM_CALLER")) + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CALLER; -static void edit_params(u32 argc, char **argv, char **envp) { + if (getenv("AFL_LLVM_NGRAM_SIZE")) { - cc_params = ck_alloc(MAX_PARAMS_NUM * sizeof(u8 *)); + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_NGRAM; + aflcc->ngram_size = atoi(getenv("AFL_LLVM_NGRAM_SIZE")); + if (aflcc->ngram_size < 2 || aflcc->ngram_size > NGRAM_SIZE_MAX) + FATAL( + "NGRAM instrumentation mode must be between 2 and NGRAM_SIZE_MAX " + "(%u)", + NGRAM_SIZE_MAX); - for (u32 c = 1; c < argc; ++c) { + } - if (!strcmp(argv[c], "-c")) have_c = 1; - if (!strncmp(argv[c], "-fsanitize-coverage-", 20) && - strstr(argv[c], "list=")) { + if (getenv("AFL_LLVM_CTX_K")) { - have_instr_list = 1; + aflcc->ctx_k = atoi(getenv("AFL_LLVM_CTX_K")); + if (aflcc->ctx_k < 1 || aflcc->ctx_k > CTX_MAX_K) + FATAL("K-CTX instrumentation mode must be between 1 and CTX_MAX_K (%u)", + CTX_MAX_K); + if (aflcc->ctx_k == 1) { - } + setenv("AFL_LLVM_CALLER", "1", 1); + unsetenv("AFL_LLVM_CTX_K"); + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CALLER; - } + } else { - if (lto_mode) { + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CTX_K; - if (lto_flag[0] != '-') - FATAL( - "Using afl-clang-lto is not possible because Makefile magic did not " - "identify the correct -flto flag"); - else - compiler_mode = LTO; + } } - if (plusplus_mode) { +} - u8 *alt_cxx = getenv("AFL_CXX"); +// compiler_mode would also be set if depended by the instrument_mode +static void instrument_mode_new_environ(aflcc_state_t *aflcc) { - if (!alt_cxx) { + if (!getenv("AFL_LLVM_INSTRUMENT")) { return; } - if (compiler_mode >= GCC_PLUGIN) { + u8 *ptr2 = strtok(getenv("AFL_LLVM_INSTRUMENT"), ":,;"); - if (compiler_mode == GCC) { + while (ptr2) { - alt_cxx = clang_mode ? "clang++" : "g++"; + if (strncasecmp(ptr2, "afl", strlen("afl")) == 0 || + strncasecmp(ptr2, "classic", strlen("classic")) == 0) { - } else if (compiler_mode == CLANG) { + if (aflcc->instrument_mode == INSTRUMENT_LTO) { - alt_cxx = "clang++"; + aflcc->instrument_mode = INSTRUMENT_CLASSIC; + aflcc->lto_mode = 1; - } else { + } else if (!aflcc->instrument_mode || - alt_cxx = "g++"; + aflcc->instrument_mode == INSTRUMENT_AFL) { - } + aflcc->instrument_mode = INSTRUMENT_AFL; } else { - if (USE_BINDIR) - snprintf(llvm_fullpath, sizeof(llvm_fullpath), "%s/clang++", - LLVM_BINDIR); - else - snprintf(llvm_fullpath, sizeof(llvm_fullpath), CLANGPP_BIN); - alt_cxx = llvm_fullpath; + FATAL("main instrumentation mode already set with %s", + instrument_mode_2str(aflcc->instrument_mode)); } } - cc_params[0] = alt_cxx; + if (strncasecmp(ptr2, "pc-guard", strlen("pc-guard")) == 0 || + strncasecmp(ptr2, "pcguard", strlen("pcguard")) == 0) { - } else { + if (!aflcc->instrument_mode || + aflcc->instrument_mode == INSTRUMENT_PCGUARD) - u8 *alt_cc = getenv("AFL_CC"); + aflcc->instrument_mode = INSTRUMENT_PCGUARD; - if (!alt_cc) { + else + FATAL("main instrumentation mode already set with %s", + instrument_mode_2str(aflcc->instrument_mode)); + + } - if (compiler_mode >= GCC_PLUGIN) { + if (strncasecmp(ptr2, "llvmnative", strlen("llvmnative")) == 0 || + strncasecmp(ptr2, "llvm-native", strlen("llvm-native")) == 0 || + strncasecmp(ptr2, "native", strlen("native")) == 0) { - if (compiler_mode == GCC) { + if (!aflcc->instrument_mode || + aflcc->instrument_mode == INSTRUMENT_LLVMNATIVE) - alt_cc = clang_mode ? "clang" : "gcc"; + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; - } else if (compiler_mode == CLANG) { + else + FATAL("main instrumentation mode already set with %s", + instrument_mode_2str(aflcc->instrument_mode)); - alt_cc = "clang"; + } - } else { + if (strncasecmp(ptr2, "llvmcodecov", strlen("llvmcodecov")) == 0 || + strncasecmp(ptr2, "llvm-codecov", strlen("llvm-codecov")) == 0) { - alt_cc = "gcc"; + if (!aflcc->instrument_mode || + aflcc->instrument_mode == INSTRUMENT_LLVMNATIVE) { - } + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CODECOV; } else { - if (USE_BINDIR) - snprintf(llvm_fullpath, sizeof(llvm_fullpath), "%s/clang", - LLVM_BINDIR); - else - snprintf(llvm_fullpath, sizeof(llvm_fullpath), "%s", CLANG_BIN); - alt_cc = llvm_fullpath; + FATAL("main instrumentation mode already set with %s", + instrument_mode_2str(aflcc->instrument_mode)); } } - cc_params[0] = alt_cc; + if (strncasecmp(ptr2, "cfg", strlen("cfg")) == 0 || + strncasecmp(ptr2, "instrim", strlen("instrim")) == 0) { - } + FATAL( + "InsTrim instrumentation was removed. Use a modern LLVM and " + "PCGUARD (default in afl-cc).\n"); + + } - if (compiler_mode == GCC || compiler_mode == CLANG) { + if (strncasecmp(ptr2, "lto", strlen("lto")) == 0) { - cc_params[cc_par_cnt++] = "-B"; - cc_params[cc_par_cnt++] = obj_path; + aflcc->lto_mode = 1; + if (!aflcc->instrument_mode || aflcc->instrument_mode == INSTRUMENT_LTO) - if (clang_mode || compiler_mode == CLANG) { + aflcc->instrument_mode = INSTRUMENT_LTO; - cc_params[cc_par_cnt++] = "-no-integrated-as"; + else + FATAL("main instrumentation mode already set with %s", + instrument_mode_2str(aflcc->instrument_mode)); } - } +#if defined(__x86_64__) + if (strcasecmp(ptr2, "gcc") == 0) { - if (compiler_mode == GCC_PLUGIN) { + if (!aflcc->instrument_mode || aflcc->instrument_mode == INSTRUMENT_GCC) - char *fplugin_arg; + aflcc->instrument_mode = INSTRUMENT_GCC; - if (cmplog_mode) { + else if (aflcc->instrument_mode != INSTRUMENT_GCC) + FATAL("main instrumentation mode already set with %s", + instrument_mode_2str(aflcc->instrument_mode)); - fplugin_arg = - alloc_printf("-fplugin=%s/afl-gcc-cmplog-pass.so", obj_path); - cc_params[cc_par_cnt++] = fplugin_arg; - fplugin_arg = - alloc_printf("-fplugin=%s/afl-gcc-cmptrs-pass.so", obj_path); - cc_params[cc_par_cnt++] = fplugin_arg; + aflcc->compiler_mode = GCC; } - fplugin_arg = alloc_printf("-fplugin=%s/afl-gcc-pass.so", obj_path); - cc_params[cc_par_cnt++] = fplugin_arg; - cc_params[cc_par_cnt++] = "-fno-if-conversion"; - cc_params[cc_par_cnt++] = "-fno-if-conversion2"; +#endif - } +#if defined(__x86_64__) + if (strcasecmp(ptr2, "clang") == 0) { - if (compiler_mode == LLVM || compiler_mode == LTO) { + if (!aflcc->instrument_mode || aflcc->instrument_mode == INSTRUMENT_CLANG) - cc_params[cc_par_cnt++] = "-Wno-unused-command-line-argument"; + aflcc->instrument_mode = INSTRUMENT_CLANG; - if (lto_mode && have_instr_env) { + else if (aflcc->instrument_mode != INSTRUMENT_CLANG) + FATAL("main instrumentation mode already set with %s", + instrument_mode_2str(aflcc->instrument_mode)); -#if LLVM_MAJOR >= 11 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = alloc_printf( - "-fpass-plugin=%s/afl-llvm-lto-instrumentlist.so", obj_path); -#else - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = "-load"; - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-llvm-lto-instrumentlist.so", obj_path); -#endif + aflcc->compiler_mode = CLANG; } - if (getenv("AFL_LLVM_DICT2FILE")) { - -#if LLVM_MAJOR >= 11 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/afl-llvm-dict2file.so", obj_path); -#else - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = "-load"; - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-llvm-dict2file.so", obj_path); #endif - } + if (strncasecmp(ptr2, "ctx-", strlen("ctx-")) == 0 || + strncasecmp(ptr2, "kctx-", strlen("c-ctx-")) == 0 || + strncasecmp(ptr2, "k-ctx-", strlen("k-ctx-")) == 0) { - // laf - if (getenv("LAF_SPLIT_SWITCHES") || getenv("AFL_LLVM_LAF_SPLIT_SWITCHES")) { + u8 *ptr3 = ptr2; + while (*ptr3 && (*ptr3 < '0' || *ptr3 > '9')) + ptr3++; -#if LLVM_MAJOR >= 11 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/split-switches-pass.so", obj_path); -#else - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = "-load"; - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = - alloc_printf("%s/split-switches-pass.so", obj_path); -#endif + if (!*ptr3) { - } + if ((ptr3 = getenv("AFL_LLVM_CTX_K")) == NULL) + FATAL( + "you must set the K-CTX K with (e.g. for value 2) " + "AFL_LLVM_INSTRUMENT=ctx-2"); - if (getenv("LAF_TRANSFORM_COMPARES") || - getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES")) { + } -#if LLVM_MAJOR >= 11 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/compare-transform-pass.so", obj_path); -#else - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = "-load"; - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = - alloc_printf("%s/compare-transform-pass.so", obj_path); -#endif + aflcc->ctx_k = atoi(ptr3); + if (aflcc->ctx_k < 1 || aflcc->ctx_k > CTX_MAX_K) + FATAL( + "K-CTX instrumentation option must be between 1 and CTX_MAX_K " + "(%u)", + CTX_MAX_K); - } + if (aflcc->ctx_k == 1) { - if (getenv("LAF_SPLIT_COMPARES") || getenv("AFL_LLVM_LAF_SPLIT_COMPARES") || - getenv("AFL_LLVM_LAF_SPLIT_FLOATS")) { + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CALLER; + setenv("AFL_LLVM_CALLER", "1", 1); + unsetenv("AFL_LLVM_CTX_K"); -#if LLVM_MAJOR >= 11 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/split-compares-pass.so", obj_path); -#else - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = "-load"; - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = - alloc_printf("%s/split-compares-pass.so", obj_path); -#endif + } else { - } + aflcc->instrument_opt_mode |= (INSTRUMENT_OPT_CTX_K); + u8 *ptr4 = alloc_printf("%u", aflcc->ctx_k); + setenv("AFL_LLVM_CTX_K", ptr4, 1); - // /laf + } - unsetenv("AFL_LD"); - unsetenv("AFL_LD_CALLER"); + } - if (cmplog_mode) { + if (strcasecmp(ptr2, "ctx") == 0) { - cc_params[cc_par_cnt++] = "-fno-inline"; + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CTX; + setenv("AFL_LLVM_CTX", "1", 1); -#if LLVM_MAJOR >= 11 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/cmplog-switches-pass.so", obj_path); - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/split-switches-pass.so", obj_path); -#else - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = "-load"; - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = - alloc_printf("%s/cmplog-switches-pass.so", obj_path); + } - // reuse split switches from laf - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = "-load"; - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = - alloc_printf("%s/split-switches-pass.so", obj_path); -#endif + if (strncasecmp(ptr2, "caller", strlen("caller")) == 0) { + + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CALLER; + setenv("AFL_LLVM_CALLER", "1", 1); } - // #if LLVM_MAJOR >= 13 - // // Use the old pass manager in LLVM 14 which the AFL++ passes still - // use. cc_params[cc_par_cnt++] = "-flegacy-pass-manager"; - // #endif + if (strncasecmp(ptr2, "ngram", strlen("ngram")) == 0) { - if (lto_mode && !have_c) { + u8 *ptr3 = ptr2 + strlen("ngram"); + while (*ptr3 && (*ptr3 < '0' || *ptr3 > '9')) { - u8 *ld_path = NULL; - if (getenv("AFL_REAL_LD")) { + ptr3++; - ld_path = strdup(getenv("AFL_REAL_LD")); + } - } else { + if (!*ptr3) { - ld_path = strdup(AFL_REAL_LD); + if ((ptr3 = getenv("AFL_LLVM_NGRAM_SIZE")) == NULL) + FATAL( + "you must set the NGRAM size with (e.g. for value 2) " + "AFL_LLVM_INSTRUMENT=ngram-2"); } - if (!ld_path || !*ld_path) { + aflcc->ngram_size = atoi(ptr3); - if (ld_path) { + if (aflcc->ngram_size < 2 || aflcc->ngram_size > NGRAM_SIZE_MAX) { - // Freeing empty string - free(ld_path); + FATAL( + "NGRAM instrumentation option must be between 2 and " + "NGRAM_SIZE_MAX (%u)", + NGRAM_SIZE_MAX); - } + } - ld_path = strdup("ld.lld"); + aflcc->instrument_opt_mode |= (INSTRUMENT_OPT_NGRAM); + u8 *ptr4 = alloc_printf("%u", aflcc->ngram_size); + setenv("AFL_LLVM_NGRAM_SIZE", ptr4, 1); - } + } - if (!ld_path) { PFATAL("Could not allocate mem for ld_path"); } -#if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 12 - cc_params[cc_par_cnt++] = alloc_printf("--ld-path=%s", ld_path); -#else - cc_params[cc_par_cnt++] = alloc_printf("-fuse-ld=%s", ld_path); -#endif - free(ld_path); + ptr2 = strtok(NULL, ":,;"); -#if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 15 - // The NewPM implementation only works fully since LLVM 15. - cc_params[cc_par_cnt++] = alloc_printf( - "-Wl,--load-pass-plugin=%s/SanitizerCoverageLTO.so", obj_path); -#elif defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 13 - cc_params[cc_par_cnt++] = "-Wl,--lto-legacy-pass-manager"; - cc_params[cc_par_cnt++] = - alloc_printf("-Wl,-mllvm=-load=%s/SanitizerCoverageLTO.so", obj_path); -#else - cc_params[cc_par_cnt++] = "-fno-experimental-new-pass-manager"; - cc_params[cc_par_cnt++] = - alloc_printf("-Wl,-mllvm=-load=%s/SanitizerCoverageLTO.so", obj_path); -#endif - - cc_params[cc_par_cnt++] = "-Wl,--allow-multiple-definition"; - cc_params[cc_par_cnt++] = lto_flag; - - } else { - - if (instrument_mode == INSTRUMENT_PCGUARD) { - -#if LLVM_MAJOR >= 13 - #if defined __ANDROID__ || ANDROID - cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; - instrument_mode = INSTRUMENT_LLVMNATIVE; - #else - if (have_instr_list) { - - if (!be_quiet) - SAYF( - "Using unoptimized trace-pc-guard, due usage of " - "-fsanitize-coverage-allow/denylist, you can use " - "AFL_LLVM_ALLOWLIST/AFL_LLMV_DENYLIST instead.\n"); - cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; - instrument_mode = INSTRUMENT_LLVMNATIVE; - - } else { - - #if LLVM_MAJOR >= 13 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = alloc_printf( - "-fpass-plugin=%s/SanitizerCoveragePCGUARD.so", obj_path); - #else - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = "-load"; - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = - alloc_printf("%s/SanitizerCoveragePCGUARD.so", obj_path); - #endif - - } - - #endif -#else - #if LLVM_MAJOR >= 4 - if (!be_quiet) - SAYF( - "Using unoptimized trace-pc-guard, upgrade to LLVM 13+ for " - "enhanced version.\n"); - cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; - instrument_mode = INSTRUMENT_LLVMNATIVE; - #else - FATAL("pcguard instrumentation requires LLVM 4.0.1+"); - #endif -#endif - - } else if (instrument_mode == INSTRUMENT_LLVMNATIVE) { - -#if LLVM_MAJOR >= 4 - if (instrument_opt_mode & INSTRUMENT_OPT_CODECOV) { - - #if LLVM_MAJOR >= 6 - cc_params[cc_par_cnt++] = - "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table"; - #else - FATAL("pcguard instrumentation with pc-table requires LLVM 6.0.1+"); - #endif + } - } else { +} - cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; +void instrument_mode_by_environ(aflcc_state_t *aflcc) { - } + if (getenv("AFL_LLVM_INSTRUMENT_FILE") || getenv("AFL_LLVM_WHITELIST") || + getenv("AFL_LLVM_ALLOWLIST") || getenv("AFL_LLVM_DENYLIST") || + getenv("AFL_LLVM_BLOCKLIST")) { -#else - FATAL("pcguard instrumentation requires LLVM 4.0.1+"); -#endif + aflcc->have_instr_env = 1; - } else { + } -#if LLVM_MAJOR >= 11 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/afl-llvm-pass.so", obj_path); -#else + if (aflcc->have_instr_env && getenv("AFL_DONT_OPTIMIZE") && !be_quiet) { - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = "-load"; - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-pass.so", obj_path); -#endif + WARNF( + "AFL_LLVM_ALLOWLIST/DENYLIST and AFL_DONT_OPTIMIZE cannot be combined " + "for file matching, only function matching!"); - } + } - } + instrument_mode_old_environ(aflcc); + instrument_mode_new_environ(aflcc); - if (cmplog_mode) { +} -#if LLVM_MAJOR >= 11 - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = alloc_printf( - "-fpass-plugin=%s/cmplog-instructions-pass.so", obj_path); - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/cmplog-routines-pass.so", obj_path); -#else - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = "-load"; - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = - alloc_printf("%s/cmplog-instructions-pass.so", obj_path); - - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = "-load"; - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = - alloc_printf("%s/cmplog-routines-pass.so", obj_path); -#endif +static void instrument_opt_mode_exclude(aflcc_state_t *aflcc) { - } + if ((aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX) && + (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER)) { - if (getenv("AFL_LLVM_INJECTIONS_ALL") || - getenv("AFL_LLVM_INJECTIONS_SQL") || - getenv("AFL_LLVM_INJECTIONS_LDAP") || - getenv("AFL_LLVM_INJECTIONS_XSS")) { + FATAL("you cannot set CTX and CALLER together"); -#if LLVM_MAJOR >= 11 - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/injection-pass.so", obj_path); -#else - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = "-load"; - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = alloc_printf("%s/injection-pass.so", obj_path); -#endif + } - } + if ((aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX) && + (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX_K)) { - // cc_params[cc_par_cnt++] = "-Qunused-arguments"; + FATAL("you cannot set CTX and K-CTX together"); } - /* Inspect the command line parameters. */ + if ((aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER) && + (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX_K)) { - process_params(argc, argv); + FATAL("you cannot set CALLER and K-CTX together"); - if (!have_pic) { + } - cc_params[cc_par_cnt++] = "-fPIC"; - have_pic = 1; + if (aflcc->instrument_opt_mode && aflcc->compiler_mode != LLVM) + FATAL("CTX, CALLER and NGRAM can only be used in LLVM mode"); - } + if (aflcc->instrument_opt_mode && + aflcc->instrument_opt_mode != INSTRUMENT_OPT_CODECOV && + aflcc->instrument_mode != INSTRUMENT_CLASSIC) + FATAL( + "CALLER, CTX and NGRAM instrumentation options can only be used with " + "the LLVM CLASSIC instrumentation mode."); - if (compiler_mode != GCC_PLUGIN && compiler_mode != GCC && - !getenv("AFL_LLVM_NO_RPATH")) { +} - // in case LLVM is installed not via a package manager or "make install" - // e.g. compiled download or compiled from github then its ./lib directory - // might not be in the search path. Add it if so. - const char *libdir = LLVM_LIBDIR; - if (plusplus_mode && strlen(libdir) && strncmp(libdir, "/usr", 4) && - strncmp(libdir, "/lib", 4)) { +void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) { - u8 *libdir_opt = strdup("-Wl,-rpath=" LLVM_LIBDIR); - cc_params[cc_par_cnt++] = libdir_opt; + if (aflcc->instrument_opt_mode && + aflcc->instrument_mode == INSTRUMENT_DEFAULT && + (aflcc->compiler_mode == LLVM || aflcc->compiler_mode == UNSET)) { - } + aflcc->instrument_mode = INSTRUMENT_CLASSIC; + aflcc->compiler_mode = LLVM; } - if (getenv("AFL_HARDEN")) { - - cc_params[cc_par_cnt++] = "-fstack-protector-all"; + if (!aflcc->compiler_mode) { - if (!fortify_set) cc_params[cc_par_cnt++] = "-D_FORTIFY_SOURCE=2"; + // lto is not a default because outside of afl-cc RANLIB and AR have to + // be set to LLVM versions so this would work + if (aflcc->have_llvm) + aflcc->compiler_mode = LLVM; + else if (aflcc->have_gcc_plugin) + aflcc->compiler_mode = GCC_PLUGIN; + else if (aflcc->have_gcc) + aflcc->compiler_mode = GCC; + else if (aflcc->have_clang) + aflcc->compiler_mode = CLANG; + else if (aflcc->have_lto) + aflcc->compiler_mode = LTO; + else + FATAL("no compiler mode available"); } - if (!asan_set) { + switch (aflcc->compiler_mode) { - if (getenv("AFL_USE_ASAN")) { + case GCC: + if (!aflcc->have_gcc) FATAL("afl-gcc not available on your platform!"); + break; + case CLANG: + if (!aflcc->have_clang) + FATAL("afl-clang not available on your platform!"); + break; + case LLVM: + if (!aflcc->have_llvm) + FATAL( + "LLVM mode is not available, please install LLVM 13+ and recompile " + "AFL++"); + break; + case GCC_PLUGIN: + if (!aflcc->have_gcc_plugin) + FATAL( + "GCC_PLUGIN mode is not available, install gcc plugin support and " + "recompile AFL++"); + break; + case LTO: + if (!aflcc->have_lto) + FATAL( + "LTO mode is not available, please install LLVM 13+ and lld of the " + "same version and recompile AFL++"); + break; + default: + FATAL("no compiler mode available"); - if (getenv("AFL_USE_MSAN")) FATAL("ASAN and MSAN are mutually exclusive"); + } - if (getenv("AFL_HARDEN")) - FATAL("ASAN and AFL_HARDEN are mutually exclusive"); + if (aflcc->compiler_mode == GCC) { aflcc->instrument_mode = INSTRUMENT_GCC; } - cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE"; - cc_params[cc_par_cnt++] = "-fsanitize=address"; + if (aflcc->compiler_mode == CLANG) { - } else if (getenv("AFL_USE_MSAN")) { + /* if our PCGUARD implementation is not available then silently switch to + native LLVM PCGUARD. Or classic asm instrument is explicitly preferred. */ + if (!aflcc->have_optimized_pcguard && + (aflcc->instrument_mode == INSTRUMENT_DEFAULT || + aflcc->instrument_mode == INSTRUMENT_PCGUARD)) { - if (getenv("AFL_USE_ASAN")) FATAL("ASAN and MSAN are mutually exclusive"); + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; - if (getenv("AFL_HARDEN")) - FATAL("MSAN and AFL_HARDEN are mutually exclusive"); + } else { - cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE"; - cc_params[cc_par_cnt++] = "-fsanitize=memory"; + aflcc->instrument_mode = INSTRUMENT_CLANG; + setenv(CLANG_ENV_VAR, "1", 1); // used by afl-as } } - if (getenv("AFL_USE_UBSAN")) { + if (aflcc->compiler_mode == LTO) { - cc_params[cc_par_cnt++] = "-fsanitize=undefined"; - cc_params[cc_par_cnt++] = "-fsanitize-undefined-trap-on-error"; - cc_params[cc_par_cnt++] = "-fno-sanitize-recover=all"; - cc_params[cc_par_cnt++] = "-fno-omit-frame-pointer"; + if (aflcc->instrument_mode == 0 || + aflcc->instrument_mode == INSTRUMENT_LTO || + aflcc->instrument_mode == INSTRUMENT_CFG || + aflcc->instrument_mode == INSTRUMENT_PCGUARD) { - } + aflcc->lto_mode = 1; + // force CFG + // if (!aflcc->instrument_mode) { - if (getenv("AFL_USE_TSAN")) { + aflcc->instrument_mode = INSTRUMENT_PCGUARD; - cc_params[cc_par_cnt++] = "-fsanitize=thread"; - cc_params[cc_par_cnt++] = "-fno-omit-frame-pointer"; + // } - } + } else if (aflcc->instrument_mode == INSTRUMENT_CLASSIC) { - if (getenv("AFL_USE_LSAN")) { + aflcc->lto_mode = 1; - cc_params[cc_par_cnt++] = "-fsanitize=leak"; - cc_params[cc_par_cnt++] = "-includesanitizer/lsan_interface.h"; - cc_params[cc_par_cnt++] = - "-D__AFL_LEAK_CHECK()={if(__lsan_do_recoverable_leak_check() > 0) " - "_exit(23); }"; - cc_params[cc_par_cnt++] = "-D__AFL_LSAN_OFF()=__lsan_disable();"; - cc_params[cc_par_cnt++] = "-D__AFL_LSAN_ON()=__lsan_enable();"; + } else { - } + if (!be_quiet) { - if (getenv("AFL_USE_CFISAN")) { + WARNF("afl-clang-lto called with mode %s, using that mode instead", + instrument_mode_2str(aflcc->instrument_mode)); - if (compiler_mode == GCC_PLUGIN || compiler_mode == GCC) { + } - cc_params[cc_par_cnt++] = "-fcf-protection=full"; + } - } else { + } - if (!lto_mode) { + if (aflcc->instrument_mode == 0 && aflcc->compiler_mode < GCC_PLUGIN) { - uint32_t i = 0, found = 0; - while (envp[i] != NULL && !found) - if (strncmp("-flto", envp[i++], 5) == 0) found = 1; - if (!found) cc_params[cc_par_cnt++] = "-flto"; +#if LLVM_MAJOR >= 7 + #if LLVM_MAJOR < 11 && (LLVM_MAJOR < 10 || LLVM_MINOR < 1) + if (aflcc->have_instr_env) { - } + aflcc->instrument_mode = INSTRUMENT_AFL; + if (!be_quiet) { - cc_params[cc_par_cnt++] = "-fsanitize=cfi"; - cc_params[cc_par_cnt++] = "-fvisibility=hidden"; + WARNF( + "Switching to classic instrumentation because " + "AFL_LLVM_ALLOWLIST/DENYLIST does not work with PCGUARD < 10.0.1."); - } + } - } + } else - if (!getenv("AFL_DONT_OPTIMIZE")) { + #endif + aflcc->instrument_mode = INSTRUMENT_PCGUARD; - cc_params[cc_par_cnt++] = "-g"; - if (!have_o) cc_params[cc_par_cnt++] = "-O3"; - if (!have_unroll) cc_params[cc_par_cnt++] = "-funroll-loops"; - // if (strlen(march_opt) > 1 && march_opt[0] == '-') - // cc_params[cc_par_cnt++] = march_opt; +#else + aflcc->instrument_mode = INSTRUMENT_AFL; +#endif } - if (getenv("AFL_NO_BUILTIN") || getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES") || - getenv("LAF_TRANSFORM_COMPARES") || getenv("AFL_LLVM_LAF_ALL") || - lto_mode) { + if (!aflcc->instrument_opt_mode && aflcc->lto_mode && + aflcc->instrument_mode == INSTRUMENT_CFG) { - cc_params[cc_par_cnt++] = "-fno-builtin-strcmp"; - cc_params[cc_par_cnt++] = "-fno-builtin-strncmp"; - cc_params[cc_par_cnt++] = "-fno-builtin-strcasecmp"; - cc_params[cc_par_cnt++] = "-fno-builtin-strncasecmp"; - cc_params[cc_par_cnt++] = "-fno-builtin-memcmp"; - cc_params[cc_par_cnt++] = "-fno-builtin-bcmp"; - cc_params[cc_par_cnt++] = "-fno-builtin-strstr"; - cc_params[cc_par_cnt++] = "-fno-builtin-strcasestr"; + aflcc->instrument_mode = INSTRUMENT_PCGUARD; } -#if defined(USEMMAP) && !defined(__HAIKU__) && !__APPLE__ - if (!have_c) cc_params[cc_par_cnt++] = "-lrt"; +#ifndef AFL_CLANG_FLTO + if (aflcc->lto_mode) + FATAL( + "instrumentation mode LTO specified but LLVM support not available " + "(requires LLVM 11 or higher)"); #endif - cc_params[cc_par_cnt++] = "-D__AFL_COMPILER=1"; - cc_params[cc_par_cnt++] = "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1"; + if (aflcc->lto_mode) { - /* As documented in instrumentation/README.persistent_mode.md, deferred - forkserver initialization and persistent mode are not available in afl-gcc - and afl-clang. */ - if (compiler_mode != GCC && compiler_mode != CLANG) { + if (aflcc->lto_flag[0] != '-') + FATAL( + "Using afl-clang-lto is not possible because Makefile magic did not " + "identify the correct -flto flag"); + else + aflcc->compiler_mode = LTO; - cc_params[cc_par_cnt++] = "-D__AFL_HAVE_MANUAL_CONTROL=1"; + } - /* When the user tries to use persistent or deferred forkserver modes by - appending a single line to the program, we want to reliably inject a - signature into the binary (to be picked up by afl-fuzz) and we want - to call a function from the runtime .o file. This is unnecessarily - painful for three reasons: + if (getenv("AFL_LLVM_SKIP_NEVERZERO") && getenv("AFL_LLVM_NOT_ZERO")) + FATAL( + "AFL_LLVM_NOT_ZERO and AFL_LLVM_SKIP_NEVERZERO can not be set " + "together"); - 1) We need to convince the compiler not to optimize out the signature. - This is done with __attribute__((used)). +#if LLVM_MAJOR < 11 && (LLVM_MAJOR < 10 || LLVM_MINOR < 1) - 2) We need to convince the linker, when called with -Wl,--gc-sections, - not to do the same. This is done by forcing an assignment to a - 'volatile' pointer. + if (aflcc->instrument_mode == INSTRUMENT_PCGUARD && aflcc->have_instr_env) { - 3) We need to declare __afl_persistent_loop() in the global namespace, - but doing this within a method in a class is hard - :: and extern "C" - are forbidden and __attribute__((alias(...))) doesn't work. Hence the - __asm__ aliasing trick. + FATAL( + "Instrumentation type PCGUARD does not support " + "AFL_LLVM_ALLOWLIST/DENYLIST! Use LLVM 10.0.1+ instead."); - */ + } - cc_params[cc_par_cnt++] = - "-D__AFL_FUZZ_INIT()=" - "int __afl_sharedmem_fuzzing = 1;" - "extern unsigned int *__afl_fuzz_len;" - "extern unsigned char *__afl_fuzz_ptr;" - "unsigned char __afl_fuzz_alt[1048576];" - "unsigned char *__afl_fuzz_alt_ptr = __afl_fuzz_alt;"; +#endif - } + instrument_opt_mode_exclude(aflcc); - if (plusplus_mode) { + u8 *ptr2; - cc_params[cc_par_cnt++] = - "-D__AFL_COVERAGE()=int __afl_selective_coverage = 1;" - "extern \"C\" void __afl_coverage_discard();" - "extern \"C\" void __afl_coverage_skip();" - "extern \"C\" void __afl_coverage_on();" - "extern \"C\" void __afl_coverage_off();"; + if ((ptr2 = getenv("AFL_LLVM_DICT2FILE")) != NULL && *ptr2 != '/') + FATAL("AFL_LLVM_DICT2FILE must be set to an absolute file path"); - } else { + if (getenv("AFL_LLVM_LAF_ALL")) { - cc_params[cc_par_cnt++] = - "-D__AFL_COVERAGE()=int __afl_selective_coverage = 1;" - "void __afl_coverage_discard();" - "void __afl_coverage_skip();" - "void __afl_coverage_on();" - "void __afl_coverage_off();"; + setenv("AFL_LLVM_LAF_SPLIT_SWITCHES", "1", 1); + setenv("AFL_LLVM_LAF_SPLIT_COMPARES", "1", 1); + setenv("AFL_LLVM_LAF_SPLIT_FLOATS", "1", 1); + setenv("AFL_LLVM_LAF_TRANSFORM_COMPARES", "1", 1); } - cc_params[cc_par_cnt++] = - "-D__AFL_COVERAGE_START_OFF()=int __afl_selective_coverage_start_off = " - "1;"; - cc_params[cc_par_cnt++] = "-D__AFL_COVERAGE_ON()=__afl_coverage_on()"; - cc_params[cc_par_cnt++] = "-D__AFL_COVERAGE_OFF()=__afl_coverage_off()"; - cc_params[cc_par_cnt++] = - "-D__AFL_COVERAGE_DISCARD()=__afl_coverage_discard()"; - cc_params[cc_par_cnt++] = "-D__AFL_COVERAGE_SKIP()=__afl_coverage_skip()"; - cc_params[cc_par_cnt++] = - "-D__AFL_FUZZ_TESTCASE_BUF=(__afl_fuzz_ptr ? __afl_fuzz_ptr : " - "__afl_fuzz_alt_ptr)"; - cc_params[cc_par_cnt++] = - "-D__AFL_FUZZ_TESTCASE_LEN=(__afl_fuzz_ptr ? *__afl_fuzz_len : " - "(*__afl_fuzz_len = read(0, __afl_fuzz_alt_ptr, 1048576)) == 0xffffffff " - "? 0 : *__afl_fuzz_len)"; + aflcc->cmplog_mode = getenv("AFL_CMPLOG") || getenv("AFL_LLVM_CMPLOG") || + getenv("AFL_GCC_CMPLOG"); - if (compiler_mode != GCC && compiler_mode != CLANG) { +} - cc_params[cc_par_cnt++] = - "-D__AFL_LOOP(_A)=" - "({ static volatile const char *_B __attribute__((used,unused)); " - " _B = (const char*)\"" PERSIST_SIG - "\"; " - "extern int __afl_connected;" -#ifdef __APPLE__ - "__attribute__((visibility(\"default\"))) " - "int _L(unsigned int) __asm__(\"___afl_persistent_loop\"); " -#else - "__attribute__((visibility(\"default\"))) " - "int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); " -#endif /* ^__APPLE__ */ - // if afl is connected, we run _A times, else once. - "_L(__afl_connected ? _A : 1); })"; - - cc_params[cc_par_cnt++] = - "-D__AFL_INIT()=" - "do { static volatile const char *_A __attribute__((used,unused)); " - " _A = (const char*)\"" DEFER_SIG - "\"; " -#ifdef __APPLE__ - "__attribute__((visibility(\"default\"))) " - "void _I(void) __asm__(\"___afl_manual_init\"); " -#else - "__attribute__((visibility(\"default\"))) " - "void _I(void) __asm__(\"__afl_manual_init\"); " -#endif /* ^__APPLE__ */ - "_I(); } while (0)"; +void mode_notification(aflcc_state_t *aflcc) { - } + char *ptr2 = alloc_printf(" + NGRAM-%u", aflcc->ngram_size); + char *ptr3 = alloc_printf(" + K-CTX-%u", aflcc->ctx_k); + + char *ptr1 = alloc_printf( + "%s%s%s%s%s", instrument_mode_2str(aflcc->instrument_mode), + (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX) ? " + CTX" : "", + (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER) ? " + CALLER" : "", + (aflcc->instrument_opt_mode & INSTRUMENT_OPT_NGRAM) ? ptr2 : "", + (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX_K) ? ptr3 : ""); - if (x_set) { + ck_free(ptr2); + ck_free(ptr3); - cc_params[cc_par_cnt++] = "-x"; - cc_params[cc_par_cnt++] = "none"; + if ((isatty(2) && !be_quiet) || aflcc->debug) { + + SAYF(cCYA + "afl-cc" VERSION cRST + " by Michal Zalewski, Laszlo Szekeres, Marc Heuse - mode: %s-%s\n", + compiler_mode_2str(aflcc->compiler_mode), ptr1); } - // prevent unnecessary build errors - if (compiler_mode != GCC_PLUGIN && compiler_mode != GCC) { + ck_free(ptr1); + + if (!be_quiet && + (aflcc->compiler_mode == GCC || aflcc->compiler_mode == CLANG)) { - cc_params[cc_par_cnt++] = "-Wno-unused-command-line-argument"; + WARNF( + "You are using outdated instrumentation, install LLVM and/or " + "gcc-plugin and use afl-clang-fast/afl-clang-lto/afl-gcc-fast " + "instead!"); } - if (preprocessor_only || have_c || !non_dash) { +} - /* In the preprocessor_only case (-E), we are not actually compiling at - all but requesting the compiler to output preprocessed sources only. - We must not add the runtime in this case because the compiler will - simply output its binary content back on stdout, breaking any build - systems that rely on a separate source preprocessing step. */ - cc_params[cc_par_cnt] = NULL; - return; +void add_real_argv0(aflcc_state_t *aflcc) { - } + static u8 llvm_fullpath[PATH_MAX]; -#ifndef __ANDROID__ + if (aflcc->plusplus_mode) { - if (compiler_mode != GCC && compiler_mode != CLANG) { + u8 *alt_cxx = getenv("AFL_CXX"); - switch (bit_mode) { + if (!alt_cxx) { - case 0: - if (!shared_linking && !partial_linking) - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-compiler-rt.o", obj_path); - if (lto_mode) - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-llvm-rt-lto.o", obj_path); - break; + if (aflcc->compiler_mode == GCC || aflcc->compiler_mode == GCC_PLUGIN) { - case 32: - if (!shared_linking && !partial_linking) { + alt_cxx = "g++"; - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-compiler-rt-32.o", obj_path); - if (access(cc_params[cc_par_cnt - 1], R_OK)) - FATAL("-m32 is not supported by your compiler"); + } else if (aflcc->compiler_mode == CLANG) { - } + alt_cxx = "clang++"; - if (lto_mode) { + } else { - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-llvm-rt-lto-32.o", obj_path); - if (access(cc_params[cc_par_cnt - 1], R_OK)) - FATAL("-m32 is not supported by your compiler"); + if (USE_BINDIR) + snprintf(llvm_fullpath, sizeof(llvm_fullpath), "%s/clang++", + LLVM_BINDIR); + else + snprintf(llvm_fullpath, sizeof(llvm_fullpath), CLANGPP_BIN); + alt_cxx = llvm_fullpath; - } + } - break; + } - case 64: - if (!shared_linking && !partial_linking) { + aflcc->cc_params[0] = alt_cxx; - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-compiler-rt-64.o", obj_path); - if (access(cc_params[cc_par_cnt - 1], R_OK)) - FATAL("-m64 is not supported by your compiler"); + } else { - } + u8 *alt_cc = getenv("AFL_CC"); - if (lto_mode) { + if (!alt_cc) { - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-llvm-rt-lto-64.o", obj_path); - if (access(cc_params[cc_par_cnt - 1], R_OK)) - FATAL("-m64 is not supported by your compiler"); + if (aflcc->compiler_mode == GCC || aflcc->compiler_mode == GCC_PLUGIN) { - } + alt_cc = "gcc"; - break; + } else if (aflcc->compiler_mode == CLANG) { - } + alt_cc = "clang"; - #if !defined(__APPLE__) && !defined(__sun) - if (!shared_linking && !partial_linking) - cc_params[cc_par_cnt++] = - alloc_printf("-Wl,--dynamic-list=%s/dynamic_list.txt", obj_path); - #endif + } else { - #if defined(__APPLE__) - if (shared_linking || partial_linking) { + if (USE_BINDIR) + snprintf(llvm_fullpath, sizeof(llvm_fullpath), "%s/clang", + LLVM_BINDIR); + else + snprintf(llvm_fullpath, sizeof(llvm_fullpath), CLANG_BIN); + alt_cc = llvm_fullpath; - cc_params[cc_par_cnt++] = "-Wl,-U"; - cc_params[cc_par_cnt++] = "-Wl,___afl_area_ptr"; - cc_params[cc_par_cnt++] = "-Wl,-U"; - cc_params[cc_par_cnt++] = "-Wl,___sanitizer_cov_trace_pc_guard_init"; + } } - #endif + aflcc->cc_params[0] = alt_cc; } - #if defined(USEMMAP) && !defined(__HAIKU__) && !__APPLE__ - cc_params[cc_par_cnt++] = "-lrt"; - #endif +} -#endif +/* Macro defs for the preprocessor */ - cc_params[cc_par_cnt] = NULL; +void add_defs_common(aflcc_state_t *aflcc) { + + insert_param(aflcc, "-D__AFL_COMPILER=1"); + insert_param(aflcc, "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1"); } -/* Main entry point */ +/* See instrumentation/README.instrument_list.md# + 2-selective-instrumentation-with-_afl_coverage-directives */ +void add_defs_selective_instr(aflcc_state_t *aflcc) { -int main(int argc, char **argv, char **envp) { + if (aflcc->plusplus_mode) { - int i; - char *callname = argv[0], *ptr = NULL; + insert_param(aflcc, + "-D__AFL_COVERAGE()=int __afl_selective_coverage = 1;" + "extern \"C\" void __afl_coverage_discard();" + "extern \"C\" void __afl_coverage_skip();" + "extern \"C\" void __afl_coverage_on();" + "extern \"C\" void __afl_coverage_off();"); - if (getenv("AFL_DEBUG")) { + } else { - debug = 1; - if (strcmp(getenv("AFL_DEBUG"), "0") == 0) unsetenv("AFL_DEBUG"); + insert_param(aflcc, + "-D__AFL_COVERAGE()=int __afl_selective_coverage = 1;" + "void __afl_coverage_discard();" + "void __afl_coverage_skip();" + "void __afl_coverage_on();" + "void __afl_coverage_off();"); - } else if (getenv("AFL_QUIET")) + } - be_quiet = 1; + insert_param( + aflcc, + "-D__AFL_COVERAGE_START_OFF()=int __afl_selective_coverage_start_off = " + "1;"); + insert_param(aflcc, "-D__AFL_COVERAGE_ON()=__afl_coverage_on()"); + insert_param(aflcc, "-D__AFL_COVERAGE_OFF()=__afl_coverage_off()"); + insert_param(aflcc, "-D__AFL_COVERAGE_DISCARD()=__afl_coverage_discard()"); + insert_param(aflcc, "-D__AFL_COVERAGE_SKIP()=__afl_coverage_skip()"); - if (getenv("AFL_LLVM_INSTRUMENT_FILE") || getenv("AFL_LLVM_WHITELIST") || - getenv("AFL_LLVM_ALLOWLIST") || getenv("AFL_LLVM_DENYLIST") || - getenv("AFL_LLVM_BLOCKLIST")) { +} - have_instr_env = 1; +/* As documented in instrumentation/README.persistent_mode.md, deferred + forkserver initialization and persistent mode are not available in afl-gcc + and afl-clang. */ +void add_defs_persistent_mode(aflcc_state_t *aflcc) { - } + if (aflcc->compiler_mode == GCC || aflcc->compiler_mode == CLANG) return; - if (getenv("AFL_PASSTHROUGH") || getenv("AFL_NOOPT")) { + insert_param(aflcc, "-D__AFL_HAVE_MANUAL_CONTROL=1"); - passthrough = 1; - if (!debug) { be_quiet = 1; } + /* When the user tries to use persistent or deferred forkserver modes by + appending a single line to the program, we want to reliably inject a + signature into the binary (to be picked up by afl-fuzz) and we want + to call a function from the runtime .o file. This is unnecessarily + painful for three reasons: - } + 1) We need to convince the compiler not to optimize out the signature. + This is done with __attribute__((used)). - if ((ptr = strrchr(callname, '/')) != NULL) callname = ptr + 1; - argvnull = (u8 *)argv[0]; - check_environment_vars(envp); + 2) We need to convince the linker, when called with -Wl,--gc-sections, + not to do the same. This is done by forcing an assignment to a + 'volatile' pointer. - if ((ptr = find_object("as", argv[0])) != NULL) { + 3) We need to declare __afl_persistent_loop() in the global namespace, + but doing this within a method in a class is hard - :: and extern "C" + are forbidden and __attribute__((alias(...))) doesn't work. Hence the + __asm__ aliasing trick. - have_gcc = 1; - ck_free(ptr); + */ - } + insert_param(aflcc, + "-D__AFL_FUZZ_INIT()=" + "int __afl_sharedmem_fuzzing = 1;" + "extern unsigned int *__afl_fuzz_len;" + "extern unsigned char *__afl_fuzz_ptr;" + "unsigned char __afl_fuzz_alt[1048576];" + "unsigned char *__afl_fuzz_alt_ptr = __afl_fuzz_alt;"); -#if (LLVM_MAJOR >= 3) + insert_param(aflcc, + "-D__AFL_FUZZ_TESTCASE_BUF=(__afl_fuzz_ptr ? __afl_fuzz_ptr : " + "__afl_fuzz_alt_ptr)"); - if ((ptr = find_object("SanitizerCoverageLTO.so", argv[0])) != NULL) { + insert_param( + aflcc, + "-D__AFL_FUZZ_TESTCASE_LEN=(__afl_fuzz_ptr ? *__afl_fuzz_len : " + "(*__afl_fuzz_len = read(0, __afl_fuzz_alt_ptr, 1048576)) == 0xffffffff " + "? 0 : *__afl_fuzz_len)"); + + insert_param( + aflcc, + "-D__AFL_LOOP(_A)=" + "({ static volatile const char *_B __attribute__((used,unused)); " + " _B = (const char*)\"" PERSIST_SIG + "\"; " + "extern int __afl_connected;" +#ifdef __APPLE__ + "__attribute__((visibility(\"default\"))) " + "int _L(unsigned int) __asm__(\"___afl_persistent_loop\"); " +#else + "__attribute__((visibility(\"default\"))) " + "int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); " +#endif /* ^__APPLE__ */ + // if afl is connected, we run _A times, else once. + "_L(__afl_connected ? _A : 1); })"); + + insert_param( + aflcc, + "-D__AFL_INIT()=" + "do { static volatile const char *_A __attribute__((used,unused)); " + " _A = (const char*)\"" DEFER_SIG + "\"; " +#ifdef __APPLE__ + "__attribute__((visibility(\"default\"))) " + "void _I(void) __asm__(\"___afl_manual_init\"); " +#else + "__attribute__((visibility(\"default\"))) " + "void _I(void) __asm__(\"__afl_manual_init\"); " +#endif /* ^__APPLE__ */ + "_I(); } while (0)"); - have_lto = 1; - ck_free(ptr); +} - } +/* Control _FORTIFY_SOURCE */ +void add_defs_fortify(aflcc_state_t *aflcc, u8 action) { - if ((ptr = find_object("cmplog-routines-pass.so", argv[0])) != NULL) { + switch (action) { - have_llvm = 1; - ck_free(ptr); + case 1: + insert_param(aflcc, "-D_FORTIFY_SOURCE=1"); + break; - } + case 2: + insert_param(aflcc, "-D_FORTIFY_SOURCE=2"); + break; -#endif + default: // OFF + insert_param(aflcc, "-U_FORTIFY_SOURCE"); + break; -#ifdef __ANDROID__ - have_llvm = 1; -#endif + } - if ((ptr = find_object("afl-gcc-pass.so", argv[0])) != NULL) { +} - have_gcc_plugin = 1; - ck_free(ptr); +void add_defs_lsan_ctrl(aflcc_state_t *aflcc) { - } + insert_param(aflcc, "-includesanitizer/lsan_interface.h"); + insert_param( + aflcc, + "-D__AFL_LEAK_CHECK()={if(__lsan_do_recoverable_leak_check() > 0) " + "_exit(23); }"); + insert_param(aflcc, "-D__AFL_LSAN_OFF()=__lsan_disable();"); + insert_param(aflcc, "-D__AFL_LSAN_ON()=__lsan_enable();"); -#if (LLVM_MAJOR >= 3) +} - if (strncmp(callname, "afl-clang-fast", 14) == 0) { +/* About fsanitize (including PCGUARD features) */ - compiler_mode = LLVM; +/* For input "-fsanitize=...", it: - } else if (strncmp(callname, "afl-clang-lto", 13) == 0 || + 1. may have various OOB traps :) if ... doesn't contain ',' or + the input has bad syntax such as "-fsantiz=," + 2. strips any fuzzer* in ... and writes back (may result in "-fsanitize=") + 3. rets 1 if exactly "fuzzer" found, otherwise rets 0 +*/ +static u8 fsanitize_fuzzer_comma(char *string) { - strncmp(callname, "afl-lto", 7) == 0) { + u8 detect_single_fuzzer = 0; - compiler_mode = LTO; + char *p, *ptr = string + strlen("-fsanitize="); + // ck_alloc will check alloc failure + char *new = ck_alloc(strlen(string) + 1); + char *tmp = ck_alloc(strlen(ptr) + 1); + u32 count = 0, len, ende = 0; - } else + strcpy(new, "-fsanitize="); -#endif - if (strncmp(callname, "afl-gcc-fast", 12) == 0 || + do { - strncmp(callname, "afl-g++-fast", 12) == 0) { + p = strchr(ptr, ','); + if (!p) { - compiler_mode = GCC_PLUGIN; + p = ptr + strlen(ptr) + 1; + ende = 1; - } else if (strncmp(callname, "afl-gcc", 7) == 0 || + } - strncmp(callname, "afl-g++", 7) == 0) { + len = p - ptr; + if (len) { - compiler_mode = GCC; + strncpy(tmp, ptr, len); + tmp[len] = 0; + // fprintf(stderr, "Found: %s\n", tmp); + ptr += len + 1; + if (*tmp) { - } else if (strcmp(callname, "afl-clang") == 0 || + u32 copy = 1; + if (!strcmp(tmp, "fuzzer")) { - strcmp(callname, "afl-clang++") == 0) { + detect_single_fuzzer = 1; + copy = 0; - compiler_mode = CLANG; + } else if (!strncmp(tmp, "fuzzer", 6)) { - } + copy = 0; - if ((ptr = getenv("AFL_CC_COMPILER"))) { + } - if (compiler_mode) { + if (copy) { - if (!be_quiet) { + if (count) { strcat(new, ","); } + strcat(new, tmp); + ++count; - WARNF( - "\"AFL_CC_COMPILER\" is set but a specific compiler was already " - "selected by command line parameter or symlink, ignoring the " - "environment variable!"); + } } } else { - if (strncasecmp(ptr, "LTO", 3) == 0) { + ptr++; - compiler_mode = LTO; + } - } else if (strncasecmp(ptr, "LLVM", 4) == 0) { + } while (!ende); - compiler_mode = LLVM; + strcpy(string, new); - } else if (strncasecmp(ptr, "GCC_P", 5) == 0 || + ck_free(tmp); + ck_free(new); - strncasecmp(ptr, "GCC-P", 5) == 0 || - strncasecmp(ptr, "GCCP", 4) == 0) { + return detect_single_fuzzer; - compiler_mode = GCC_PLUGIN; +} - } else if (strcasecmp(ptr, "GCC") == 0) { +param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { - compiler_mode = GCC; + param_st final_ = PARAM_MISS; - } else + if (!strncmp(cur_argv, "-fsanitize-coverage-", 20) && + strstr(cur_argv, "list=")) { + + if (scan) { + + aflcc->have_instr_list = 1; + final_ = PARAM_SCAN; + + } else { - FATAL("Unknown AFL_CC_COMPILER mode: %s\n", ptr); + final_ = PARAM_KEEP; // may be set to DROP next } } - if (strcmp(callname, "afl-clang") == 0 || - strcmp(callname, "afl-clang++") == 0) { + if (!strcmp(cur_argv, "-fsanitize=fuzzer")) { - clang_mode = 1; - compiler_mode = CLANG; + if (scan) { - if (strcmp(callname, "afl-clang++") == 0) { plusplus_mode = 1; } + aflcc->need_aflpplib = 1; + final_ = PARAM_SCAN; - } + } else { - for (i = 1; i < argc; i++) { + final_ = PARAM_DROP; - if (strncmp(argv[i], "--afl", 5) == 0) { + } - if (!strcmp(argv[i], "--afl_noopt") || !strcmp(argv[i], "--afl-noopt")) { + } else if (!strncmp(cur_argv, "-fsanitize=", strlen("-fsanitize=")) && - passthrough = 1; - argv[i] = "-g"; // we have to overwrite it, -g is always good - continue; + strchr(cur_argv, ',') && + !strstr(cur_argv, "=,")) { // avoid OOB errors - } + if (scan) { - if (compiler_mode && !be_quiet) { + u8 *cur_argv_ = ck_strdup(cur_argv); - WARNF( - "--afl-... compiler mode supersedes the AFL_CC_COMPILER and " - "symlink compiler selection!"); + if (fsanitize_fuzzer_comma(cur_argv_)) { + + aflcc->need_aflpplib = 1; + final_ = PARAM_SCAN; } - ptr = argv[i]; - ptr += 5; - while (*ptr == '-') - ptr++; + ck_free(cur_argv_); - if (strncasecmp(ptr, "LTO", 3) == 0) { + } else { - compiler_mode = LTO; + fsanitize_fuzzer_comma(cur_argv); + if (!cur_argv || strlen(cur_argv) <= strlen("-fsanitize=")) + final_ = PARAM_DROP; // this means it only has "fuzzer" previously. - } else if (strncasecmp(ptr, "LLVM", 4) == 0) { + } - compiler_mode = LLVM; + } else if ((!strncmp(cur_argv, "-fsanitize=fuzzer-", - } else if (strncasecmp(ptr, "PCGUARD", 7) == 0 || + strlen("-fsanitize=fuzzer-")) || + !strncmp(cur_argv, "-fsanitize-coverage", + strlen("-fsanitize-coverage"))) && + (strncmp(cur_argv, "sanitize-coverage-allow", + strlen("sanitize-coverage-allow")) && + strncmp(cur_argv, "sanitize-coverage-deny", + strlen("sanitize-coverage-deny")) && + aflcc->instrument_mode != INSTRUMENT_LLVMNATIVE)) { - strncasecmp(ptr, "PC-GUARD", 8) == 0) { + if (scan) { - compiler_mode = LLVM; - instrument_mode = INSTRUMENT_PCGUARD; + final_ = PARAM_SCAN; - } else if (strcasecmp(ptr, "INSTRIM") == 0 || + } else { - strcasecmp(ptr, "CFG") == 0) { + if (!be_quiet) { WARNF("Found '%s' - stripping!", cur_argv); } + final_ = PARAM_DROP; - FATAL( - "InsTrim instrumentation was removed. Use a modern LLVM and " - "PCGUARD (default in afl-cc).\n"); + } - } else if (strcasecmp(ptr, "AFL") == 0 || + } - strcasecmp(ptr, "CLASSIC") == 0) { + if (!strcmp(cur_argv, "-fsanitize=address") || + !strcmp(cur_argv, "-fsanitize=memory")) { - compiler_mode = LLVM; - instrument_mode = INSTRUMENT_CLASSIC; + if (scan) { - } else if (strcasecmp(ptr, "LLVMNATIVE") == 0 || + // "-fsanitize=undefined,address" may be un-treated, but it's OK. + aflcc->asan_set = 1; + final_ = PARAM_SCAN; - strcasecmp(ptr, "NATIVE") == 0 || - strcasecmp(ptr, "LLVM-NATIVE") == 0) { + } else { - compiler_mode = LLVM; - instrument_mode = INSTRUMENT_LLVMNATIVE; + // It's impossible that final_ is PARAM_DROP before, + // so no checks are needed here. + final_ = PARAM_KEEP; - } else if (strncasecmp(ptr, "GCC_P", 5) == 0 || + } - strncasecmp(ptr, "GCC-P", 5) == 0 || - strncasecmp(ptr, "GCCP", 4) == 0) { + } - compiler_mode = GCC_PLUGIN; + if (final_ == PARAM_KEEP) insert_param(aflcc, cur_argv); - } else if (strcasecmp(ptr, "GCC") == 0) { + return final_; - compiler_mode = GCC; +} - } else if (strncasecmp(ptr, "CLANG", 5) == 0) { +void add_sanitizers(aflcc_state_t *aflcc, char **envp) { - compiler_mode = CLANG; + if (!aflcc->asan_set) { - } else + if (getenv("AFL_USE_ASAN")) { - FATAL("Unknown --afl-... compiler mode: %s\n", argv[i]); + if (getenv("AFL_USE_MSAN")) FATAL("ASAN and MSAN are mutually exclusive"); - } + if (getenv("AFL_HARDEN")) + FATAL("ASAN and AFL_HARDEN are mutually exclusive"); - } + add_defs_fortify(aflcc, 0); + insert_param(aflcc, "-fsanitize=address"); - if (strlen(callname) > 2 && - (strncmp(callname + strlen(callname) - 2, "++", 2) == 0 || - strstr(callname, "-g++") != NULL)) - plusplus_mode = 1; + } else if (getenv("AFL_USE_MSAN")) { - if (getenv("USE_TRACE_PC") || getenv("AFL_USE_TRACE_PC") || - getenv("AFL_LLVM_USE_TRACE_PC") || getenv("AFL_TRACE_PC")) { + if (getenv("AFL_USE_ASAN")) FATAL("ASAN and MSAN are mutually exclusive"); - if (instrument_mode == 0) - instrument_mode = INSTRUMENT_PCGUARD; - else if (instrument_mode != INSTRUMENT_PCGUARD) - FATAL("you cannot set AFL_LLVM_INSTRUMENT and AFL_TRACE_PC together"); + if (getenv("AFL_HARDEN")) + FATAL("MSAN and AFL_HARDEN are mutually exclusive"); + + add_defs_fortify(aflcc, 0); + insert_param(aflcc, "-fsanitize=memory"); + + } } - if (have_instr_env && getenv("AFL_DONT_OPTIMIZE") && !be_quiet) { + if (getenv("AFL_USE_UBSAN")) { - WARNF( - "AFL_LLVM_ALLOWLIST/DENYLIST and AFL_DONT_OPTIMIZE cannot be combined " - "for file matching, only function matching!"); + insert_param(aflcc, "-fsanitize=undefined"); + insert_param(aflcc, "-fsanitize-undefined-trap-on-error"); + insert_param(aflcc, "-fno-sanitize-recover=all"); + insert_param(aflcc, "-fno-omit-frame-pointer"); } - if (getenv("AFL_LLVM_INSTRIM") || getenv("INSTRIM") || - getenv("INSTRIM_LIB")) { + if (getenv("AFL_USE_TSAN")) { - FATAL( - "InsTrim instrumentation was removed. Use a modern LLVM and PCGUARD " - "(default in afl-cc).\n"); + insert_param(aflcc, "-fsanitize=thread"); + insert_param(aflcc, "-fno-omit-frame-pointer"); } - if (getenv("AFL_LLVM_CTX")) instrument_opt_mode |= INSTRUMENT_OPT_CTX; - if (getenv("AFL_LLVM_CALLER")) instrument_opt_mode |= INSTRUMENT_OPT_CALLER; - - if (getenv("AFL_LLVM_NGRAM_SIZE")) { + if (getenv("AFL_USE_LSAN")) { - instrument_opt_mode |= INSTRUMENT_OPT_NGRAM; - ngram_size = atoi(getenv("AFL_LLVM_NGRAM_SIZE")); - if (ngram_size < 2 || ngram_size > NGRAM_SIZE_MAX) - FATAL( - "NGRAM instrumentation mode must be between 2 and NGRAM_SIZE_MAX " - "(%u)", - NGRAM_SIZE_MAX); + insert_param(aflcc, "-fsanitize=leak"); + add_defs_lsan_ctrl(aflcc); } - if (getenv("AFL_LLVM_CTX_K")) { + if (getenv("AFL_USE_CFISAN")) { - ctx_k = atoi(getenv("AFL_LLVM_CTX_K")); - if (ctx_k < 1 || ctx_k > CTX_MAX_K) - FATAL("K-CTX instrumentation mode must be between 1 and CTX_MAX_K (%u)", - CTX_MAX_K); - if (ctx_k == 1) { + if (aflcc->compiler_mode == GCC_PLUGIN || aflcc->compiler_mode == GCC) { - setenv("AFL_LLVM_CALLER", "1", 1); - unsetenv("AFL_LLVM_CTX_K"); - instrument_opt_mode |= INSTRUMENT_OPT_CALLER; + insert_param(aflcc, "-fcf-protection=full"); } else { - instrument_opt_mode |= INSTRUMENT_OPT_CTX_K; + if (!aflcc->lto_mode) { + + uint32_t i = 0, found = 0; + while (envp[i] != NULL && !found) + if (strncmp("-flto", envp[i++], 5) == 0) found = 1; + if (!found) insert_param(aflcc, "-flto"); + + } + + insert_param(aflcc, "-fsanitize=cfi"); + insert_param(aflcc, "-fvisibility=hidden"); } } - if (getenv("AFL_LLVM_INSTRUMENT")) { +} - u8 *ptr2 = strtok(getenv("AFL_LLVM_INSTRUMENT"), ":,;"); +void add_native_pcguard(aflcc_state_t *aflcc) { - while (ptr2) { + /* If llvm-config doesn't figure out LLVM_MAJOR, just + go on anyway and let compiler complain if doesn't work. */ - if (strncasecmp(ptr2, "afl", strlen("afl")) == 0 || - strncasecmp(ptr2, "classic", strlen("classic")) == 0) { + if (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CODECOV) { - if (instrument_mode == INSTRUMENT_LTO) { +#if LLVM_MAJOR > 0 && LLVM_MAJOR < 6 + FATAL("pcguard instrumentation with pc-table requires LLVM 6.0.1+"); +#else + #if LLVM_MAJOR == 0 + WARNF( + "pcguard instrumentation with pc-table requires LLVM 6.0.1+" + " otherwise the compiler will fail"); + #endif + insert_param(aflcc, + "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table"); +#endif - instrument_mode = INSTRUMENT_CLASSIC; - lto_mode = 1; + } else { - } else if (!instrument_mode || instrument_mode == INSTRUMENT_AFL) { +#if LLVM_MAJOR > 0 && LLVM_MAJOR < 4 + FATAL("pcguard instrumentation requires LLVM 4.0.1+"); +#else + #if LLVM_MAJOR == 0 + WARNF( + "pcguard instrumentation requires LLVM 4.0.1+" + " otherwise the compiler will fail"); + #endif + insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); +#endif - instrument_mode = INSTRUMENT_AFL; + } - } else { +} - FATAL("main instrumentation mode already set with %s", - instrument_mode_string[instrument_mode]); +void add_optimized_pcguard(aflcc_state_t *aflcc) { - } +#if LLVM_MAJOR >= 13 + #if defined __ANDROID__ || ANDROID - } + insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; - if (strncasecmp(ptr2, "pc-guard", strlen("pc-guard")) == 0 || - strncasecmp(ptr2, "pcguard", strlen("pcguard")) == 0) { + #else - if (!instrument_mode || instrument_mode == INSTRUMENT_PCGUARD) - instrument_mode = INSTRUMENT_PCGUARD; - else - FATAL("main instrumentation mode already set with %s", - instrument_mode_string[instrument_mode]); + if (aflcc->have_instr_list) { - } + if (!be_quiet) + SAYF( + "Using unoptimized trace-pc-guard, due usage of " + "-fsanitize-coverage-allow/denylist, you can use " + "AFL_LLVM_ALLOWLIST/AFL_LLMV_DENYLIST instead.\n"); - if (strncasecmp(ptr2, "llvmnative", strlen("llvmnative")) == 0 || - strncasecmp(ptr2, "llvm-native", strlen("llvm-native")) == 0 || - strncasecmp(ptr2, "native", strlen("native")) == 0) { + insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; - if (!instrument_mode || instrument_mode == INSTRUMENT_LLVMNATIVE) - instrument_mode = INSTRUMENT_LLVMNATIVE; - else - FATAL("main instrumentation mode already set with %s", - instrument_mode_string[instrument_mode]); + } else { - } + /* Since LLVM_MAJOR >= 13 we use new pass manager */ + #if LLVM_MAJOR < 16 + insert_param(aflcc, "-fexperimental-new-pass-manager"); + #endif + insert_object(aflcc, "SanitizerCoveragePCGUARD.so", "-fpass-plugin=%s", 0); - if (strncasecmp(ptr2, "llvmcodecov", strlen("llvmcodecov")) == 0 || - strncasecmp(ptr2, "llvm-codecov", strlen("llvm-codecov")) == 0) { + } - if (!instrument_mode || instrument_mode == INSTRUMENT_LLVMNATIVE) { + #endif // defined __ANDROID__ || ANDROID +#else // LLVM_MAJOR < 13 + #if LLVM_MAJOR >= 4 - instrument_mode = INSTRUMENT_LLVMNATIVE; - instrument_opt_mode |= INSTRUMENT_OPT_CODECOV; + if (!be_quiet) + SAYF( + "Using unoptimized trace-pc-guard, upgrade to LLVM 13+ for " + "enhanced version.\n"); + insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; - } else { + #else - FATAL("main instrumentation mode already set with %s", - instrument_mode_string[instrument_mode]); + FATAL("pcguard instrumentation requires LLVM 4.0.1+"); - } + #endif +#endif - } +} - if (strncasecmp(ptr2, "cfg", strlen("cfg")) == 0 || - strncasecmp(ptr2, "instrim", strlen("instrim")) == 0) { +/* Linking behaviors */ - FATAL( - "InsTrim instrumentation was removed. Use a modern LLVM and " - "PCGUARD (default in afl-cc).\n"); +param_st parse_linking_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan, + u8 *skip_next, char **argv) { - } + if (aflcc->lto_mode && !strncmp(cur_argv, "-flto=thin", 10)) { - if (strncasecmp(ptr2, "lto", strlen("lto")) == 0) { + FATAL( + "afl-clang-lto cannot work with -flto=thin. Switch to -flto=full or " + "use afl-clang-fast!"); - lto_mode = 1; - if (!instrument_mode || instrument_mode == INSTRUMENT_LTO) - instrument_mode = INSTRUMENT_LTO; - else - FATAL("main instrumentation mode already set with %s", - instrument_mode_string[instrument_mode]); + } - } + param_st final_ = PARAM_MISS; - if (strcasecmp(ptr2, "gcc") == 0) { + if (!strcmp(cur_argv, "-shared") || !strcmp(cur_argv, "-dynamiclib")) { - if (!instrument_mode || instrument_mode == INSTRUMENT_GCC) - instrument_mode = INSTRUMENT_GCC; - else if (instrument_mode != INSTRUMENT_GCC) - FATAL("main instrumentation mode already set with %s", - instrument_mode_string[instrument_mode]); - compiler_mode = GCC; + if (scan) { - } + aflcc->shared_linking = 1; + final_ = PARAM_SCAN; - if (strcasecmp(ptr2, "clang") == 0) { + } else { - if (!instrument_mode || instrument_mode == INSTRUMENT_CLANG) - instrument_mode = INSTRUMENT_CLANG; - else if (instrument_mode != INSTRUMENT_CLANG) - FATAL("main instrumentation mode already set with %s", - instrument_mode_string[instrument_mode]); - compiler_mode = CLANG; + final_ = PARAM_KEEP; - } + } - if (strncasecmp(ptr2, "ctx-", strlen("ctx-")) == 0 || - strncasecmp(ptr2, "kctx-", strlen("c-ctx-")) == 0 || - strncasecmp(ptr2, "k-ctx-", strlen("k-ctx-")) == 0) { + } else if (!strcmp(cur_argv, "-Wl,-r") || !strcmp(cur_argv, "-Wl,-i") || - u8 *ptr3 = ptr2; - while (*ptr3 && (*ptr3 < '0' || *ptr3 > '9')) - ptr3++; + !strcmp(cur_argv, "-Wl,--relocatable") || + !strcmp(cur_argv, "-r") || !strcmp(cur_argv, "--relocatable")) { - if (!*ptr3) { + if (scan) { - if ((ptr3 = getenv("AFL_LLVM_CTX_K")) == NULL) - FATAL( - "you must set the K-CTX K with (e.g. for value 2) " - "AFL_LLVM_INSTRUMENT=ctx-2"); + aflcc->partial_linking = 1; + final_ = PARAM_SCAN; - } + } else { - ctx_k = atoi(ptr3); - if (ctx_k < 1 || ctx_k > CTX_MAX_K) - FATAL( - "K-CTX instrumentation option must be between 1 and CTX_MAX_K " - "(%u)", - CTX_MAX_K); + final_ = PARAM_KEEP; - if (ctx_k == 1) { + } - instrument_opt_mode |= INSTRUMENT_OPT_CALLER; - setenv("AFL_LLVM_CALLER", "1", 1); - unsetenv("AFL_LLVM_CTX_K"); + } else if (!strncmp(cur_argv, "-fuse-ld=", 9) || - } else { + !strncmp(cur_argv, "--ld-path=", 10)) { - instrument_opt_mode |= (INSTRUMENT_OPT_CTX_K); - u8 *ptr4 = alloc_printf("%u", ctx_k); - setenv("AFL_LLVM_CTX_K", ptr4, 1); + if (scan) { - } + final_ = PARAM_SCAN; - } + } else { - if (strcasecmp(ptr2, "ctx") == 0) { + if (aflcc->lto_mode) + final_ = PARAM_DROP; + else + final_ = PARAM_KEEP; - instrument_opt_mode |= INSTRUMENT_OPT_CTX; - setenv("AFL_LLVM_CTX", "1", 1); + } - } + } else if (!strcmp(cur_argv, "-Wl,-z,defs") || - if (strncasecmp(ptr2, "caller", strlen("caller")) == 0) { + !strcmp(cur_argv, "-Wl,--no-undefined") || + !strcmp(cur_argv, "-Wl,-no-undefined") || + !strcmp(cur_argv, "--no-undefined") || + strstr(cur_argv, "afl-compiler-rt") || + strstr(cur_argv, "afl-llvm-rt")) { - instrument_opt_mode |= INSTRUMENT_OPT_CALLER; - setenv("AFL_LLVM_CALLER", "1", 1); + if (scan) { - } + final_ = PARAM_SCAN; - if (strncasecmp(ptr2, "ngram", strlen("ngram")) == 0) { + } else { - u8 *ptr3 = ptr2 + strlen("ngram"); - while (*ptr3 && (*ptr3 < '0' || *ptr3 > '9')) - ptr3++; + final_ = PARAM_DROP; - if (!*ptr3) { + } - if ((ptr3 = getenv("AFL_LLVM_NGRAM_SIZE")) == NULL) - FATAL( - "you must set the NGRAM size with (e.g. for value 2) " - "AFL_LLVM_INSTRUMENT=ngram-2"); + } else if (!strcmp(cur_argv, "-z") || !strcmp(cur_argv, "-Wl,-z")) { - } + u8 *param = *(argv + 1); + if (param && (!strcmp(param, "defs") || !strcmp(param, "-Wl,defs"))) { - ngram_size = atoi(ptr3); - if (ngram_size < 2 || ngram_size > NGRAM_SIZE_MAX) - FATAL( - "NGRAM instrumentation option must be between 2 and " - "NGRAM_SIZE_MAX (%u)", - NGRAM_SIZE_MAX); - instrument_opt_mode |= (INSTRUMENT_OPT_NGRAM); - u8 *ptr4 = alloc_printf("%u", ngram_size); - setenv("AFL_LLVM_NGRAM_SIZE", ptr4, 1); + *skip_next = 1; - } + if (scan) { - ptr2 = strtok(NULL, ":,;"); + final_ = PARAM_SCAN; - } + } else { - } + final_ = PARAM_DROP; - if ((instrument_opt_mode & INSTRUMENT_OPT_CTX) && - (instrument_opt_mode & INSTRUMENT_OPT_CALLER)) { + } - FATAL("you cannot set CTX and CALLER together"); + } } - if ((instrument_opt_mode & INSTRUMENT_OPT_CTX) && - (instrument_opt_mode & INSTRUMENT_OPT_CTX_K)) { + // Try to warn user for some unsupported cases + if (scan && final_ == PARAM_MISS) { - FATAL("you cannot set CTX and K-CTX together"); + u8 *ptr_ = NULL; - } + if (!strcmp(cur_argv, "-Xlinker") && (ptr_ = *(argv + 1))) { - if ((instrument_opt_mode & INSTRUMENT_OPT_CALLER) && - (instrument_opt_mode & INSTRUMENT_OPT_CTX_K)) { + if (!strcmp(ptr_, "defs")) { - FATAL("you cannot set CALLER and K-CTX together"); + WARNF("'-Xlinker' 'defs' detected. This may result in a bad link."); - } + } else if (strstr(ptr_, "-no-undefined")) { - if (instrument_opt_mode && instrument_mode == INSTRUMENT_DEFAULT && - (compiler_mode == LLVM || compiler_mode == UNSET)) { + WARNF( + "'-Xlinker' '%s' detected. The latter option may be dropped and " + "result in a bad link.", + ptr_); - instrument_mode = INSTRUMENT_CLASSIC; - compiler_mode = LLVM; + } - } + } else if (!strncmp(cur_argv, "-Wl,", 4) && - if (!compiler_mode) { + (u8 *)strrchr(cur_argv, ',') != (cur_argv + 3)) { - // lto is not a default because outside of afl-cc RANLIB and AR have to - // be set to LLVM versions so this would work - if (have_llvm) - compiler_mode = LLVM; - else if (have_gcc_plugin) - compiler_mode = GCC_PLUGIN; - else if (have_gcc) -#ifdef __APPLE__ - // on OSX clang masquerades as GCC - compiler_mode = CLANG; -#else - compiler_mode = GCC; -#endif - else if (have_lto) - compiler_mode = LTO; - else - FATAL("no compiler mode available"); + ptr_ = cur_argv + 4; - } + if (strstr(ptr_, "-shared") || strstr(ptr_, "-dynamiclib")) { - /* if our PCGUARD implementation is not available then silently switch to - native LLVM PCGUARD */ - if (compiler_mode == CLANG && - (instrument_mode == INSTRUMENT_DEFAULT || - instrument_mode == INSTRUMENT_PCGUARD) && - find_object("SanitizerCoveragePCGUARD.so", argv[0]) == NULL) { + WARNF( + "'%s': multiple link options after '-Wl,' may break shared " + "linking.", + ptr_); - instrument_mode = INSTRUMENT_LLVMNATIVE; + } - } + if (strstr(ptr_, "-r,") || strstr(ptr_, "-i,") || strstr(ptr_, ",-r") || + strstr(ptr_, ",-i") || strstr(ptr_, "--relocatable")) { - if (compiler_mode == GCC) { + WARNF( + "'%s': multiple link options after '-Wl,' may break partial " + "linking.", + ptr_); - if (clang_mode) { + } - instrument_mode = INSTRUMENT_CLANG; + if (strstr(ptr_, "defs") || strstr(ptr_, "no-undefined")) { - } else { + WARNF( + "'%s': multiple link options after '-Wl,' may enable report " + "unresolved symbol references and result in a bad link.", + ptr_); - instrument_mode = INSTRUMENT_GCC; + } } } - if (compiler_mode == CLANG) { + if (final_ == PARAM_KEEP) insert_param(aflcc, cur_argv); - instrument_mode = INSTRUMENT_CLANG; - setenv(CLANG_ENV_VAR, "1", 1); // used by afl-as + return final_; - } +} + +void add_lto_linker(aflcc_state_t *aflcc) { + + unsetenv("AFL_LD"); + unsetenv("AFL_LD_CALLER"); + + u8 *ld_path = NULL; + if (getenv("AFL_REAL_LD")) { + + ld_path = strdup(getenv("AFL_REAL_LD")); + + } else { + + ld_path = strdup(AFL_REAL_LD); + + } + + if (!ld_path || !*ld_path) { + + if (ld_path) { + + // Freeing empty string + free(ld_path); + + } + + ld_path = strdup("ld.lld"); + + } + + if (!ld_path) { PFATAL("Could not allocate mem for ld_path"); } +#if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 12 + insert_param(aflcc, alloc_printf("--ld-path=%s", ld_path)); +#else + insert_param(aflcc, alloc_printf("-fuse-ld=%s", ld_path)); +#endif + free(ld_path); + +} + +void add_lto_passes(aflcc_state_t *aflcc) { + +#if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 15 + // The NewPM implementation only works fully since LLVM 15. + insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,--load-pass-plugin=%s", + 0); +#elif defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 13 + insert_param(aflcc, "-Wl,--lto-legacy-pass-manager"); + insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,-mllvm=-load=%s", 0); +#else + insert_param(aflcc, "-fno-experimental-new-pass-manager"); + insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,-mllvm=-load=%s", 0); +#endif + + insert_param(aflcc, "-Wl,--allow-multiple-definition"); + +} + +static void add_aflpplib(aflcc_state_t *aflcc) { + + if (!aflcc->need_aflpplib) return; + + u8 *afllib = find_object(aflcc, "libAFLDriver.a"); + + if (!be_quiet) { + + OKF("Found '-fsanitize=fuzzer', replacing with libAFLDriver.a"); + + } + + if (!afllib) { + + if (!be_quiet) { + + WARNF( + "Cannot find 'libAFLDriver.a' to replace '-fsanitize=fuzzer' in " + "the flags - this will fail!"); + + } + + } else { + + insert_param(aflcc, afllib); + +#ifdef __APPLE__ + insert_param(aflcc, "-Wl,-undefined"); + insert_param(aflcc, "dynamic_lookup"); +#endif + + } + +} + +void add_runtime(aflcc_state_t *aflcc) { + + if (aflcc->preprocessor_only || aflcc->have_c || !aflcc->non_dash) { + + /* In the preprocessor_only case (-E), we are not actually compiling at + all but requesting the compiler to output preprocessed sources only. + We must not add the runtime in this case because the compiler will + simply output its binary content back on stdout, breaking any build + systems that rely on a separate source preprocessing step. */ + return; + + } + + if (aflcc->compiler_mode != GCC_PLUGIN && aflcc->compiler_mode != GCC && + !getenv("AFL_LLVM_NO_RPATH")) { + + // in case LLVM is installed not via a package manager or "make install" + // e.g. compiled download or compiled from github then its ./lib directory + // might not be in the search path. Add it if so. + const char *libdir = LLVM_LIBDIR; + if (aflcc->plusplus_mode && strlen(libdir) && strncmp(libdir, "/usr", 4) && + strncmp(libdir, "/lib", 4)) { + + u8 *libdir_opt = strdup("-Wl,-rpath=" LLVM_LIBDIR); + insert_param(aflcc, libdir_opt); + + } + + } + +#ifndef __ANDROID__ + + #define M32_ERR_MSG "-m32 is not supported by your compiler" + #define M64_ERR_MSG "-m64 is not supported by your compiler" + + if (aflcc->compiler_mode != GCC && aflcc->compiler_mode != CLANG) { + + switch (aflcc->bit_mode) { + + case 0: + if (!aflcc->shared_linking && !aflcc->partial_linking) + insert_object(aflcc, "afl-compiler-rt.o", 0, 0); + if (aflcc->lto_mode) insert_object(aflcc, "afl-llvm-rt-lto.o", 0, 0); + break; + + case 32: + if (!aflcc->shared_linking && !aflcc->partial_linking) + insert_object(aflcc, "afl-compiler-rt-32.o", 0, M32_ERR_MSG); + if (aflcc->lto_mode) + insert_object(aflcc, "afl-llvm-rt-lto-32.o", 0, M32_ERR_MSG); + break; + + case 64: + if (!aflcc->shared_linking && !aflcc->partial_linking) + insert_object(aflcc, "afl-compiler-rt-64.o", 0, M64_ERR_MSG); + if (aflcc->lto_mode) + insert_object(aflcc, "afl-llvm-rt-lto-64.o", 0, M64_ERR_MSG); + break; + + } + + #if !defined(__APPLE__) && !defined(__sun) + if (!aflcc->shared_linking && !aflcc->partial_linking) + insert_object(aflcc, "dynamic_list.txt", "-Wl,--dynamic-list=%s", 0); + #endif + + #if defined(__APPLE__) + if (aflcc->shared_linking || aflcc->partial_linking) { + + insert_param(aflcc, "-Wl,-U"); + insert_param(aflcc, "-Wl,___afl_area_ptr"); + insert_param(aflcc, "-Wl,-U"); + insert_param(aflcc, "-Wl,___sanitizer_cov_trace_pc_guard_init"); + + } + + #endif + + } + +#endif + + add_aflpplib(aflcc); + +#if defined(USEMMAP) && !defined(__HAIKU__) && !__APPLE__ + insert_param(aflcc, "-Wl,-lrt"); +#endif + +} + +/* Misc */ + +void add_assembler(aflcc_state_t *aflcc) { + + u8 *afl_as = find_object(aflcc, "as"); + + if (!afl_as) FATAL("Cannot find 'as' (symlink to 'afl-as')."); + + u8 *slash = strrchr(afl_as, '/'); + if (slash) *slash = 0; + + insert_param(aflcc, "-B"); + insert_param(aflcc, afl_as); + + if (aflcc->compiler_mode == CLANG) insert_param(aflcc, "-no-integrated-as"); + +} + +void add_gcc_plugin(aflcc_state_t *aflcc) { + + if (aflcc->cmplog_mode) { + + insert_object(aflcc, "afl-gcc-cmplog-pass.so", "-fplugin=%s", 0); + insert_object(aflcc, "afl-gcc-cmptrs-pass.so", "-fplugin=%s", 0); + + } + + insert_object(aflcc, "afl-gcc-pass.so", "-fplugin=%s", 0); + + insert_param(aflcc, "-fno-if-conversion"); + insert_param(aflcc, "-fno-if-conversion2"); + +} + +void add_misc_params(aflcc_state_t *aflcc) { + + if (getenv("AFL_NO_BUILTIN") || getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES") || + getenv("AFL_LLVM_LAF_ALL") || getenv("AFL_LLVM_CMPLOG") || + aflcc->lto_mode) { + + insert_param(aflcc, "-fno-builtin-strcmp"); + insert_param(aflcc, "-fno-builtin-strncmp"); + insert_param(aflcc, "-fno-builtin-strcasecmp"); + insert_param(aflcc, "-fno-builtin-strncasecmp"); + insert_param(aflcc, "-fno-builtin-memcmp"); + insert_param(aflcc, "-fno-builtin-bcmp"); + insert_param(aflcc, "-fno-builtin-strstr"); + insert_param(aflcc, "-fno-builtin-strcasestr"); + + } + + if (!aflcc->have_pic) { insert_param(aflcc, "-fPIC"); } + + if (getenv("AFL_HARDEN")) { + + insert_param(aflcc, "-fstack-protector-all"); + + if (!aflcc->fortify_set) add_defs_fortify(aflcc, 2); + + } + + if (!getenv("AFL_DONT_OPTIMIZE")) { + + insert_param(aflcc, "-g"); + if (!aflcc->have_o) insert_param(aflcc, "-O3"); + if (!aflcc->have_unroll) insert_param(aflcc, "-funroll-loops"); + // if (strlen(aflcc->march_opt) > 1 && aflcc->march_opt[0] == '-') + // insert_param(aflcc, aflcc->march_opt); + + } + + if (aflcc->x_set) { + + insert_param(aflcc, "-x"); + insert_param(aflcc, "none"); + + } + +} + +param_st parse_misc_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { + + param_st final_ = PARAM_MISS; + +// MACRO START +#define SCAN_KEEP(dst, src) \ + do { \ + \ + if (scan) { \ + \ + dst = src; \ + final_ = PARAM_SCAN; \ + \ + } else { \ + \ + final_ = PARAM_KEEP; \ + \ + } \ + \ + } while (0) + + // MACRO END + + if (!strncasecmp(cur_argv, "-fpic", 5)) { + + SCAN_KEEP(aflcc->have_pic, 1); + + } else if (!strcmp(cur_argv, "-m32") || + + !strcmp(cur_argv, "armv7a-linux-androideabi")) { + + SCAN_KEEP(aflcc->bit_mode, 32); + + } else if (!strcmp(cur_argv, "-m64")) { + + SCAN_KEEP(aflcc->bit_mode, 64); + + } else if (strstr(cur_argv, "FORTIFY_SOURCE")) { + + SCAN_KEEP(aflcc->fortify_set, 1); + + } else if (!strcmp(cur_argv, "-x")) { + + SCAN_KEEP(aflcc->x_set, 1); + + } else if (!strcmp(cur_argv, "-E")) { + + SCAN_KEEP(aflcc->preprocessor_only, 1); + + } else if (!strcmp(cur_argv, "--target=wasm32-wasi")) { + + SCAN_KEEP(aflcc->passthrough, 1); + + } else if (!strcmp(cur_argv, "-c")) { + + SCAN_KEEP(aflcc->have_c, 1); + + } else if (!strncmp(cur_argv, "-O", 2)) { + + SCAN_KEEP(aflcc->have_o, 1); + + } else if (!strncmp(cur_argv, "-funroll-loop", 13)) { + + SCAN_KEEP(aflcc->have_unroll, 1); + + } else if (!strncmp(cur_argv, "--afl", 5)) { + + if (scan) + final_ = PARAM_SCAN; + else + final_ = PARAM_DROP; + + } else if (!strncmp(cur_argv, "-fno-unroll", 11)) { + + if (scan) + final_ = PARAM_SCAN; + else + final_ = PARAM_DROP; + + } else if (!strcmp(cur_argv, "-pipe") && aflcc->compiler_mode == GCC_PLUGIN) { + + if (scan) + final_ = PARAM_SCAN; + else + final_ = PARAM_DROP; + + } else if (!strncmp(cur_argv, "-stdlib=", 8) && + + (aflcc->compiler_mode == GCC || + aflcc->compiler_mode == GCC_PLUGIN)) { + + if (scan) { + + final_ = PARAM_SCAN; + + } else { + + if (!be_quiet) WARNF("Found '%s' - stripping!", cur_argv); + final_ = PARAM_DROP; + + } + + } else if (cur_argv[0] != '-') { + + /* It's a weak, loose pattern, with very different purpose + than others. We handle it at last, cautiously and robustly. */ + + if (scan && cur_argv[0] != '@') // response file support + aflcc->non_dash = 1; + + } + +#undef SCAN_KEEP + + if (final_ == PARAM_KEEP) insert_param(aflcc, cur_argv); + + return final_; + +} + +static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { if (argc < 2 || strncmp(argv[1], "-h", 2) == 0) { @@ -2168,16 +2559,22 @@ int main(int argc, char **argv, char **envp) { " [GCC/CLANG] simple gcc/clang: %s%s\n" " CLASSIC DEFAULT no no no no no " "no\n\n", - have_llvm ? "AVAILABLE" : "unavailable!", - compiler_mode == LLVM ? " [SELECTED]" : "", - have_llvm ? "AVAILABLE" : "unavailable!", - have_llvm ? "AVAILABLE" : "unavailable!", - have_lto ? "AVAILABLE" : "unavailable!", - compiler_mode == LTO ? " [SELECTED]" : "", - have_gcc_plugin ? "AVAILABLE" : "unavailable!", - compiler_mode == GCC_PLUGIN ? " [SELECTED]" : "", - have_gcc ? "AVAILABLE" : "unavailable!", - (compiler_mode == GCC || compiler_mode == CLANG) ? " [SELECTED]" : ""); + aflcc->have_llvm ? "AVAILABLE" : "unavailable!", + aflcc->compiler_mode == LLVM ? " [SELECTED]" : "", + aflcc->have_llvm ? "AVAILABLE" : "unavailable!", + aflcc->have_llvm ? "AVAILABLE" : "unavailable!", + aflcc->have_lto ? "AVAILABLE" : "unavailable!", + aflcc->compiler_mode == LTO ? " [SELECTED]" : "", + aflcc->have_gcc_plugin ? "AVAILABLE" : "unavailable!", + aflcc->compiler_mode == GCC_PLUGIN ? " [SELECTED]" : "", + aflcc->have_gcc && aflcc->have_clang + ? "AVAILABLE" + : (aflcc->have_gcc + ? "GCC ONLY " + : (aflcc->have_clang ? "CLANG ONLY" : "unavailable!")), + (aflcc->compiler_mode == GCC || aflcc->compiler_mode == CLANG) + ? " [SELECTED]" + : ""); SAYF( "Modes:\n" @@ -2266,7 +2663,7 @@ int main(int argc, char **argv, char **envp) { " AFL_USE_TSAN: activate thread sanitizer\n" " AFL_USE_LSAN: activate leak-checker sanitizer\n"); - if (have_gcc_plugin) + if (aflcc->have_gcc_plugin) SAYF( "\nGCC Plugin-specific environment variables:\n" " AFL_GCC_CMPLOG: log operands of comparisons (RedQueen mutator)\n" @@ -2282,7 +2679,7 @@ int main(int argc, char **argv, char **envp) { #define COUNTER_BEHAVIOUR \ " AFL_LLVM_NOT_ZERO: use cycling trace counters that skip zero\n" #endif - if (have_llvm) + if (aflcc->have_llvm) SAYF( "\nLLVM/LTO/afl-clang-fast/afl-clang-lto specific environment " "variables:\n" @@ -2310,7 +2707,7 @@ int main(int argc, char **argv, char **envp) { "instrument allow/\n" " deny listing (selective instrumentation)\n"); - if (have_llvm) + if (aflcc->have_llvm) SAYF( " AFL_LLVM_CMPLOG: log operands of comparisons (RedQueen " "mutator)\n" @@ -2329,7 +2726,7 @@ int main(int argc, char **argv, char **envp) { "locations\n"); #ifdef AFL_CLANG_FLTO - if (have_lto) + if (aflcc->have_lto) SAYF( "\nLTO/afl-clang-lto specific environment variables:\n" " AFL_LLVM_MAP_ADDR: use a fixed coverage map address (speed), " @@ -2365,9 +2762,9 @@ int main(int argc, char **argv, char **envp) { "targets.\n\n"); #if (LLVM_MAJOR >= 3) - if (have_lto) + if (aflcc->have_lto) SAYF("afl-cc LTO with ld=%s %s\n", AFL_REAL_LD, AFL_CLANG_FLTO); - if (have_llvm) + if (aflcc->have_llvm) SAYF("afl-cc LLVM version %d using the binary path \"%s\".\n", LLVM_MAJOR, LLVM_BINDIR); #endif @@ -2406,205 +2803,356 @@ int main(int argc, char **argv, char **envp) { } - if (compiler_mode == LTO) { +} - if (instrument_mode == 0 || instrument_mode == INSTRUMENT_LTO || - instrument_mode == INSTRUMENT_CFG || - instrument_mode == INSTRUMENT_PCGUARD) { +static void process_params(aflcc_state_t *aflcc, u8 scan, u32 argc, + char **argv) { - lto_mode = 1; - // force CFG - // if (!instrument_mode) { + limit_params(aflcc, argc); - instrument_mode = INSTRUMENT_PCGUARD; - // ptr = instrument_mode_string[instrument_mode]; - // } - - } else if (instrument_mode == INSTRUMENT_CLASSIC) { + // for (u32 x = 0; x < argc; ++x) fprintf(stderr, "[%u] %s\n", x, argv[x]); - lto_mode = 1; + /* Process the argument list. */ - } else { + u8 skip_next = 0; + while (--argc) { - if (!be_quiet) { + u8 *cur = *(++argv); - WARNF("afl-clang-lto called with mode %s, using that mode instead", - instrument_mode_string[instrument_mode]); + if (skip_next > 0) { - } + skip_next--; + continue; } - } + if (PARAM_MISS != parse_misc_params(aflcc, cur, scan)) continue; - if (instrument_mode == 0 && compiler_mode < GCC_PLUGIN) { + if (PARAM_MISS != parse_fsanitize(aflcc, cur, scan)) continue; -#if LLVM_MAJOR >= 7 - #if LLVM_MAJOR < 11 && (LLVM_MAJOR < 10 || LLVM_MINOR < 1) - if (have_instr_env) { + if (PARAM_MISS != parse_linking_params(aflcc, cur, scan, &skip_next, argv)) + continue; - instrument_mode = INSTRUMENT_AFL; - if (!be_quiet) { + if (*cur == '@') { - WARNF( - "Switching to classic instrumentation because " - "AFL_LLVM_ALLOWLIST/DENYLIST does not work with PCGUARD < 10.0.1."); + // response file support. + // we have two choices - move everything to the command line or + // rewrite the response files to temporary files and delete them + // afterwards. We choose the first for easiness. + // We do *not* support quotes in the rsp files to cope with spaces in + // filenames etc! If you need that then send a patch! + u8 *filename = cur + 1; + if (aflcc->debug) { DEBUGF("response file=%s\n", filename); } + FILE *f = fopen(filename, "r"); + struct stat st; + + // Check not found or empty? let the compiler complain if so. + if (!f || fstat(fileno(f), &st) < 0 || st.st_size < 1) { + + if (!scan) insert_param(aflcc, cur); + continue; } - } else + u8 *tmpbuf = malloc(st.st_size + 2), *ptr; + char **args = malloc(sizeof(char *) * (st.st_size >> 1)); + int count = 1, cont = 0, cont_act = 0; - #endif - instrument_mode = INSTRUMENT_PCGUARD; + while (fgets(tmpbuf, st.st_size + 1, f)) { -#else - instrument_mode = INSTRUMENT_AFL; -#endif + ptr = tmpbuf; + // fprintf(stderr, "1: %s\n", ptr); + // no leading whitespace + while (isspace(*ptr)) { - } + ++ptr; + cont_act = 0; - if (instrument_opt_mode && compiler_mode != LLVM) - FATAL("CTX, CALLER and NGRAM can only be used in LLVM mode"); + } - if (!instrument_opt_mode) { + // no comments, no empty lines + if (*ptr == '#' || *ptr == '\n' || !*ptr) { continue; } + // remove LF + if (ptr[strlen(ptr) - 1] == '\n') { ptr[strlen(ptr) - 1] = 0; } + // remove CR + if (*ptr && ptr[strlen(ptr) - 1] == '\r') { ptr[strlen(ptr) - 1] = 0; } + // handle \ at end of line + if (*ptr && ptr[strlen(ptr) - 1] == '\\') { - if (lto_mode && instrument_mode == INSTRUMENT_CFG) - instrument_mode = INSTRUMENT_PCGUARD; - ptr = instrument_mode_string[instrument_mode]; + cont = 1; + ptr[strlen(ptr) - 1] = 0; - } else { + } - char *ptr2 = alloc_printf(" + NGRAM-%u", ngram_size); - char *ptr3 = alloc_printf(" + K-CTX-%u", ctx_k); + // fprintf(stderr, "2: %s\n", ptr); - ptr = alloc_printf( - "%s%s%s%s%s", instrument_mode_string[instrument_mode], - (instrument_opt_mode & INSTRUMENT_OPT_CTX) ? " + CTX" : "", - (instrument_opt_mode & INSTRUMENT_OPT_CALLER) ? " + CALLER" : "", - (instrument_opt_mode & INSTRUMENT_OPT_NGRAM) ? ptr2 : "", - (instrument_opt_mode & INSTRUMENT_OPT_CTX_K) ? ptr3 : ""); + // remove whitespace at end + while (*ptr && isspace(ptr[strlen(ptr) - 1])) { - ck_free(ptr2); - ck_free(ptr3); + ptr[strlen(ptr) - 1] = 0; + cont = 0; - } + } -#ifndef AFL_CLANG_FLTO - if (lto_mode) - FATAL( - "instrumentation mode LTO specified but LLVM support not available " - "(requires LLVM 11 or higher)"); -#endif + // fprintf(stderr, "3: %s\n", ptr); + if (*ptr) { - if (instrument_opt_mode && instrument_opt_mode != INSTRUMENT_OPT_CODECOV && - instrument_mode != INSTRUMENT_CLASSIC) - FATAL( - "CALLER, CTX and NGRAM instrumentation options can only be used with " - "the LLVM CLASSIC instrumentation mode."); + do { - if (getenv("AFL_LLVM_SKIP_NEVERZERO") && getenv("AFL_LLVM_NOT_ZERO")) - FATAL( - "AFL_LLVM_NOT_ZERO and AFL_LLVM_SKIP_NEVERZERO can not be set " - "together"); + u8 *value = ptr; + while (*ptr && !isspace(*ptr)) { -#if LLVM_MAJOR < 11 && (LLVM_MAJOR < 10 || LLVM_MINOR < 1) - if (instrument_mode == INSTRUMENT_PCGUARD && have_instr_env) { + ++ptr; - FATAL( - "Instrumentation type PCGUARD does not support " - "AFL_LLVM_ALLOWLIST/DENYLIST! Use LLVM 10.0.1+ instead."); + } - } + while (*ptr && isspace(*ptr)) { -#endif + *ptr++ = 0; - u8 *ptr2; + } - if ((ptr2 = getenv("AFL_LLVM_DICT2FILE")) != NULL && *ptr2 != '/') - FATAL("AFL_LLVM_DICT2FILE must be set to an absolute file path"); + if (cont_act) { - if ((isatty(2) && !be_quiet) || debug) { + u32 len = strlen(args[count - 1]) + strlen(value) + 1; + u8 *tmp = malloc(len); + snprintf(tmp, len, "%s%s", args[count - 1], value); + free(args[count - 1]); + args[count - 1] = tmp; + cont_act = 0; - SAYF(cCYA - "afl-cc" VERSION cRST - " by Michal Zalewski, Laszlo Szekeres, Marc Heuse - mode: %s-%s\n", - compiler_mode_string[compiler_mode], ptr); + } else { - } + args[count++] = strdup(value); - if (!be_quiet && (compiler_mode == GCC || compiler_mode == CLANG)) { + } - WARNF( - "You are using outdated instrumentation, install LLVM and/or " - "gcc-plugin and use afl-clang-fast/afl-clang-lto/afl-gcc-fast " - "instead!"); + } while (*ptr); + + } + + if (cont) { + + cont_act = 1; + cont = 0; + + } + + } + + if (count) { process_params(aflcc, scan, count, args); } + + // we cannot free args[] unless we don't need + // to keep any reference in cc_params + if (scan) { + + if (count) do { + + free(args[--count]); + + } while (count); + + free(args); + + } + + free(tmpbuf); + + continue; + + } + + if (!scan) insert_param(aflcc, cur); } - if (debug) { +} - DEBUGF("cd '%s';", getthecwd()); - for (i = 0; i < argc; i++) - SAYF(" '%s'", argv[i]); - SAYF("\n"); - fflush(stdout); - fflush(stderr); +/* Copy argv to cc_params, making the necessary edits. */ + +static void edit_params(aflcc_state_t *aflcc, u32 argc, char **argv, + char **envp) { + + add_real_argv0(aflcc); + + // prevent unnecessary build errors + if (aflcc->compiler_mode != GCC_PLUGIN && aflcc->compiler_mode != GCC) { + + insert_param(aflcc, "-Wno-unused-command-line-argument"); } - if (getenv("AFL_LLVM_LAF_ALL")) { + if (aflcc->compiler_mode == GCC || aflcc->compiler_mode == CLANG) { - setenv("AFL_LLVM_LAF_SPLIT_SWITCHES", "1", 1); - setenv("AFL_LLVM_LAF_SPLIT_COMPARES", "1", 1); - setenv("AFL_LLVM_LAF_SPLIT_FLOATS", "1", 1); - setenv("AFL_LLVM_LAF_TRANSFORM_COMPARES", "1", 1); + add_assembler(aflcc); } - cmplog_mode = getenv("AFL_CMPLOG") || getenv("AFL_LLVM_CMPLOG") || - getenv("AFL_GCC_CMPLOG"); + if (aflcc->compiler_mode == GCC_PLUGIN) { add_gcc_plugin(aflcc); } -#if !defined(__ANDROID__) && !defined(ANDROID) - ptr = find_object("afl-compiler-rt.o", argv[0]); + if (aflcc->compiler_mode == LLVM || aflcc->compiler_mode == LTO) { - if (!ptr) { + if (aflcc->lto_mode && aflcc->have_instr_env) { - FATAL( - "Unable to find 'afl-compiler-rt.o'. Please set the AFL_PATH " - "environment variable."); + load_llvm_pass(aflcc, "afl-llvm-lto-instrumentlist.so"); - } + } - if (debug) { DEBUGF("rt=%s obj_path=%s\n", ptr, obj_path); } + if (getenv("AFL_LLVM_DICT2FILE")) { - ck_free(ptr); -#endif + load_llvm_pass(aflcc, "afl-llvm-dict2file.so"); - edit_params(argc, argv, envp); + } - if (debug) { + // laf + if (getenv("LAF_SPLIT_SWITCHES") || getenv("AFL_LLVM_LAF_SPLIT_SWITCHES")) { - DEBUGF("cd '%s';", getthecwd()); - for (i = 0; i < (s32)cc_par_cnt; i++) - SAYF(" '%s'", cc_params[i]); - SAYF("\n"); - fflush(stdout); - fflush(stderr); + load_llvm_pass(aflcc, "split-switches-pass.so"); + + } + + if (getenv("LAF_TRANSFORM_COMPARES") || + getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES")) { + + load_llvm_pass(aflcc, "compare-transform-pass.so"); + + } + + if (getenv("LAF_SPLIT_COMPARES") || getenv("AFL_LLVM_LAF_SPLIT_COMPARES") || + getenv("AFL_LLVM_LAF_SPLIT_FLOATS")) { + + load_llvm_pass(aflcc, "split-compares-pass.so"); + + } + + // /laf + + if (aflcc->cmplog_mode) { + + insert_param(aflcc, "-fno-inline"); + + load_llvm_pass(aflcc, "cmplog-switches-pass.so"); + // reuse split switches from laf + load_llvm_pass(aflcc, "split-switches-pass.so"); + + } + + // #if LLVM_MAJOR >= 13 + // // Use the old pass manager in LLVM 14 which the AFL++ passes still + // use. insert_param(aflcc, "-flegacy-pass-manager"); + // #endif + + if (aflcc->lto_mode) { + + insert_param(aflcc, aflcc->lto_flag); + + if (!aflcc->have_c) { + + add_lto_linker(aflcc); + add_lto_passes(aflcc); + + } + + } else { + + if (aflcc->instrument_mode == INSTRUMENT_PCGUARD) { + + add_optimized_pcguard(aflcc); + + } else if (aflcc->instrument_mode == INSTRUMENT_LLVMNATIVE) { + + add_native_pcguard(aflcc); + + } else { + + load_llvm_pass(aflcc, "afl-llvm-pass.so"); + + } + + } + + if (aflcc->cmplog_mode) { + + load_llvm_pass(aflcc, "cmplog-instructions-pass.so"); + load_llvm_pass(aflcc, "cmplog-routines-pass.so"); + + } + + if (getenv("AFL_LLVM_INJECTIONS_ALL") || + getenv("AFL_LLVM_INJECTIONS_SQL") || + getenv("AFL_LLVM_INJECTIONS_LDAP") || + getenv("AFL_LLVM_INJECTIONS_XSS")) { + + load_llvm_pass(aflcc, "injection-pass.so"); + + } + + // insert_param(aflcc, "-Qunused-arguments"); } - if (passthrough) { + /* Inspect the command line parameters. */ + + process_params(aflcc, 0, argc, argv); + + add_sanitizers(aflcc, envp); + + add_misc_params(aflcc); + + add_defs_common(aflcc); + add_defs_selective_instr(aflcc); + add_defs_persistent_mode(aflcc); + + add_runtime(aflcc); + + insert_param(aflcc, NULL); + +} + +/* Main entry point */ + +int main(int argc, char **argv, char **envp) { + + aflcc_state_t *aflcc = malloc(sizeof(aflcc_state_t)); + aflcc_state_init(aflcc, (u8 *)argv[0]); + + check_environment_vars(envp); + + find_built_deps(aflcc); + + compiler_mode_by_callname(aflcc); + compiler_mode_by_environ(aflcc); + compiler_mode_by_cmdline(aflcc, argc, argv); + + instrument_mode_by_environ(aflcc); + + mode_final_checkout(aflcc, argc, argv); + + process_params(aflcc, 1, argc, argv); + + maybe_usage(aflcc, argc, argv); + + mode_notification(aflcc); + + if (aflcc->debug) debugf_args(argc, argv); + + edit_params(aflcc, argc, argv, envp); + + if (aflcc->debug) + debugf_args((s32)aflcc->cc_par_cnt, (char **)aflcc->cc_params); + + if (aflcc->passthrough) { - argv[0] = cc_params[0]; - execvp(cc_params[0], (char **)argv); + argv[0] = aflcc->cc_params[0]; + execvp(aflcc->cc_params[0], (char **)argv); } else { - execvp(cc_params[0], (char **)cc_params); + execvp(aflcc->cc_params[0], (char **)aflcc->cc_params); } - FATAL("Oops, failed to execute '%s' - check your PATH", cc_params[0]); + FATAL("Oops, failed to execute '%s' - check your PATH", aflcc->cc_params[0]); return 0; diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 34a5ff81..1ee8ebe7 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -169,20 +169,16 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) { } - if (unlikely(afl->custom_mutators_count)) { - - LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { - - if (el->afl_custom_fuzz_send) { + LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { - el->afl_custom_fuzz_send(el->data, *mem, new_size); - sent = 1; + if (el->afl_custom_fuzz_send) { - } + el->afl_custom_fuzz_send(el->data, *mem, new_size); + sent = 1; - }); + } - } + }); if (likely(!sent)) { @@ -203,7 +199,7 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) { } - } else { + } else { /* !afl->custom_mutators_count */ if (unlikely(len < afl->min_length && !fix)) { @@ -215,27 +211,8 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) { } - if (unlikely(afl->custom_mutators_count)) { - - LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { - - if (el->afl_custom_fuzz_send) { - - el->afl_custom_fuzz_send(el->data, *mem, len); - sent = 1; - - } - - }); - - } - - if (likely(!sent)) { - - /* boring uncustom. */ - afl_fsrv_write_to_testcase(&afl->fsrv, *mem, len); - - } + /* boring uncustom. */ + afl_fsrv_write_to_testcase(&afl->fsrv, *mem, len); } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 17949fd7..2d5787e8 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1812,6 +1812,10 @@ int main(int argc, char **argv_orig, char **envp) { check_cpu_governor(afl); #endif + #ifdef __APPLE__ + setenv("DYLD_NO_PIE", "1", 0); + #endif + if (getenv("LD_PRELOAD")) { WARNF( -- cgit v1.2.3 From 660b697ed9d1d14987ffba4bf80ad4cbe6f29f95 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 19 Jan 2024 10:28:39 +0100 Subject: typos --- src/afl-cc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 192c5423..cda964df 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1180,11 +1180,11 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) { switch (aflcc->compiler_mode) { case GCC: - if (!aflcc->have_gcc) FATAL("afl-gcc not available on your platform!"); + if (!aflcc->have_gcc) FATAL("afl-gcc is not available on your platform!"); break; case CLANG: if (!aflcc->have_clang) - FATAL("afl-clang not available on your platform!"); + FATAL("afl-clang is not available on your platform!"); break; case LLVM: if (!aflcc->have_llvm) @@ -2538,11 +2538,11 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { "MODES: NCC PERSIST DICT LAF " "CMPLOG SELECT\n" " [LLVM] LLVM: %s%s\n" - " PCGUARD %s yes yes module yes yes " + " PCGUARD %s yes yes module yes yes " "yes\n" - " NATIVE AVAILABLE no yes no no " + " NATIVE AVAILABLE no yes no no " "part. yes\n" - " CLASSIC %s no yes module yes yes " + " CLASSIC %s no yes module yes yes " "yes\n" " - NORMAL\n" " - CALLER\n" -- cgit v1.2.3 From ab0823cd3bd0bf59e6fd1b29484e1529d055776b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 19 Jan 2024 15:51:57 +0100 Subject: apple fixes --- src/afl-cc.c | 30 ------------------------------ 1 file changed, 30 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index cda964df..5cbd964e 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -611,26 +611,18 @@ void compiler_mode_by_callname(aflcc_state_t *aflcc) { aflcc->compiler_mode = GCC_PLUGIN; -#if defined(__x86_64__) - } else if (strncmp(aflcc->callname, "afl-gcc", 7) == 0 || strncmp(aflcc->callname, "afl-g++", 7) == 0) { aflcc->compiler_mode = GCC; -#endif - -#if defined(__x86_64__) - } else if (strcmp(aflcc->callname, "afl-clang") == 0 || strcmp(aflcc->callname, "afl-clang++") == 0) { aflcc->compiler_mode = CLANG; -#endif - } } @@ -675,22 +667,14 @@ void compiler_mode_by_environ(aflcc_state_t *aflcc) { aflcc->compiler_mode = GCC_PLUGIN; -#if defined(__x86_64__) - } else if (strcasecmp(ptr, "GCC") == 0) { aflcc->compiler_mode = GCC; -#endif - -#if defined(__x86_64__) - } else if (strcasecmp(ptr, "CLANG") == 0) { aflcc->compiler_mode = CLANG; -#endif - } else FATAL("Unknown AFL_CC_COMPILER mode: %s\n", ptr); @@ -774,22 +758,14 @@ void compiler_mode_by_cmdline(aflcc_state_t *aflcc, int argc, char **argv) { aflcc->compiler_mode = GCC_PLUGIN; -#if defined(__x86_64__) - } else if (strcasecmp(ptr, "GCC") == 0) { aflcc->compiler_mode = GCC; -#endif - -#if defined(__x86_64__) - } else if (strncasecmp(ptr, "CLANG", 5) == 0) { aflcc->compiler_mode = CLANG; -#endif - } else FATAL("Unknown --afl-... compiler mode: %s\n", argv[i]); @@ -960,7 +936,6 @@ static void instrument_mode_new_environ(aflcc_state_t *aflcc) { } -#if defined(__x86_64__) if (strcasecmp(ptr2, "gcc") == 0) { if (!aflcc->instrument_mode || aflcc->instrument_mode == INSTRUMENT_GCC) @@ -975,9 +950,6 @@ static void instrument_mode_new_environ(aflcc_state_t *aflcc) { } -#endif - -#if defined(__x86_64__) if (strcasecmp(ptr2, "clang") == 0) { if (!aflcc->instrument_mode || aflcc->instrument_mode == INSTRUMENT_CLANG) @@ -992,8 +964,6 @@ static void instrument_mode_new_environ(aflcc_state_t *aflcc) { } -#endif - if (strncasecmp(ptr2, "ctx-", strlen("ctx-")) == 0 || strncasecmp(ptr2, "kctx-", strlen("c-ctx-")) == 0 || strncasecmp(ptr2, "k-ctx-", strlen("k-ctx-")) == 0) { -- cgit v1.2.3 From 9cefc4d3d48f6bfddc63e29cf4256c8382fc59d7 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 22 Jan 2024 10:52:22 +0100 Subject: fix docs --- src/afl-fuzz.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 2d5787e8..5aec072e 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -165,7 +165,7 @@ static void usage(u8 *argv0, int more_help) { "\n" "Mutator settings:\n" - " -a - target input format, \"text\" or \"binary\" (default: " + " -a type - target input format, \"text\" or \"binary\" (default: " "generic)\n" " -g minlength - set min length of generated fuzz input (default: 1)\n" " -G maxlength - set max length of generated fuzz input (default: " -- cgit v1.2.3 From 8fedf4998449d5b6b909a1118fc2e152e4d2e6e7 Mon Sep 17 00:00:00 2001 From: Davide Quarta Date: Tue, 23 Jan 2024 19:36:49 +0100 Subject: replay mode support --- src/afl-forkserver.c | 79 +++++++++++++++++++++++++++++++++------------------- src/afl-fuzz-init.c | 6 ++++ src/afl-fuzz.c | 2 +- 3 files changed, 57 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 3f9bfa72..f8dd783f 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -1591,6 +1591,11 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, u32 exec_ms; u32 write_value = fsrv->last_run_timed_out; +#ifdef AFL_PERSISTENT_RECORD + fsrv_run_result_t retval = FSRV_RUN_OK; + char *persistent_out_fmt; +#endif + #ifdef __linux__ if (fsrv->nyx_mode) { @@ -1684,7 +1689,7 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, } -#ifdef AFL_PERSISTENT_RECORD +#ifdef AFL_eERSISTENT_RECORD // end of persistent loop? if (unlikely(fsrv->persistent_record && fsrv->persistent_record_pid != fsrv->child_pid)) { @@ -1790,8 +1795,14 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, if (unlikely(fsrv->last_run_timed_out)) { fsrv->last_kill_signal = fsrv->child_kill_signal; - return FSRV_RUN_TMOUT; +#ifndef AFL_PERSISTENT_RECORD + return FSRV_RUN_TMOUT; +#else + retval = FSRV_RUN_TMOUT; + persistent_out_fmt = "%s/hangs/RECORD:%06u,cnt:%06u"; + goto store_persistent_record; +#endif } /* Did we crash? @@ -1811,48 +1822,58 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, (fsrv->uses_crash_exitcode && WEXITSTATUS(fsrv->child_status) == fsrv->crash_exitcode))) { -#ifdef AFL_PERSISTENT_RECORD - if (unlikely(fsrv->persistent_record)) { + /* For a proper crash, set last_kill_signal to WTERMSIG, else set it to 0 */ + fsrv->last_kill_signal = + WIFSIGNALED(fsrv->child_status) ? WTERMSIG(fsrv->child_status) : 0; - char fn[PATH_MAX]; - u32 i, writecnt = 0; - for (i = 0; i < fsrv->persistent_record; ++i) { +#ifndef AFL_PERSISTENT_RECORD + return FSRV_RUN_CRASH; +#else + retval = FSRV_RUN_CRASH; + persistent_out_fmt = "%s/crashes/RECORD:%06u,cnt:%06u"; + goto store_persistent_record; +#endif - u32 entry = (i + fsrv->persistent_record_idx) % fsrv->persistent_record; - u8 *data = fsrv->persistent_record_data[entry]; - u32 len = fsrv->persistent_record_len[entry]; - if (likely(len && data)) { + } - snprintf(fn, sizeof(fn), "%s/RECORD:%06u,cnt:%06u", - fsrv->persistent_record_dir, fsrv->persistent_record_cnt, - writecnt++); - int fd = open(fn, O_CREAT | O_TRUNC | O_WRONLY, 0644); - if (fd >= 0) { + /* success :) */ + return FSRV_RUN_OK; + +#ifdef AFL_PERSISTENT_RECORD +store_persistent_record: + if (unlikely(retval == FSRV_RUN_CRASH || retval == FSRV_RUN_TMOUT) && + unlikely(fsrv->persistent_record)) { - ck_write(fd, data, len, fn); - close(fd); + char fn[PATH_MAX]; + u32 i, writecnt = 0; + for (i = 0; i < fsrv->persistent_record; ++i) { - } + u32 entry = (i + fsrv->persistent_record_idx) % fsrv->persistent_record; + u8 *data = fsrv->persistent_record_data[entry]; + u32 len = fsrv->persistent_record_len[entry]; + if (likely(len && data)) { + + snprintf(fn, sizeof(fn), persistent_out_fmt, + fsrv->persistent_record_dir, fsrv->persistent_record_cnt, + writecnt++); + int fd = open(fn, O_CREAT | O_TRUNC | O_WRONLY, 0644); + if (fd >= 0) { + + ck_write(fd, data, len, fn); + close(fd); } } - ++fsrv->persistent_record_cnt; - } -#endif - - /* For a proper crash, set last_kill_signal to WTERMSIG, else set it to 0 */ - fsrv->last_kill_signal = - WIFSIGNALED(fsrv->child_status) ? WTERMSIG(fsrv->child_status) : 0; - return FSRV_RUN_CRASH; + ++fsrv->persistent_record_cnt; } - /* success :) */ - return FSRV_RUN_OK; + return retval; +#endif } diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 35932913..5b7dc4c1 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1915,6 +1915,9 @@ static void handle_existing_out_dir(afl_state_t *afl) { } +#ifdef AFL_PERSISTENT_RECORD + delete_files(fn, RECORD_PREFIX); +#endif if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } ck_free(fn); @@ -1947,6 +1950,9 @@ static void handle_existing_out_dir(afl_state_t *afl) { } +#ifdef AFL_PERSISTENT_RECORD + delete_files(fn, RECORD_PREFIX); +#endif if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } ck_free(fn); diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 17949fd7..40c30472 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2163,7 +2163,7 @@ int main(int argc, char **argv_orig, char **envp) { } - afl->fsrv.persistent_record_dir = alloc_printf("%s/crashes", afl->out_dir); + afl->fsrv.persistent_record_dir = alloc_printf("%s", afl->out_dir); } -- cgit v1.2.3 From d5812786f30f03ad162643a0e21c945f8ffd14d3 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Wed, 24 Jan 2024 17:54:57 +0100 Subject: gcc asan workaround (#1966) --- src/afl-cc.c | 176 ++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 138 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 5cbd964e..ec25bf9d 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -170,8 +170,10 @@ typedef struct aflcc_state { u8 have_instr_env, have_gcc, have_clang, have_llvm, have_gcc_plugin, have_lto, have_optimized_pcguard, have_instr_list; - u8 fortify_set, asan_set, x_set, bit_mode, preprocessor_only, have_unroll, - have_o, have_pic, have_c, shared_linking, partial_linking, non_dash; + u8 fortify_set, x_set, bit_mode, preprocessor_only, have_unroll, have_o, + have_pic, have_c, shared_linking, partial_linking, non_dash, have_fp, + have_flto, have_hidden, have_fortify, have_fcf, have_staticasan, + have_asan, have_msan, have_ubsan, have_lsan, have_tsan, have_cfisan; // u8 *march_opt; u8 need_aflpplib; @@ -1553,6 +1555,8 @@ void add_defs_persistent_mode(aflcc_state_t *aflcc) { /* Control _FORTIFY_SOURCE */ void add_defs_fortify(aflcc_state_t *aflcc, u8 action) { + if (aflcc->have_fortify) { return; } + switch (action) { case 1: @@ -1666,6 +1670,42 @@ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { param_st final_ = PARAM_MISS; + if (strstr(cur_argv, "=address") || strstr(cur_argv, ",address")) { + + aflcc->have_asan = 1; + + } + + if (strstr(cur_argv, "=memory") || strstr(cur_argv, ",memory")) { + + aflcc->have_msan = 1; + + } + + if (strstr(cur_argv, "=undefined") || strstr(cur_argv, ",undefined")) { + + aflcc->have_ubsan = 1; + + } + + if (strstr(cur_argv, "=thread") || strstr(cur_argv, ",thread")) { + + aflcc->have_tsan = 1; + + } + + if (strstr(cur_argv, "=leak") || strstr(cur_argv, ",leak")) { + + aflcc->have_lsan = 1; + + } + + if (strstr(cur_argv, "=cfi") || strstr(cur_argv, ",cfi")) { + + aflcc->have_cfisan = 1; + + } + if (!strncmp(cur_argv, "-fsanitize-coverage-", 20) && strstr(cur_argv, "list=")) { @@ -1745,19 +1785,14 @@ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { } - if (!strcmp(cur_argv, "-fsanitize=address") || - !strcmp(cur_argv, "-fsanitize=memory")) { + if (final_ == PARAM_MISS) { if (scan) { - // "-fsanitize=undefined,address" may be un-treated, but it's OK. - aflcc->asan_set = 1; final_ = PARAM_SCAN; } else { - // It's impossible that final_ is PARAM_DROP before, - // so no checks are needed here. final_ = PARAM_KEEP; } @@ -1772,74 +1807,113 @@ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { void add_sanitizers(aflcc_state_t *aflcc, char **envp) { - if (!aflcc->asan_set) { + if (getenv("AFL_USE_ASAN") || aflcc->have_asan) { + + if (getenv("AFL_USE_MSAN") || aflcc->have_msan) + FATAL("ASAN and MSAN are mutually exclusive"); - if (getenv("AFL_USE_ASAN")) { + if (getenv("AFL_HARDEN")) + FATAL("ASAN and AFL_HARDEN are mutually exclusive"); - if (getenv("AFL_USE_MSAN")) FATAL("ASAN and MSAN are mutually exclusive"); + if (aflcc->compiler_mode == GCC_PLUGIN && !aflcc->have_staticasan) { - if (getenv("AFL_HARDEN")) - FATAL("ASAN and AFL_HARDEN are mutually exclusive"); + insert_param(aflcc, "-static-libasan"); - add_defs_fortify(aflcc, 0); - insert_param(aflcc, "-fsanitize=address"); + } - } else if (getenv("AFL_USE_MSAN")) { + add_defs_fortify(aflcc, 0); + if (!aflcc->have_asan) { insert_param(aflcc, "-fsanitize=address"); } + aflcc->have_asan = 1; - if (getenv("AFL_USE_ASAN")) FATAL("ASAN and MSAN are mutually exclusive"); + } else if (getenv("AFL_USE_MSAN") || aflcc->have_msan) { - if (getenv("AFL_HARDEN")) - FATAL("MSAN and AFL_HARDEN are mutually exclusive"); + if (getenv("AFL_USE_ASAN") || aflcc->have_asan) + FATAL("ASAN and MSAN are mutually exclusive"); - add_defs_fortify(aflcc, 0); - insert_param(aflcc, "-fsanitize=memory"); + if (getenv("AFL_HARDEN")) + FATAL("MSAN and AFL_HARDEN are mutually exclusive"); - } + add_defs_fortify(aflcc, 0); + insert_param(aflcc, "-fsanitize=memory"); + aflcc->have_msan = 1; } - if (getenv("AFL_USE_UBSAN")) { + if (getenv("AFL_USE_UBSAN") || aflcc->have_ubsan) { + + if (!aflcc->have_ubsan) { + + insert_param(aflcc, "-fsanitize=undefined"); + insert_param(aflcc, "-fsanitize-undefined-trap-on-error"); + insert_param(aflcc, "-fno-sanitize-recover=all"); + + } + + if (!aflcc->have_fp) { + + insert_param(aflcc, "-fno-omit-frame-pointer"); + aflcc->have_fp = 1; + + } - insert_param(aflcc, "-fsanitize=undefined"); - insert_param(aflcc, "-fsanitize-undefined-trap-on-error"); - insert_param(aflcc, "-fno-sanitize-recover=all"); - insert_param(aflcc, "-fno-omit-frame-pointer"); + aflcc->have_ubsan = 1; } - if (getenv("AFL_USE_TSAN")) { + if (getenv("AFL_USE_TSAN") || aflcc->have_tsan) { + + if (!aflcc->have_fp) { + + insert_param(aflcc, "-fno-omit-frame-pointer"); + aflcc->have_fp = 1; + + } - insert_param(aflcc, "-fsanitize=thread"); - insert_param(aflcc, "-fno-omit-frame-pointer"); + if (!aflcc->have_tsan) { insert_param(aflcc, "-fsanitize=thread"); } + aflcc->have_tsan = 1; } - if (getenv("AFL_USE_LSAN")) { + if (getenv("AFL_USE_LSAN") && !aflcc->have_lsan) { insert_param(aflcc, "-fsanitize=leak"); add_defs_lsan_ctrl(aflcc); + aflcc->have_lsan = 1; } - if (getenv("AFL_USE_CFISAN")) { + if (getenv("AFL_USE_CFISAN") || aflcc->have_cfisan) { if (aflcc->compiler_mode == GCC_PLUGIN || aflcc->compiler_mode == GCC) { - insert_param(aflcc, "-fcf-protection=full"); + if (!aflcc->have_fcf) { insert_param(aflcc, "-fcf-protection=full"); } } else { - if (!aflcc->lto_mode) { + if (!aflcc->lto_mode && !aflcc->have_flto) { uint32_t i = 0, found = 0; - while (envp[i] != NULL && !found) + while (envp[i] != NULL && !found) { + if (strncmp("-flto", envp[i++], 5) == 0) found = 1; - if (!found) insert_param(aflcc, "-flto"); + + } + + if (!found) { insert_param(aflcc, "-flto"); } + aflcc->have_flto = 1; } - insert_param(aflcc, "-fsanitize=cfi"); - insert_param(aflcc, "-fvisibility=hidden"); + if (!aflcc->have_cfisan) { insert_param(aflcc, "-fsanitize=cfi"); } + + if (!aflcc->have_hidden) { + + insert_param(aflcc, "-fvisibility=hidden"); + aflcc->have_hidden = 1; + + } + + aflcc->have_cfisan = 1; } @@ -2417,6 +2491,32 @@ param_st parse_misc_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { SCAN_KEEP(aflcc->have_c, 1); + } else if (!strcmp(cur_argv, "-static-libasan")) { + + SCAN_KEEP(aflcc->have_staticasan, 1); + + } else if (!strcmp(cur_argv, "-fno-omit-frame-pointer")) { + + SCAN_KEEP(aflcc->have_fp, 1); + + } else if (!strcmp(cur_argv, "-fvisibility=hidden")) { + + SCAN_KEEP(aflcc->have_hidden, 1); + + } else if (!strcmp(cur_argv, "-flto") || !strcmp(cur_argv, "-flto=full")) { + + SCAN_KEEP(aflcc->have_flto, 1); + + } else if (!strncmp(cur_argv, "-D_FORTIFY_SOURCE", + + strlen("-D_FORTIFY_SOURCE"))) { + + SCAN_KEEP(aflcc->have_fortify, 1); + + } else if (!strncmp(cur_argv, "-fcf-protection", strlen("-fcf-protection"))) { + + SCAN_KEEP(aflcc->have_cfisan, 1); + } else if (!strncmp(cur_argv, "-O", 2)) { SCAN_KEEP(aflcc->have_o, 1); -- cgit v1.2.3 From 8746b3e310ba6200e9e62fd6fabbba36edaa3811 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 24 Jan 2024 18:06:02 +0100 Subject: fix github merge fuckup --- src/afl-cc.c | 503 ++++------------------------------------------------------- 1 file changed, 27 insertions(+), 476 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index dee90946..ec25bf9d 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -650,7 +650,7 @@ void compiler_mode_by_environ(aflcc_state_t *aflcc) { "selected by command line parameter or symlink, ignoring the " "environment variable!"); - if (aflcc->compiler_mode) { + } } else { @@ -708,7 +708,7 @@ void compiler_mode_by_cmdline(aflcc_state_t *aflcc, int argc, char **argv) { "--afl-... compiler mode supersedes the AFL_CC_COMPILER and " "symlink compiler selection!"); - char *ptr = NULL; + } ptr = argv[i]; ptr += 5; @@ -831,8 +831,7 @@ static void instrument_mode_old_environ(aflcc_state_t *aflcc) { aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CTX_K; - if (getenv("USE_TRACE_PC") || getenv("AFL_USE_TRACE_PC") || - getenv("AFL_LLVM_USE_TRACE_PC") || getenv("AFL_TRACE_PC")) { + } } @@ -1005,26 +1004,21 @@ static void instrument_mode_new_environ(aflcc_state_t *aflcc) { } - if ((ptr3 = getenv("AFL_LLVM_CTX_K")) == NULL) - FATAL( - "you must set the K-CTX K with (e.g. for value 2) " - "AFL_LLVM_INSTRUMENT=ctx-2"); + } if (strcasecmp(ptr2, "ctx") == 0) { aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CTX; setenv("AFL_LLVM_CTX", "1", 1); - if (aflcc->ctx_k == 1) { + } if (strncasecmp(ptr2, "caller", strlen("caller")) == 0) { aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CALLER; setenv("AFL_LLVM_CALLER", "1", 1); - aflcc->instrument_opt_mode |= (INSTRUMENT_OPT_CTX_K); - u8 *ptr4 = alloc_printf("%u", aflcc->ctx_k); - setenv("AFL_LLVM_CTX_K", ptr4, 1); + } if (strncasecmp(ptr2, "ngram", strlen("ngram")) == 0) { @@ -1204,8 +1198,7 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) { aflcc->instrument_mode = INSTRUMENT_CLANG; setenv(CLANG_ENV_VAR, "1", 1); // used by afl-as - aflcc->instrument_mode = INSTRUMENT_CLASSIC; - aflcc->compiler_mode = LLVM; + } } @@ -1265,7 +1258,7 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) { aflcc->instrument_mode = INSTRUMENT_AFL; #endif - if (!be_quiet) { + } if (!aflcc->instrument_opt_mode && aflcc->lto_mode && aflcc->instrument_mode == INSTRUMENT_CFG) { @@ -1290,7 +1283,7 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) { else aflcc->compiler_mode = LTO; - } else + } if (getenv("AFL_LLVM_SKIP_NEVERZERO") && getenv("AFL_LLVM_NOT_ZERO")) FATAL( @@ -1364,18 +1357,10 @@ void mode_notification(aflcc_state_t *aflcc) { "gcc-plugin and use afl-clang-fast/afl-clang-lto/afl-gcc-fast " "instead!"); - char *ptr2 = alloc_printf(" + NGRAM-%u", aflcc->ngram_size); - char *ptr3 = alloc_printf(" + K-CTX-%u", aflcc->ctx_k); - - char *ptr1 = alloc_printf( - "%s%s%s%s%s", instrument_mode_2str(aflcc->instrument_mode), - (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX) ? " + CTX" : "", - (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER) ? " + CALLER" : "", - (aflcc->instrument_opt_mode & INSTRUMENT_OPT_NGRAM) ? ptr2 : "", - (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX_K) ? ptr3 : ""); - } +} + void add_real_argv0(aflcc_state_t *aflcc) { static u8 llvm_fullpath[PATH_MAX]; @@ -1434,7 +1419,7 @@ void add_real_argv0(aflcc_state_t *aflcc) { } - alt_cc = "clang"; + } aflcc->cc_params[0] = alt_cc; @@ -1586,9 +1571,7 @@ void add_defs_fortify(aflcc_state_t *aflcc, u8 action) { insert_param(aflcc, "-U_FORTIFY_SOURCE"); break; - case 2: - insert_param(aflcc, "-D_FORTIFY_SOURCE=2"); - break; + } } @@ -1709,7 +1692,7 @@ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { aflcc->have_tsan = 1; - } else { + } if (strstr(cur_argv, "=leak") || strstr(cur_argv, ",leak")) { @@ -1798,11 +1781,9 @@ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { if (!be_quiet) { WARNF("Found '%s' - stripping!", cur_argv); } final_ = PARAM_DROP; - if (getenv("AFL_HARDEN")) - FATAL("ASAN and AFL_HARDEN are mutually exclusive"); + } - add_defs_fortify(aflcc, 0); - insert_param(aflcc, "-fsanitize=address"); + } if (final_ == PARAM_MISS) { @@ -1916,8 +1897,7 @@ void add_sanitizers(aflcc_state_t *aflcc, char **envp) { if (strncmp("-flto", envp[i++], 5) == 0) found = 1; - #endif -#endif + } if (!found) { insert_param(aflcc, "-flto"); } aflcc->have_flto = 1; @@ -1931,7 +1911,7 @@ void add_sanitizers(aflcc_state_t *aflcc, char **envp) { insert_param(aflcc, "-fvisibility=hidden"); aflcc->have_hidden = 1; - if (aflcc->lto_mode && !strncmp(cur_argv, "-flto=thin", 10)) { + } aflcc->have_cfisan = 1; @@ -2101,10 +2081,7 @@ param_st parse_linking_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan, final_ = PARAM_SCAN; - WARNF( - "'%s': multiple link options after '-Wl,' may enable report " - "unresolved symbol references and result in a bad link.", - ptr_); + } else { final_ = PARAM_DROP; @@ -2129,392 +2106,8 @@ param_st parse_linking_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan, } -} - -void add_lto_linker(aflcc_state_t *aflcc) { - - unsetenv("AFL_LD"); - unsetenv("AFL_LD_CALLER"); - - u8 *ld_path = NULL; - if (getenv("AFL_REAL_LD")) { - - ld_path = strdup(getenv("AFL_REAL_LD")); - - } else { - - ld_path = strdup(AFL_REAL_LD); - - } - - if (!ld_path || !*ld_path) { - - if (ld_path) { - - // Freeing empty string - free(ld_path); - - } - - ld_path = strdup("ld.lld"); - - } - - if (!ld_path) { PFATAL("Could not allocate mem for ld_path"); } -#if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 12 - insert_param(aflcc, alloc_printf("--ld-path=%s", ld_path)); -#else - insert_param(aflcc, alloc_printf("-fuse-ld=%s", ld_path)); -#endif - free(ld_path); - -} - -void add_lto_passes(aflcc_state_t *aflcc) { - -#if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 15 - // The NewPM implementation only works fully since LLVM 15. - insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,--load-pass-plugin=%s", - 0); -#elif defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 13 - insert_param(aflcc, "-Wl,--lto-legacy-pass-manager"); - insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,-mllvm=-load=%s", 0); -#else - insert_param(aflcc, "-fno-experimental-new-pass-manager"); - insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,-mllvm=-load=%s", 0); -#endif - - insert_param(aflcc, "-Wl,--allow-multiple-definition"); - -} - -static void add_aflpplib(aflcc_state_t *aflcc) { - - if (!aflcc->need_aflpplib) return; - - u8 *afllib = find_object(aflcc, "libAFLDriver.a"); - - if (!be_quiet) { - - OKF("Found '-fsanitize=fuzzer', replacing with libAFLDriver.a"); - - } - - if (!afllib) { - - if (!be_quiet) { - - WARNF( - "Cannot find 'libAFLDriver.a' to replace '-fsanitize=fuzzer' in " - "the flags - this will fail!"); - - } - - } else { - - insert_param(aflcc, afllib); - -#ifdef __APPLE__ - insert_param(aflcc, "-Wl,-undefined"); - insert_param(aflcc, "dynamic_lookup"); -#endif - - } - -} - -void add_runtime(aflcc_state_t *aflcc) { - - if (aflcc->preprocessor_only || aflcc->have_c || !aflcc->non_dash) { - - /* In the preprocessor_only case (-E), we are not actually compiling at - all but requesting the compiler to output preprocessed sources only. - We must not add the runtime in this case because the compiler will - simply output its binary content back on stdout, breaking any build - systems that rely on a separate source preprocessing step. */ - return; - - } - - if (aflcc->compiler_mode != GCC_PLUGIN && aflcc->compiler_mode != GCC && - !getenv("AFL_LLVM_NO_RPATH")) { - - // in case LLVM is installed not via a package manager or "make install" - // e.g. compiled download or compiled from github then its ./lib directory - // might not be in the search path. Add it if so. - const char *libdir = LLVM_LIBDIR; - if (aflcc->plusplus_mode && strlen(libdir) && strncmp(libdir, "/usr", 4) && - strncmp(libdir, "/lib", 4)) { - - u8 *libdir_opt = strdup("-Wl,-rpath=" LLVM_LIBDIR); - insert_param(aflcc, libdir_opt); - - } - - } - -#ifndef __ANDROID__ - - #define M32_ERR_MSG "-m32 is not supported by your compiler" - #define M64_ERR_MSG "-m64 is not supported by your compiler" - - if (aflcc->compiler_mode != GCC && aflcc->compiler_mode != CLANG) { - - switch (aflcc->bit_mode) { - - case 0: - if (!aflcc->shared_linking && !aflcc->partial_linking) - insert_object(aflcc, "afl-compiler-rt.o", 0, 0); - if (aflcc->lto_mode) insert_object(aflcc, "afl-llvm-rt-lto.o", 0, 0); - break; - - case 32: - if (!aflcc->shared_linking && !aflcc->partial_linking) - insert_object(aflcc, "afl-compiler-rt-32.o", 0, M32_ERR_MSG); - if (aflcc->lto_mode) - insert_object(aflcc, "afl-llvm-rt-lto-32.o", 0, M32_ERR_MSG); - break; - - case 64: - if (!aflcc->shared_linking && !aflcc->partial_linking) - insert_object(aflcc, "afl-compiler-rt-64.o", 0, M64_ERR_MSG); - if (aflcc->lto_mode) - insert_object(aflcc, "afl-llvm-rt-lto-64.o", 0, M64_ERR_MSG); - break; - - } - - #if !defined(__APPLE__) && !defined(__sun) - if (!aflcc->shared_linking && !aflcc->partial_linking) - insert_object(aflcc, "dynamic_list.txt", "-Wl,--dynamic-list=%s", 0); - #endif - - #if defined(__APPLE__) - if (aflcc->shared_linking || aflcc->partial_linking) { - - insert_param(aflcc, "-Wl,-U"); - insert_param(aflcc, "-Wl,___afl_area_ptr"); - insert_param(aflcc, "-Wl,-U"); - insert_param(aflcc, "-Wl,___sanitizer_cov_trace_pc_guard_init"); - - } - - #endif - - } - -#endif - - add_aflpplib(aflcc); - -#if defined(USEMMAP) && !defined(__HAIKU__) && !__APPLE__ - insert_param(aflcc, "-Wl,-lrt"); -#endif - -} - -/* Misc */ - -void add_assembler(aflcc_state_t *aflcc) { - - u8 *afl_as = find_object(aflcc, "as"); - - if (!afl_as) FATAL("Cannot find 'as' (symlink to 'afl-as')."); - - u8 *slash = strrchr(afl_as, '/'); - if (slash) *slash = 0; - - insert_param(aflcc, "-B"); - insert_param(aflcc, afl_as); - - if (aflcc->compiler_mode == CLANG) insert_param(aflcc, "-no-integrated-as"); - -} - -void add_gcc_plugin(aflcc_state_t *aflcc) { - - if (aflcc->cmplog_mode) { - - insert_object(aflcc, "afl-gcc-cmplog-pass.so", "-fplugin=%s", 0); - insert_object(aflcc, "afl-gcc-cmptrs-pass.so", "-fplugin=%s", 0); - - } - - insert_object(aflcc, "afl-gcc-pass.so", "-fplugin=%s", 0); - - insert_param(aflcc, "-fno-if-conversion"); - insert_param(aflcc, "-fno-if-conversion2"); - -} - -void add_misc_params(aflcc_state_t *aflcc) { - - if (getenv("AFL_NO_BUILTIN") || getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES") || - getenv("AFL_LLVM_LAF_ALL") || getenv("AFL_LLVM_CMPLOG") || - aflcc->lto_mode) { - - insert_param(aflcc, "-fno-builtin-strcmp"); - insert_param(aflcc, "-fno-builtin-strncmp"); - insert_param(aflcc, "-fno-builtin-strcasecmp"); - insert_param(aflcc, "-fno-builtin-strncasecmp"); - insert_param(aflcc, "-fno-builtin-memcmp"); - insert_param(aflcc, "-fno-builtin-bcmp"); - insert_param(aflcc, "-fno-builtin-strstr"); - insert_param(aflcc, "-fno-builtin-strcasestr"); - - } - - if (!aflcc->have_pic) { insert_param(aflcc, "-fPIC"); } - - if (getenv("AFL_HARDEN")) { - - insert_param(aflcc, "-fstack-protector-all"); - - if (!aflcc->fortify_set) add_defs_fortify(aflcc, 2); - - } - - if (!getenv("AFL_DONT_OPTIMIZE")) { - - insert_param(aflcc, "-g"); - if (!aflcc->have_o) insert_param(aflcc, "-O3"); - if (!aflcc->have_unroll) insert_param(aflcc, "-funroll-loops"); - // if (strlen(aflcc->march_opt) > 1 && aflcc->march_opt[0] == '-') - // insert_param(aflcc, aflcc->march_opt); - - } - - if (aflcc->x_set) { - - insert_param(aflcc, "-x"); - insert_param(aflcc, "none"); - - } - -} - -param_st parse_misc_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { - - param_st final_ = PARAM_MISS; - -// MACRO START -#define SCAN_KEEP(dst, src) \ - do { \ - \ - if (scan) { \ - \ - dst = src; \ - final_ = PARAM_SCAN; \ - \ - } else { \ - \ - final_ = PARAM_KEEP; \ - \ - } \ - \ - } while (0) - - // MACRO END - - if (!strncasecmp(cur_argv, "-fpic", 5)) { - - SCAN_KEEP(aflcc->have_pic, 1); - - } else if (!strcmp(cur_argv, "-m32") || - - !strcmp(cur_argv, "armv7a-linux-androideabi")) { - - SCAN_KEEP(aflcc->bit_mode, 32); - - } else if (!strcmp(cur_argv, "-m64")) { - - SCAN_KEEP(aflcc->bit_mode, 64); - - } else if (strstr(cur_argv, "FORTIFY_SOURCE")) { - - SCAN_KEEP(aflcc->fortify_set, 1); - - } else if (!strcmp(cur_argv, "-x")) { - - SCAN_KEEP(aflcc->x_set, 1); - - } else if (!strcmp(cur_argv, "-E")) { - - SCAN_KEEP(aflcc->preprocessor_only, 1); - - } else if (!strcmp(cur_argv, "--target=wasm32-wasi")) { - - SCAN_KEEP(aflcc->passthrough, 1); - - } else if (!strcmp(cur_argv, "-c")) { - - SCAN_KEEP(aflcc->have_c, 1); - - } else if (!strncmp(cur_argv, "-O", 2)) { - - SCAN_KEEP(aflcc->have_o, 1); - - } else if (!strncmp(cur_argv, "-funroll-loop", 13)) { - - SCAN_KEEP(aflcc->have_unroll, 1); - - } else if (!strncmp(cur_argv, "--afl", 5)) { - - if (scan) - final_ = PARAM_SCAN; - else - final_ = PARAM_DROP; - - } else if (!strncmp(cur_argv, "-fno-unroll", 11)) { - - if (scan) - final_ = PARAM_SCAN; - else - final_ = PARAM_DROP; - - } else if (!strcmp(cur_argv, "-pipe") && aflcc->compiler_mode == GCC_PLUGIN) { - - if (scan) - final_ = PARAM_SCAN; - else - final_ = PARAM_DROP; - - } else if (!strncmp(cur_argv, "-stdlib=", 8) && - - (aflcc->compiler_mode == GCC || - aflcc->compiler_mode == GCC_PLUGIN)) { - - if (scan) { - - final_ = PARAM_SCAN; - - } else { - - if (!be_quiet) WARNF("Found '%s' - stripping!", cur_argv); - final_ = PARAM_DROP; - - } - - } else if (cur_argv[0] != '-') { - - /* It's a weak, loose pattern, with very different purpose - than others. We handle it at last, cautiously and robustly. */ - - if (scan && cur_argv[0] != '@') // response file support - aflcc->non_dash = 1; - } -#undef SCAN_KEEP - - if (final_ == PARAM_KEEP) insert_param(aflcc, cur_argv); - - return final_; - -} - -static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { - // Try to warn user for some unsupported cases if (scan && final_ == PARAM_MISS) { @@ -3435,6 +3028,14 @@ static void process_params(aflcc_state_t *aflcc, u8 scan, u32 argc, free(tmpbuf); + continue; + + } + + if (!scan) insert_param(aflcc, cur); + + } + } /* Copy argv to cc_params, making the necessary edits. */ @@ -3580,56 +3181,6 @@ static void edit_params(aflcc_state_t *aflcc, u32 argc, char **argv, /* Main entry point */ -int main(int argc, char **argv, char **envp) { - - aflcc_state_t *aflcc = malloc(sizeof(aflcc_state_t)); - aflcc_state_init(aflcc, (u8 *)argv[0]); - - check_environment_vars(envp); - - find_built_deps(aflcc); - - compiler_mode_by_callname(aflcc); - compiler_mode_by_environ(aflcc); - compiler_mode_by_cmdline(aflcc, argc, argv); - - instrument_mode_by_environ(aflcc); - - mode_final_checkout(aflcc, argc, argv); - - process_params(aflcc, 1, argc, argv); - - maybe_usage(aflcc, argc, argv); - - mode_notification(aflcc); - - if (aflcc->debug) debugf_args(argc, argv); - - edit_params(aflcc, argc, argv, envp); - - if (aflcc->debug) - debugf_args((s32)aflcc->cc_par_cnt, (char **)aflcc->cc_params); - - /* Inspect the command line parameters. */ - - process_params(aflcc, 0, argc, argv); - - add_sanitizers(aflcc, envp); - - add_misc_params(aflcc); - - add_defs_common(aflcc); - add_defs_selective_instr(aflcc); - add_defs_persistent_mode(aflcc); - - add_runtime(aflcc); - - insert_param(aflcc, NULL); - -} - -/* Main entry point */ - int main(int argc, char **argv, char **envp) { aflcc_state_t *aflcc = malloc(sizeof(aflcc_state_t)); -- cgit v1.2.3 From ba28c4982b7fed33a22214537b4f8ffcc08286d4 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 24 Jan 2024 18:22:17 +0100 Subject: fix --- src/afl-cc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index ec25bf9d..ccbb4f8d 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1572,6 +1572,8 @@ void add_defs_fortify(aflcc_state_t *aflcc, u8 action) { break; } + + aflcc->have_fortify = 1; } -- cgit v1.2.3 From d88c97ad2887962a8565473269057d39d75f998d Mon Sep 17 00:00:00 2001 From: Sonic <50692172+SonicStark@users.noreply.github.com> Date: Thu, 25 Jan 2024 16:57:50 +0800 Subject: Fix afl-cc (#1968) - Check if too many cmdline params here, each time before insert a new param. - Check if it is "-fsanitize=..." before we do sth. - Remove improper param_st transfer. --- src/afl-cc.c | 87 ++++++++++++++++++++++++------------------------------------ 1 file changed, 34 insertions(+), 53 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index ccbb4f8d..174b3783 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -192,15 +192,11 @@ u8 *find_object(aflcc_state_t *, u8 *obj); void find_built_deps(aflcc_state_t *); -static inline void limit_params(aflcc_state_t *aflcc, u32 add) { +static inline void insert_param(aflcc_state_t *aflcc, u8 *param) { - if (aflcc->cc_par_cnt + add >= MAX_PARAMS_NUM) + if (unlikely(aflcc->cc_par_cnt + 1 >= MAX_PARAMS_NUM)) FATAL("Too many command line parameters, please increase MAX_PARAMS_NUM."); -} - -static inline void insert_param(aflcc_state_t *aflcc, u8 *param) { - aflcc->cc_params[aflcc->cc_par_cnt++] = param; } @@ -1572,7 +1568,7 @@ void add_defs_fortify(aflcc_state_t *aflcc, u8 action) { break; } - + aflcc->have_fortify = 1; } @@ -1672,41 +1668,42 @@ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { param_st final_ = PARAM_MISS; - if (strstr(cur_argv, "=address") || strstr(cur_argv, ",address")) { - - aflcc->have_asan = 1; - - } - - if (strstr(cur_argv, "=memory") || strstr(cur_argv, ",memory")) { - - aflcc->have_msan = 1; - - } - - if (strstr(cur_argv, "=undefined") || strstr(cur_argv, ",undefined")) { - - aflcc->have_ubsan = 1; - - } - - if (strstr(cur_argv, "=thread") || strstr(cur_argv, ",thread")) { - - aflcc->have_tsan = 1; +// MACRO START +#define HAVE_SANITIZER_SCAN_KEEP(v, k) \ + do { \ + \ + if (strstr(cur_argv, "=" STRINGIFY(k)) || \ + strstr(cur_argv, "," STRINGIFY(k))) { \ + \ + if (scan) { \ + \ + aflcc->have_##v = 1; \ + final_ = PARAM_SCAN; \ + \ + } else { \ + \ + final_ = PARAM_KEEP; \ + \ + } \ + \ + } \ + \ + } while (0) - } + // MACRO END - if (strstr(cur_argv, "=leak") || strstr(cur_argv, ",leak")) { + if (!strncmp(cur_argv, "-fsanitize=", strlen("-fsanitize="))) { - aflcc->have_lsan = 1; + HAVE_SANITIZER_SCAN_KEEP(asan, address); + HAVE_SANITIZER_SCAN_KEEP(msan, memory); + HAVE_SANITIZER_SCAN_KEEP(ubsan, undefined); + HAVE_SANITIZER_SCAN_KEEP(tsan, thread); + HAVE_SANITIZER_SCAN_KEEP(lsan, leak); + HAVE_SANITIZER_SCAN_KEEP(cfisan, cfi); } - if (strstr(cur_argv, "=cfi") || strstr(cur_argv, ",cfi")) { - - aflcc->have_cfisan = 1; - - } +#undef HAVE_SANITIZER_SCAN_KEEP if (!strncmp(cur_argv, "-fsanitize-coverage-", 20) && strstr(cur_argv, "list=")) { @@ -1718,7 +1715,7 @@ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { } else { - final_ = PARAM_KEEP; // may be set to DROP next + final_ = PARAM_KEEP; } @@ -1787,20 +1784,6 @@ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { } - if (final_ == PARAM_MISS) { - - if (scan) { - - final_ = PARAM_SCAN; - - } else { - - final_ = PARAM_KEEP; - - } - - } - if (final_ == PARAM_KEEP) insert_param(aflcc, cur_argv); return final_; @@ -2880,8 +2863,6 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { static void process_params(aflcc_state_t *aflcc, u8 scan, u32 argc, char **argv) { - limit_params(aflcc, argc); - // for (u32 x = 0; x < argc; ++x) fprintf(stderr, "[%u] %s\n", x, argv[x]); /* Process the argument list. */ -- cgit v1.2.3 From 4d493452a45655073d1b7b1dfe4ad04772b3c2b8 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 25 Jan 2024 17:00:53 +0100 Subject: tmp --- src/afl-cc.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 174b3783..4f6745ed 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1103,12 +1103,18 @@ static void instrument_opt_mode_exclude(aflcc_state_t *aflcc) { } - if (aflcc->instrument_opt_mode && aflcc->compiler_mode != LLVM) + fprintf(stderr, "X %u %u\n", aflcc->compiler_mode, LTO); + + if (aflcc->instrument_opt_mode && aflcc->compiler_mode != LLVM && + !((aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER) && + aflcc->compiler_mode == LTO)) FATAL("CTX, CALLER and NGRAM can only be used in LLVM mode"); if (aflcc->instrument_opt_mode && aflcc->instrument_opt_mode != INSTRUMENT_OPT_CODECOV && - aflcc->instrument_mode != INSTRUMENT_CLASSIC) + aflcc->instrument_mode != INSTRUMENT_CLASSIC && + !(aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER && + aflcc->compiler_mode == LTO)) FATAL( "CALLER, CTX and NGRAM instrumentation options can only be used with " "the LLVM CLASSIC instrumentation mode."); -- cgit v1.2.3 From 2f9eeef60cdd4ad43f8066af78009acd660a426c Mon Sep 17 00:00:00 2001 From: "Christian Holler (:decoder)" Date: Fri, 26 Jan 2024 14:41:23 +0100 Subject: Avoid adding llvmnative instrumentation when linking rust sanitizer runtime (#1969) --- src/afl-cc.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 174b3783..6d8e1024 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -173,7 +173,8 @@ typedef struct aflcc_state { u8 fortify_set, x_set, bit_mode, preprocessor_only, have_unroll, have_o, have_pic, have_c, shared_linking, partial_linking, non_dash, have_fp, have_flto, have_hidden, have_fortify, have_fcf, have_staticasan, - have_asan, have_msan, have_ubsan, have_lsan, have_tsan, have_cfisan; + have_rust_asanrt, have_asan, have_msan, have_ubsan, have_lsan, have_tsan, + have_cfisan; // u8 *march_opt; u8 need_aflpplib; @@ -1908,6 +1909,14 @@ void add_sanitizers(aflcc_state_t *aflcc, char **envp) { void add_native_pcguard(aflcc_state_t *aflcc) { + /* If there is a rust ASan runtime on the command line, it is likely we're + * linking from rust and adding native flags requiring the sanitizer runtime + * will trigger native clang to add yet another runtime, causing linker + * errors. For now we shouldn't add instrumentation here, we're linking + * anyway. + */ + if (aflcc->have_rust_asanrt) { return; } + /* If llvm-config doesn't figure out LLVM_MAJOR, just go on anyway and let compiler complain if doesn't work. */ @@ -2480,6 +2489,10 @@ param_st parse_misc_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { SCAN_KEEP(aflcc->have_staticasan, 1); + } else if (strstr(cur_argv, "librustc") && strstr(cur_argv, "_rt.asan.a")) { + + SCAN_KEEP(aflcc->have_rust_asanrt, 1); + } else if (!strcmp(cur_argv, "-fno-omit-frame-pointer")) { SCAN_KEEP(aflcc->have_fp, 1); -- cgit v1.2.3 From 58b80b68bc5538bad2cf4c858229111f58282424 Mon Sep 17 00:00:00 2001 From: "Christian Holler (:decoder)" Date: Fri, 26 Jan 2024 15:46:56 +0100 Subject: Dynamic instrumentation filtering for LLVM native (#1971) * Add two dynamic instrumentation filter methods to runtime * Always use pc-table with native pcguard * Add make_symbol_list.py and README --- src/afl-cc.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 6d8e1024..73487188 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1920,35 +1920,27 @@ void add_native_pcguard(aflcc_state_t *aflcc) { /* If llvm-config doesn't figure out LLVM_MAJOR, just go on anyway and let compiler complain if doesn't work. */ - if (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CODECOV) { - #if LLVM_MAJOR > 0 && LLVM_MAJOR < 6 - FATAL("pcguard instrumentation with pc-table requires LLVM 6.0.1+"); + FATAL("pcguard instrumentation with pc-table requires LLVM 6.0.1+"); #else #if LLVM_MAJOR == 0 - WARNF( - "pcguard instrumentation with pc-table requires LLVM 6.0.1+" - " otherwise the compiler will fail"); + WARNF( + "pcguard instrumentation with pc-table requires LLVM 6.0.1+" + " otherwise the compiler will fail"); #endif + if (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CODECOV) { + insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table"); -#endif } else { -#if LLVM_MAJOR > 0 && LLVM_MAJOR < 4 - FATAL("pcguard instrumentation requires LLVM 4.0.1+"); -#else - #if LLVM_MAJOR == 0 - WARNF( - "pcguard instrumentation requires LLVM 4.0.1+" - " otherwise the compiler will fail"); - #endif - insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); -#endif + insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard,pc-table"); } +#endif + } void add_optimized_pcguard(aflcc_state_t *aflcc) { -- cgit v1.2.3 From 12ab9ebd321abf46da7505c7492d908e351347ce Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 30 Jan 2024 09:55:44 +0100 Subject: new forkserver check --- src/afl-forkserver.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 3f9bfa72..c3c115a1 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -1017,6 +1017,12 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if (rlen == 4) { + if (memcmp((char*)status, "AFL", 3) == 0) { + + FATAL("Target uses the new forkserver model, you need to switch to a newer afl-fuzz too!"); + + } + if (!be_quiet) { OKF("All right - fork server is up."); } if (getenv("AFL_DEBUG")) { -- cgit v1.2.3 From d5b6c0f773178eb8890d0e7004c3c6d4931687fa Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 30 Jan 2024 11:01:49 +0100 Subject: fix --- src/afl-forkserver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index c3c115a1..214b4fe9 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -1017,7 +1017,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if (rlen == 4) { - if (memcmp((char*)status, "AFL", 3) == 0) { + if (status >= 0x41464c00 && status <= 0x41464cff) { FATAL("Target uses the new forkserver model, you need to switch to a newer afl-fuzz too!"); -- cgit v1.2.3 From 9604fe922ede9282a06a89b8d18d4de267aebd54 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 30 Jan 2024 15:06:34 +0100 Subject: nyx test for CI --- src/afl-fuzz-init.c | 6 ++++++ src/afl-fuzz.c | 9 +++++++++ 2 files changed, 15 insertions(+) (limited to 'src') diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 35932913..8ab44a3b 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -124,6 +124,9 @@ void bind_to_free_cpu(afl_state_t *afl) { } WARNF("Not binding to a CPU core (AFL_NO_AFFINITY set)."); + #ifdef __linux__ + if (afl->fsrv.nyx_mode) { afl->fsrv.nyx_bind_cpu_id = 0; } + #endif return; } @@ -151,6 +154,9 @@ void bind_to_free_cpu(afl_state_t *afl) { } else { OKF("CPU binding request using -b %d successful.", afl->cpu_to_bind); + #ifdef __linux__ + if (afl->fsrv.nyx_mode) { afl->fsrv.nyx_bind_cpu_id = afl->cpu_to_bind; } + #endif } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 5aec072e..8cf6c735 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1915,6 +1915,15 @@ int main(int argc, char **argv_orig, char **envp) { bind_to_free_cpu(afl); #endif /* HAVE_AFFINITY */ + #ifdef __linux__ + if (afl->fsrv.nyx_mode && afl->fsrv.nyx_bind_cpu_id == 0xFFFFFFFF) { + + afl->fsrv.nyx_bind_cpu_id = 0; + + } + + #endif + #ifdef __HAIKU__ /* Prioritizes performance over power saving */ set_scheduler_mode(SCHEDULER_MODE_LOW_LATENCY); -- cgit v1.2.3 From 644e0694509d4019e6f5075c4b900d412f29df32 Mon Sep 17 00:00:00 2001 From: "Christian Holler (:decoder)" Date: Tue, 30 Jan 2024 15:30:18 +0100 Subject: Fixes to afl-cc and documentation (#1974) * Always compile with -ldl when building for CODE_COVERAGE When building with CODE_COVERAGE, the afl runtime contains code that calls `dladdr` which requires -ldl. Under most circumstances, clang already adds this (e.g. when building with pc-table), but there are some circumstances where it isn't added automatically. * Add visibility declaration to __afl_connected When building with hidden visibility, the use of __AFL_LOOP inside such code can cause linker errors due to __afl_connected being declared "hidden". * Update docs to clarify that CODE_COVERAGE=1 is required for dynamic_covfilter --- src/afl-cc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 73487188..d11419b0 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1521,7 +1521,7 @@ void add_defs_persistent_mode(aflcc_state_t *aflcc) { "({ static volatile const char *_B __attribute__((used,unused)); " " _B = (const char*)\"" PERSIST_SIG "\"; " - "extern int __afl_connected;" + "extern __attribute__((visibility(\"default\"))) int __afl_connected;" #ifdef __APPLE__ "__attribute__((visibility(\"default\"))) " "int _L(unsigned int) __asm__(\"___afl_persistent_loop\"); " @@ -2311,6 +2311,11 @@ void add_runtime(aflcc_state_t *aflcc) { } + #if __AFL_CODE_COVERAGE + // Required for dladdr used in afl-compiler-rt.o + insert_param(aflcc, "-ldl"); + #endif + #if !defined(__APPLE__) && !defined(__sun) if (!aflcc->shared_linking && !aflcc->partial_linking) insert_object(aflcc, "dynamic_list.txt", "-Wl,--dynamic-list=%s", 0); -- cgit v1.2.3 From 643df2b538b06561d5a6d6ae441322167d33f834 Mon Sep 17 00:00:00 2001 From: Sonic <50692172+SonicStark@users.noreply.github.com> Date: Thu, 1 Feb 2024 15:17:48 +0800 Subject: Improve afl-cc (#1975) * update response file support - full support of rsp file - fix some segv issues * Improve afl-cc - remove dead code about allow/denylist options of sancov - missing `if (!aflcc->have_msan)` - add docs for each function - typo --- src/afl-cc.c | 488 ++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 368 insertions(+), 120 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index d11419b0..c300ddfc 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -51,7 +51,7 @@ #define MAX_PARAMS_NUM 2048 #endif -/* Global declarations */ +/** Global declarations -----BEGIN----- **/ typedef enum { @@ -187,12 +187,11 @@ typedef struct aflcc_state { void aflcc_state_init(aflcc_state_t *, u8 *argv0); -/* Try to find a specific runtime we need, the path to obj would be - allocated and returned. Otherwise it returns NULL on fail. */ u8 *find_object(aflcc_state_t *, u8 *obj); void find_built_deps(aflcc_state_t *); +/* Insert param into the new argv, raise error if MAX_PARAMS_NUM exceeded. */ static inline void insert_param(aflcc_state_t *aflcc, u8 *param) { if (unlikely(aflcc->cc_par_cnt + 1 >= MAX_PARAMS_NUM)) @@ -202,6 +201,13 @@ static inline void insert_param(aflcc_state_t *aflcc, u8 *param) { } +/* + Insert a param which contains path to the object file. It uses find_object to + get the path based on the name `obj`, and then uses a sprintf like method to + format it with `fmt`. If `fmt` is NULL, the inserted arg is same as the path. + If `msg` provided, it should be an error msg raised if the path can't be + found. `obj` must not be NULL. +*/ static inline void insert_object(aflcc_state_t *aflcc, u8 *obj, u8 *fmt, u8 *msg) { @@ -231,6 +237,7 @@ static inline void insert_object(aflcc_state_t *aflcc, u8 *obj, u8 *fmt, } +/* Insert params into the new argv, make clang load the pass. */ static inline void load_llvm_pass(aflcc_state_t *aflcc, u8 *pass) { #if LLVM_MAJOR >= 11 /* use new pass manager */ @@ -291,8 +298,12 @@ void add_lto_linker(aflcc_state_t *); void add_lto_passes(aflcc_state_t *); void add_runtime(aflcc_state_t *); -/* Working state */ +/** Global declarations -----END----- **/ +/* + Init global state struct. We also extract the callname, + check debug options and if in C++ mode here. +*/ void aflcc_state_init(aflcc_state_t *aflcc, u8 *argv0) { // Default NULL/0 is a good start @@ -352,7 +363,7 @@ void aflcc_state_init(aflcc_state_t *aflcc, u8 *argv0) { } /* - in find_object() we look here: + Try to find a specific runtime we need, in here: 1. firstly we check the $AFL_PATH environment variable location if set 2. next we check argv[0] if it has path information and use it @@ -366,7 +377,6 @@ void aflcc_state_init(aflcc_state_t *aflcc, u8 *argv0) { if all these attempts fail - we return NULL and the caller has to decide what to do. Otherwise the path to obj would be allocated and returned. */ - u8 *find_object(aflcc_state_t *aflcc, u8 *obj) { u8 *argv0 = aflcc->argv0; @@ -499,6 +509,10 @@ u8 *find_object(aflcc_state_t *aflcc, u8 *obj) { } +/* + Deduce some info about compiler toolchains in current system, + from the building results of AFL++ +*/ void find_built_deps(aflcc_state_t *aflcc) { char *ptr = NULL; @@ -571,8 +585,9 @@ void find_built_deps(aflcc_state_t *aflcc) { } -/* compiler_mode & instrument_mode selecting */ +/** compiler_mode & instrument_mode selecting -----BEGIN----- **/ +/* Select compiler_mode by callname, such as "afl-clang-fast", etc. */ void compiler_mode_by_callname(aflcc_state_t *aflcc) { if (strncmp(aflcc->callname, "afl-clang-fast", 14) == 0) { @@ -626,6 +641,10 @@ void compiler_mode_by_callname(aflcc_state_t *aflcc) { } +/* + Select compiler_mode by env AFL_CC_COMPILER. And passthrough mode can be + regarded as a special compiler_mode, so we check for it here, too. +*/ void compiler_mode_by_environ(aflcc_state_t *aflcc) { if (getenv("AFL_PASSTHROUGH") || getenv("AFL_NOOPT")) { @@ -682,7 +701,13 @@ void compiler_mode_by_environ(aflcc_state_t *aflcc) { } -// If it can be inferred, instrument_mode would also be set +/* + Select compiler_mode by command line options --afl-... + If it can be inferred, instrument_mode would also be set. + This can supersedes previous result based on callname + or AFL_CC_COMPILER. And "--afl_noopt"/"--afl-noopt" will + be overwritten by "-g". +*/ void compiler_mode_by_cmdline(aflcc_state_t *aflcc, int argc, char **argv) { char *ptr = NULL; @@ -775,6 +800,12 @@ void compiler_mode_by_cmdline(aflcc_state_t *aflcc, int argc, char **argv) { } +/* + Select instrument_mode by those envs in old style: + - USE_TRACE_PC, AFL_USE_TRACE_PC, AFL_LLVM_USE_TRACE_PC, AFL_TRACE_PC + - AFL_LLVM_CALLER, AFL_LLVM_CTX, AFL_LLVM_CTX_K + - AFL_LLVM_NGRAM_SIZE +*/ static void instrument_mode_old_environ(aflcc_state_t *aflcc) { if (getenv("AFL_LLVM_INSTRIM") || getenv("INSTRIM") || @@ -834,7 +865,11 @@ static void instrument_mode_old_environ(aflcc_state_t *aflcc) { } -// compiler_mode would also be set if depended by the instrument_mode +/* + Select instrument_mode by env 'AFL_LLVM_INSTRUMENT'. + Previous compiler_mode will be superseded, if required by some + values of instrument_mode. +*/ static void instrument_mode_new_environ(aflcc_state_t *aflcc) { if (!getenv("AFL_LLVM_INSTRUMENT")) { return; } @@ -1058,6 +1093,11 @@ static void instrument_mode_new_environ(aflcc_state_t *aflcc) { } +/* + Select instrument_mode by envs, the top wrapper. We check + have_instr_env firstly, then call instrument_mode_old_environ + and instrument_mode_new_environ sequentially. +*/ void instrument_mode_by_environ(aflcc_state_t *aflcc) { if (getenv("AFL_LLVM_INSTRUMENT_FILE") || getenv("AFL_LLVM_WHITELIST") || @@ -1081,6 +1121,10 @@ void instrument_mode_by_environ(aflcc_state_t *aflcc) { } +/* + Workaround to ensure CALLER, CTX, K-CTX and NGRAM + instrumentation were used correctly. +*/ static void instrument_opt_mode_exclude(aflcc_state_t *aflcc) { if ((aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX) && @@ -1116,6 +1160,11 @@ static void instrument_opt_mode_exclude(aflcc_state_t *aflcc) { } +/* + Last step of compiler_mode & instrument_mode selecting. + We have a few of workarounds here, to check any corner cases, + prepare for a series of fallbacks, and raise warnings or errors. +*/ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) { if (aflcc->instrument_opt_mode && @@ -1320,6 +1369,10 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) { } +/* + Print welcome message on screen, giving brief notes about + compiler_mode and instrument_mode. +*/ void mode_notification(aflcc_state_t *aflcc) { char *ptr2 = alloc_printf(" + NGRAM-%u", aflcc->ngram_size); @@ -1358,6 +1411,17 @@ void mode_notification(aflcc_state_t *aflcc) { } +/* + Set argv[0] required by execvp. It can be + - specified by env AFL_CXX + - g++ or clang++ + - CLANGPP_BIN or LLVM_BINDIR/clang++ + when in C++ mode, or + - specified by env AFL_CC + - gcc or clang + - CLANG_BIN or LLVM_BINDIR/clang + otherwise. +*/ void add_real_argv0(aflcc_state_t *aflcc) { static u8 llvm_fullpath[PATH_MAX]; @@ -1424,7 +1488,9 @@ void add_real_argv0(aflcc_state_t *aflcc) { } -/* Macro defs for the preprocessor */ +/** compiler_mode & instrument_mode selecting -----END----- **/ + +/** Macro defs for the preprocessor -----BEGIN----- **/ void add_defs_common(aflcc_state_t *aflcc) { @@ -1433,8 +1499,11 @@ void add_defs_common(aflcc_state_t *aflcc) { } -/* See instrumentation/README.instrument_list.md# - 2-selective-instrumentation-with-_afl_coverage-directives */ +/* + __afl_coverage macro defs. See + instrumentation/README.instrument_list.md# + 2-selective-instrumentation-with-_afl_coverage-directives +*/ void add_defs_selective_instr(aflcc_state_t *aflcc) { if (aflcc->plusplus_mode) { @@ -1468,9 +1537,11 @@ void add_defs_selective_instr(aflcc_state_t *aflcc) { } -/* As documented in instrumentation/README.persistent_mode.md, deferred - forkserver initialization and persistent mode are not available in afl-gcc - and afl-clang. */ +/* + Macro defs for persistent mode. As documented in + instrumentation/README.persistent_mode.md, deferred forkserver initialization + and persistent mode are not available in afl-gcc and afl-clang. +*/ void add_defs_persistent_mode(aflcc_state_t *aflcc) { if (aflcc->compiler_mode == GCC || aflcc->compiler_mode == CLANG) return; @@ -1549,7 +1620,11 @@ void add_defs_persistent_mode(aflcc_state_t *aflcc) { } -/* Control _FORTIFY_SOURCE */ +/* + Control macro def of _FORTIFY_SOURCE. It will do nothing + if we detect this routine has been called previously, or + the macro already here in these existing args. +*/ void add_defs_fortify(aflcc_state_t *aflcc, u8 action) { if (aflcc->have_fortify) { return; } @@ -1574,6 +1649,7 @@ void add_defs_fortify(aflcc_state_t *aflcc, u8 action) { } +/* Macro defs of __AFL_LEAK_CHECK, __AFL_LSAN_ON and __AFL_LSAN_OFF */ void add_defs_lsan_ctrl(aflcc_state_t *aflcc) { insert_param(aflcc, "-includesanitizer/lsan_interface.h"); @@ -1586,7 +1662,9 @@ void add_defs_lsan_ctrl(aflcc_state_t *aflcc) { } -/* About fsanitize (including PCGUARD features) */ +/** Macro defs for the preprocessor -----END----- **/ + +/** About -fsanitize -----BEGIN----- **/ /* For input "-fsanitize=...", it: @@ -1665,6 +1743,16 @@ static u8 fsanitize_fuzzer_comma(char *string) { } +/* + Parse and process possible -fsanitize related args, return PARAM_MISS + if nothing matched. We have 3 main tasks here for these args: + - Check which one of those sanitizers present here. + - Check if libfuzzer present. We need to block the request of enable + libfuzzer, and link harness with our libAFLDriver.a later. + - Check if SanCov allow/denylist options present. We need to try switching + to LLVMNATIVE instead of using our optimized PCGUARD anyway. If we + can't make it finally for various reasons, just drop these options. +*/ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { param_st final_ = PARAM_MISS; @@ -1706,22 +1794,8 @@ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { #undef HAVE_SANITIZER_SCAN_KEEP - if (!strncmp(cur_argv, "-fsanitize-coverage-", 20) && - strstr(cur_argv, "list=")) { - - if (scan) { - - aflcc->have_instr_list = 1; - final_ = PARAM_SCAN; - - } else { - - final_ = PARAM_KEEP; - - } - - } - + // We can't use a "else if" there, because some of the following + // matching rules overlap with those in the if-statement above. if (!strcmp(cur_argv, "-fsanitize=fuzzer")) { if (scan) { @@ -1761,25 +1835,27 @@ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { } - } else if ((!strncmp(cur_argv, "-fsanitize=fuzzer-", + } else if (!strncmp(cur_argv, "-fsanitize-coverage-", 20) && - strlen("-fsanitize=fuzzer-")) || - !strncmp(cur_argv, "-fsanitize-coverage", - strlen("-fsanitize-coverage"))) && - (strncmp(cur_argv, "sanitize-coverage-allow", - strlen("sanitize-coverage-allow")) && - strncmp(cur_argv, "sanitize-coverage-deny", - strlen("sanitize-coverage-deny")) && - aflcc->instrument_mode != INSTRUMENT_LLVMNATIVE)) { + strstr(cur_argv, "list=")) { if (scan) { + aflcc->have_instr_list = 1; final_ = PARAM_SCAN; } else { - if (!be_quiet) { WARNF("Found '%s' - stripping!", cur_argv); } - final_ = PARAM_DROP; + if (aflcc->instrument_mode != INSTRUMENT_LLVMNATIVE) { + + if (!be_quiet) { WARNF("Found '%s' - stripping!", cur_argv); } + final_ = PARAM_DROP; + + } else { + + final_ = PARAM_KEEP; + + } } @@ -1791,6 +1867,16 @@ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { } +/* + Add params for sanitizers. Here we need to consider: + - Use static runtime for asan, as much as possible. + - ASAN, MSAN, AFL_HARDEN are mutually exclusive. + - Add options if not found there, on request of AFL_USE_ASAN, AFL_USE_MSAN, + etc. + - Update have_* so that functions called after this can have correct context. + However this also means any functions called before should NOT depend on + these have_*, otherwise they may not work as expected. +*/ void add_sanitizers(aflcc_state_t *aflcc, char **envp) { if (getenv("AFL_USE_ASAN") || aflcc->have_asan) { @@ -1820,7 +1906,7 @@ void add_sanitizers(aflcc_state_t *aflcc, char **envp) { FATAL("MSAN and AFL_HARDEN are mutually exclusive"); add_defs_fortify(aflcc, 0); - insert_param(aflcc, "-fsanitize=memory"); + if (!aflcc->have_msan) { insert_param(aflcc, "-fsanitize=memory"); } aflcc->have_msan = 1; } @@ -1907,6 +1993,7 @@ void add_sanitizers(aflcc_state_t *aflcc, char **envp) { } +/* Add params to enable LLVM SanCov, the native PCGUARD */ void add_native_pcguard(aflcc_state_t *aflcc) { /* If there is a rust ASan runtime on the command line, it is likely we're @@ -1943,6 +2030,11 @@ void add_native_pcguard(aflcc_state_t *aflcc) { } +/* + Add params to launch our optimized PCGUARD on request. + It will fallback to use the native PCGUARD in some cases. If so, plz + bear in mind that instrument_mode will be set to INSTRUMENT_LLVMNATIVE. +*/ void add_optimized_pcguard(aflcc_state_t *aflcc) { #if LLVM_MAJOR >= 13 @@ -1959,7 +2051,7 @@ void add_optimized_pcguard(aflcc_state_t *aflcc) { SAYF( "Using unoptimized trace-pc-guard, due usage of " "-fsanitize-coverage-allow/denylist, you can use " - "AFL_LLVM_ALLOWLIST/AFL_LLMV_DENYLIST instead.\n"); + "AFL_LLVM_ALLOWLIST/AFL_LLVM_DENYLIST instead.\n"); insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; @@ -1994,8 +2086,14 @@ void add_optimized_pcguard(aflcc_state_t *aflcc) { } -/* Linking behaviors */ +/** About -fsanitize -----END----- **/ +/** Linking behaviors -----BEGIN----- **/ + +/* + Parse and process possible linking stage related args, + return PARAM_MISS if nothing matched. +*/ param_st parse_linking_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan, u8 *skip_next, char **argv) { @@ -2158,6 +2256,7 @@ param_st parse_linking_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan, } +/* Add params to specify the linker used in LTO */ void add_lto_linker(aflcc_state_t *aflcc) { unsetenv("AFL_LD"); @@ -2197,6 +2296,7 @@ void add_lto_linker(aflcc_state_t *aflcc) { } +/* Add params to launch SanitizerCoverageLTO.so when linking */ void add_lto_passes(aflcc_state_t *aflcc) { #if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 15 @@ -2215,6 +2315,7 @@ void add_lto_passes(aflcc_state_t *aflcc) { } +/* Add params to link with libAFLDriver.a on request */ static void add_aflpplib(aflcc_state_t *aflcc) { if (!aflcc->need_aflpplib) return; @@ -2250,6 +2351,7 @@ static void add_aflpplib(aflcc_state_t *aflcc) { } +/* Add params to link with runtimes depended by our instrumentation */ void add_runtime(aflcc_state_t *aflcc) { if (aflcc->preprocessor_only || aflcc->have_c || !aflcc->non_dash) { @@ -2345,8 +2447,14 @@ void add_runtime(aflcc_state_t *aflcc) { } -/* Misc */ +/** Linking behaviors -----END----- **/ + +/** Miscellaneous routines -----BEGIN----- **/ +/* + Add params to make compiler driver use our afl-as + as assembler, required by the vanilla instrumentation. +*/ void add_assembler(aflcc_state_t *aflcc) { u8 *afl_as = find_object(aflcc, "as"); @@ -2363,6 +2471,7 @@ void add_assembler(aflcc_state_t *aflcc) { } +/* Add params to launch the gcc plugins for instrumentation. */ void add_gcc_plugin(aflcc_state_t *aflcc) { if (aflcc->cmplog_mode) { @@ -2379,6 +2488,7 @@ void add_gcc_plugin(aflcc_state_t *aflcc) { } +/* Add some miscellaneous params required by our instrumentation. */ void add_misc_params(aflcc_state_t *aflcc) { if (getenv("AFL_NO_BUILTIN") || getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES") || @@ -2425,6 +2535,10 @@ void add_misc_params(aflcc_state_t *aflcc) { } +/* + Parse and process a variety of args under our matching rules, + return PARAM_MISS if nothing matched. +*/ param_st parse_misc_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { param_st final_ = PARAM_MISS; @@ -2575,6 +2689,9 @@ param_st parse_misc_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { } +/** Miscellaneous routines -----END----- **/ + +/* Print help message on request */ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { if (argc < 2 || strncmp(argv[1], "-h", 2) == 0) { @@ -2870,6 +2987,24 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { } +/* + Process params passed to afl-cc. + + We have two working modes, *scan* and *non-scan*. In scan mode, + the main task is to set some variables in aflcc according to current argv[i], + while in non-scan mode, is to choose keep or drop current argv[i]. + + We have several matching routines being called sequentially in the while-loop, + and each of them try to parse and match current argv[i] according to their own + rules. If one miss match, the next will then take over. In non-scan mode, each + argv[i] mis-matched by all the routines will be kept. + + These routines are: + 1. parse_misc_params + 2. parse_fsanitize + 3. parse_linking_params + 4. `if (*cur == '@') {...}`, i.e., parse response files +*/ static void process_params(aflcc_state_t *aflcc, u8 scan, u32 argc, char **argv) { @@ -2896,134 +3031,249 @@ static void process_params(aflcc_state_t *aflcc, u8 scan, u32 argc, if (PARAM_MISS != parse_linking_params(aflcc, cur, scan, &skip_next, argv)) continue; + /* Response file support -----BEGIN----- + We have two choices - move everything to the command line or + rewrite the response files to temporary files and delete them + afterwards. We choose the first for easiness. + For clang, llvm::cl::ExpandResponseFiles does this, however it + only has C++ interface. And for gcc there is expandargv in libiberty, + written in C, but we can't simply copy-paste since its LGPL licensed. + So here we use an equivalent FSM as alternative, and try to be compatible + with the two above. See: + - https://gcc.gnu.org/onlinedocs/gcc/Overall-Options.html + - driver::expand_at_files in gcc.git/gcc/gcc.c + - expandargv in gcc.git/libiberty/argv.c + - llvm-project.git/clang/tools/driver/driver.cpp + - ExpandResponseFiles in + llvm-project.git/llvm/lib/Support/CommandLine.cpp + */ if (*cur == '@') { - // response file support. - // we have two choices - move everything to the command line or - // rewrite the response files to temporary files and delete them - // afterwards. We choose the first for easiness. - // We do *not* support quotes in the rsp files to cope with spaces in - // filenames etc! If you need that then send a patch! u8 *filename = cur + 1; if (aflcc->debug) { DEBUGF("response file=%s\n", filename); } - FILE *f = fopen(filename, "r"); - struct stat st; // Check not found or empty? let the compiler complain if so. - if (!f || fstat(fileno(f), &st) < 0 || st.st_size < 1) { + FILE *f = fopen(filename, "r"); + if (!f) { if (!scan) insert_param(aflcc, cur); continue; } - u8 *tmpbuf = malloc(st.st_size + 2), *ptr; - char **args = malloc(sizeof(char *) * (st.st_size >> 1)); - int count = 1, cont = 0, cont_act = 0; + struct stat st; + if (fstat(fileno(f), &st) || !S_ISREG(st.st_mode) || st.st_size < 1) { - while (fgets(tmpbuf, st.st_size + 1, f)) { + fclose(f); + if (!scan) insert_param(aflcc, cur); + continue; - ptr = tmpbuf; - // fprintf(stderr, "1: %s\n", ptr); - // no leading whitespace - while (isspace(*ptr)) { + } - ++ptr; - cont_act = 0; + // Limit the number of response files, the max value + // just keep consistent with expandargv. Only do this in + // scan mode, and not touch rsp_count anymore in the next. + static u32 rsp_count = 2000; + if (scan) { - } + if (rsp_count == 0) FATAL("Too many response files provided!"); - // no comments, no empty lines - if (*ptr == '#' || *ptr == '\n' || !*ptr) { continue; } - // remove LF - if (ptr[strlen(ptr) - 1] == '\n') { ptr[strlen(ptr) - 1] = 0; } - // remove CR - if (*ptr && ptr[strlen(ptr) - 1] == '\r') { ptr[strlen(ptr) - 1] = 0; } - // handle \ at end of line - if (*ptr && ptr[strlen(ptr) - 1] == '\\') { + --rsp_count; - cont = 1; - ptr[strlen(ptr) - 1] = 0; + } - } + // argc, argv acquired from this rsp file. Note that + // process_params ignores argv[0], we need to put a const "" here. + u32 argc_read = 1; + char **argv_read = ck_alloc(sizeof(char *)); + argv_read[0] = ""; + + char *arg_buf = NULL; + u64 arg_len = 0; + + enum fsm_state { + + fsm_whitespace, // whitespace seen so far + fsm_double_quote, // have unpaired double quote + fsm_single_quote, // have unpaired single quote + fsm_backslash, // a backslash is seen with no unpaired quote + fsm_normal // a normal char is seen + + }; + + // Workaround to append c to arg buffer, and append the buffer to argv +#define ARG_ALLOC(c) \ + do { \ + \ + ++arg_len; \ + arg_buf = ck_realloc(arg_buf, (arg_len + 1) * sizeof(char)); \ + arg_buf[arg_len] = '\0'; \ + arg_buf[arg_len - 1] = (char)c; \ + \ + } while (0) + +#define ARG_STORE() \ + do { \ + \ + ++argc_read; \ + argv_read = ck_realloc(argv_read, argc_read * sizeof(char *)); \ + argv_read[argc_read - 1] = arg_buf; \ + arg_buf = NULL; \ + arg_len = 0; \ + \ + } while (0) - // fprintf(stderr, "2: %s\n", ptr); + int cur_chr = (int)' '; // init as whitespace, as a good start :) + enum fsm_state state_ = fsm_whitespace; - // remove whitespace at end - while (*ptr && isspace(ptr[strlen(ptr) - 1])) { + while (cur_chr != EOF) { - ptr[strlen(ptr) - 1] = 0; - cont = 0; + switch (state_) { - } + case fsm_whitespace: + + if (arg_buf) { + + ARG_STORE(); + break; + + } - // fprintf(stderr, "3: %s\n", ptr); - if (*ptr) { + if (isspace(cur_chr)) { - do { + cur_chr = fgetc(f); - u8 *value = ptr; - while (*ptr && !isspace(*ptr)) { + } else if (cur_chr == (int)'\'') { - ++ptr; + state_ = fsm_single_quote; + cur_chr = fgetc(f); + + } else if (cur_chr == (int)'"') { + + state_ = fsm_double_quote; + cur_chr = fgetc(f); + + } else if (cur_chr == (int)'\\') { + + state_ = fsm_backslash; + cur_chr = fgetc(f); + + } else { + + state_ = fsm_normal; } - while (*ptr && isspace(*ptr)) { + break; + + case fsm_normal: - *ptr++ = 0; + if (isspace(cur_chr)) { + + state_ = fsm_whitespace; + + } else if (cur_chr == (int)'\'') { + + state_ = fsm_single_quote; + cur_chr = fgetc(f); + + } else if (cur_chr == (int)'\"') { + + state_ = fsm_double_quote; + cur_chr = fgetc(f); + + } else if (cur_chr == (int)'\\') { + + state_ = fsm_backslash; + cur_chr = fgetc(f); + + } else { + + ARG_ALLOC(cur_chr); + cur_chr = fgetc(f); } - if (cont_act) { + break; + + case fsm_backslash: + + ARG_ALLOC(cur_chr); + cur_chr = fgetc(f); + state_ = fsm_normal; + + break; + + case fsm_single_quote: + + if (cur_chr == (int)'\\') { + + cur_chr = fgetc(f); + if (cur_chr == EOF) break; + ARG_ALLOC(cur_chr); + + } else if (cur_chr == (int)'\'') { - u32 len = strlen(args[count - 1]) + strlen(value) + 1; - u8 *tmp = malloc(len); - snprintf(tmp, len, "%s%s", args[count - 1], value); - free(args[count - 1]); - args[count - 1] = tmp; - cont_act = 0; + state_ = fsm_normal; } else { - args[count++] = strdup(value); + ARG_ALLOC(cur_chr); } - } while (*ptr); + cur_chr = fgetc(f); + break; - } + case fsm_double_quote: + + if (cur_chr == (int)'\\') { + + cur_chr = fgetc(f); + if (cur_chr == EOF) break; + ARG_ALLOC(cur_chr); + + } else if (cur_chr == (int)'"') { + + state_ = fsm_normal; + + } else { + + ARG_ALLOC(cur_chr); - if (cont) { + } + + cur_chr = fgetc(f); + break; - cont_act = 1; - cont = 0; + default: + break; } } - if (count) { process_params(aflcc, scan, count, args); } + if (arg_buf) { ARG_STORE(); } // save the pending arg after EOF - // we cannot free args[] unless we don't need - // to keep any reference in cc_params - if (scan) { +#undef ARG_ALLOC +#undef ARG_STORE - if (count) do { + if (argc_read > 1) { process_params(aflcc, scan, argc_read, argv_read); } - free(args[--count]); + // We cannot free argv_read[] unless we don't need to keep any + // reference in cc_params. Never free argv[0], the const "". + if (scan) { - } while (count); + while (argc_read > 1) + ck_free(argv_read[--argc_read]); - free(args); + ck_free(argv_read); } - free(tmpbuf); - continue; - } + } /* Response file support -----END----- */ if (!scan) insert_param(aflcc, cur); @@ -3031,8 +3281,7 @@ static void process_params(aflcc_state_t *aflcc, u8 scan, u32 argc, } -/* Copy argv to cc_params, making the necessary edits. */ - +/* Process each of the existing argv, also add a few new args. */ static void edit_params(aflcc_state_t *aflcc, u32 argc, char **argv, char **envp) { @@ -3173,7 +3422,6 @@ static void edit_params(aflcc_state_t *aflcc, u32 argc, char **argv, } /* Main entry point */ - int main(int argc, char **argv, char **envp) { aflcc_state_t *aflcc = malloc(sizeof(aflcc_state_t)); -- cgit v1.2.3 From 97ba817aa78888b318a76fa278a6fc4454cec1b7 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 1 Feb 2024 09:56:31 +0100 Subject: debug ci --- src/afl-cc.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index c300ddfc..5e28ff6f 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -51,6 +51,9 @@ #define MAX_PARAMS_NUM 2048 #endif +#undef LLVM_MAJOR +#define LLVM_MAJOR 10 + /** Global declarations -----BEGIN----- **/ typedef enum { @@ -3452,6 +3455,8 @@ int main(int argc, char **argv, char **envp) { if (aflcc->debug) debugf_args((s32)aflcc->cc_par_cnt, (char **)aflcc->cc_params); + printf("DEBUGXXX: param0=%s aflcc->compiler_mode=%d aflcc->instrument_mode=%d\n", aflcc->cc_params[0], aflcc->compiler_mode, aflcc->instrument_mode); + if (aflcc->passthrough) { argv[0] = aflcc->cc_params[0]; -- cgit v1.2.3 From 7793692590b08ff05e513ad679df419bed974723 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 1 Feb 2024 10:26:16 +0100 Subject: debug ci --- src/afl-cc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 5e28ff6f..8b247597 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -51,9 +51,6 @@ #define MAX_PARAMS_NUM 2048 #endif -#undef LLVM_MAJOR -#define LLVM_MAJOR 10 - /** Global declarations -----BEGIN----- **/ typedef enum { @@ -3442,6 +3439,8 @@ int main(int argc, char **argv, char **envp) { mode_final_checkout(aflcc, argc, argv); + printf("DEBUGXXX: param0=%s aflcc->compiler_mode=%d aflcc->instrument_mode=%d\n", aflcc->cc_params[0], aflcc->compiler_mode, aflcc->instrument_mode); + process_params(aflcc, 1, argc, argv); maybe_usage(aflcc, argc, argv); -- cgit v1.2.3 From 76a033431d1d7ca7bcbe47e4ff42cf03b9874f57 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 1 Feb 2024 11:16:16 +0100 Subject: debug ci --- src/afl-cc.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 8b247597..a3b453fc 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -3439,22 +3439,28 @@ int main(int argc, char **argv, char **envp) { mode_final_checkout(aflcc, argc, argv); - printf("DEBUGXXX: param0=%s aflcc->compiler_mode=%d aflcc->instrument_mode=%d\n", aflcc->cc_params[0], aflcc->compiler_mode, aflcc->instrument_mode); + printf("DEBUGXXX0: param0=%s aflcc->compiler_mode=%d aflcc->instrument_mode=%d\n", aflcc->cc_params[0], aflcc->compiler_mode, aflcc->instrument_mode); process_params(aflcc, 1, argc, argv); maybe_usage(aflcc, argc, argv); + printf("DEBUGXXX1: param0=%s aflcc->compiler_mode=%d aflcc->instrument_mode=%d\n", aflcc->cc_params[0], aflcc->compiler_mode, aflcc->instrument_mode); + mode_notification(aflcc); if (aflcc->debug) debugf_args(argc, argv); + printf("DEBUGXXX2: param0=%s aflcc->compiler_mode=%d aflcc->instrument_mode=%d\n", aflcc->cc_params[0], aflcc->compiler_mode, aflcc->instrument_mode); + edit_params(aflcc, argc, argv, envp); + printf("DEBUGXXX3: param0=%s aflcc->compiler_mode=%d aflcc->instrument_mode=%d\n", aflcc->cc_params[0], aflcc->compiler_mode, aflcc->instrument_mode); + if (aflcc->debug) debugf_args((s32)aflcc->cc_par_cnt, (char **)aflcc->cc_params); - printf("DEBUGXXX: param0=%s aflcc->compiler_mode=%d aflcc->instrument_mode=%d\n", aflcc->cc_params[0], aflcc->compiler_mode, aflcc->instrument_mode); + printf("DEBUGXXX4: param0=%s aflcc->compiler_mode=%d aflcc->instrument_mode=%d\n", aflcc->cc_params[0], aflcc->compiler_mode, aflcc->instrument_mode); if (aflcc->passthrough) { -- cgit v1.2.3 From e5d305ad42dc29030cb256f3182a316cc806b6da Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 1 Feb 2024 11:43:04 +0100 Subject: debug ci --- src/afl-cc.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index a3b453fc..24dc1055 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1458,11 +1458,13 @@ void add_real_argv0(aflcc_state_t *aflcc) { } else { u8 *alt_cc = getenv("AFL_CC"); +printf("AFL_CC=%s\n", alt_cc); if (!alt_cc) { if (aflcc->compiler_mode == GCC || aflcc->compiler_mode == GCC_PLUGIN) { +printf("is gcc %d == %d || %d == %d\n", aflcc->compiler_mode, GCC, aflcc->compiler_mode, GCC_PLUGIN); alt_cc = "gcc"; } else if (aflcc->compiler_mode == CLANG) { @@ -1478,6 +1480,8 @@ void add_real_argv0(aflcc_state_t *aflcc) { snprintf(llvm_fullpath, sizeof(llvm_fullpath), CLANG_BIN); alt_cc = llvm_fullpath; +printf("use_bindir=%s llvm_fullpath=%s\n", USE_BINDIR ? "true" : "false", llvm_fullpath); + } } -- cgit v1.2.3 From eb52f1cc08e0aacc3c46d1c5a9742526657c842a Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 1 Feb 2024 12:58:51 +0100 Subject: fix ci --- src/afl-cc.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 24dc1055..c300ddfc 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1458,13 +1458,11 @@ void add_real_argv0(aflcc_state_t *aflcc) { } else { u8 *alt_cc = getenv("AFL_CC"); -printf("AFL_CC=%s\n", alt_cc); if (!alt_cc) { if (aflcc->compiler_mode == GCC || aflcc->compiler_mode == GCC_PLUGIN) { -printf("is gcc %d == %d || %d == %d\n", aflcc->compiler_mode, GCC, aflcc->compiler_mode, GCC_PLUGIN); alt_cc = "gcc"; } else if (aflcc->compiler_mode == CLANG) { @@ -1480,8 +1478,6 @@ printf("is gcc %d == %d || %d == %d\n", aflcc->compiler_mode, GCC, aflcc->compil snprintf(llvm_fullpath, sizeof(llvm_fullpath), CLANG_BIN); alt_cc = llvm_fullpath; -printf("use_bindir=%s llvm_fullpath=%s\n", USE_BINDIR ? "true" : "false", llvm_fullpath); - } } @@ -3443,29 +3439,19 @@ int main(int argc, char **argv, char **envp) { mode_final_checkout(aflcc, argc, argv); - printf("DEBUGXXX0: param0=%s aflcc->compiler_mode=%d aflcc->instrument_mode=%d\n", aflcc->cc_params[0], aflcc->compiler_mode, aflcc->instrument_mode); - process_params(aflcc, 1, argc, argv); maybe_usage(aflcc, argc, argv); - printf("DEBUGXXX1: param0=%s aflcc->compiler_mode=%d aflcc->instrument_mode=%d\n", aflcc->cc_params[0], aflcc->compiler_mode, aflcc->instrument_mode); - mode_notification(aflcc); if (aflcc->debug) debugf_args(argc, argv); - printf("DEBUGXXX2: param0=%s aflcc->compiler_mode=%d aflcc->instrument_mode=%d\n", aflcc->cc_params[0], aflcc->compiler_mode, aflcc->instrument_mode); - edit_params(aflcc, argc, argv, envp); - printf("DEBUGXXX3: param0=%s aflcc->compiler_mode=%d aflcc->instrument_mode=%d\n", aflcc->cc_params[0], aflcc->compiler_mode, aflcc->instrument_mode); - if (aflcc->debug) debugf_args((s32)aflcc->cc_par_cnt, (char **)aflcc->cc_params); - printf("DEBUGXXX4: param0=%s aflcc->compiler_mode=%d aflcc->instrument_mode=%d\n", aflcc->cc_params[0], aflcc->compiler_mode, aflcc->instrument_mode); - if (aflcc->passthrough) { argv[0] = aflcc->cc_params[0]; -- cgit v1.2.3 From eda770fd32b804e3ebd6a43738c0002f6118a463 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Thu, 1 Feb 2024 15:13:07 +0100 Subject: push to stable (#1967) * Output afl-clang-fast stuffs only if necessary (#1912) * afl-cc header * afl-cc common declarations - Add afl-cc-state.c - Strip includes, find_object, debug/be_quiet/have_*/callname setting from afl-cc.c - Use debugf_args in main - Modify execvp stuffs to fit new aflcc struct * afl-cc show usage * afl-cc mode selecting 1. compiler_mode by callname in argv[0] 2. compiler_mode by env "AFL_CC_COMPILER" 3. compiler_mode/instrument_mode by command line options "--afl-..." 4. instrument_mode/compiler_mode by various env vars including "AFL_LLVM_INSTRUMENT" 5. final checking steps 6. print "... - mode: %s-%s\n" 7. determine real argv[0] according to compiler_mode * afl-cc macro defs * afl-cc linking behaviors * afl-cc fsanitize behaviors * afl-cc misc * afl-cc body update * afl-cc all-in-one formated with custom-format.py * nits --------- Co-authored-by: vanhauser-thc * changelog * update grammar mutator * lto llvm 12+ * docs(custom_mutators): fix missing ':' (#1953) * Fix broken LTO mode and response file support (#1948) * Strip `-Wl,-no-undefined` during compilation (#1952) Make the compiler wrapper stripping `-Wl,-no-undefined` in addition to `-Wl,--no-undefined`. Both versions of the flag are accepted by clang and, therefore, used by building systems in the wild (e.g., samba will not build without this fix). * Remove dead code in write_to_testcase (#1955) The custom_mutators_count check in if case is duplicate with if condition. The else case is custom_mutators_count == 0, neither custom_mutator_list iteration nor sent check needed. Signed-off-by: Xeonacid * update qemuafl * WIP: Add ability to generate drcov trace using QEMU backend (#1956) * Document new drcov QEMU plugin * Add link to lightkeeper for QEMU drcov file loading --------- Co-authored-by: Jean-Romain Garnier * code format * changelog * sleep on uid != 0 afl-system-config * fix segv about skip_next, warn on unsupported cases of linking options (#1958) * todos * ensure afl-cc only allows available compiler modes * update grammar mutator * disable aslr on apple * fix for arm64 * help selective instrumentation * typos * macos * add compiler test script * apple fixes * bump nyx submodules (#1963) * fix docs * update changelog * update grammar mutator * improve compiler test script * gcc asan workaround (#1966) * fix github merge fuckup * fix * Fix afl-cc (#1968) - Check if too many cmdline params here, each time before insert a new param. - Check if it is "-fsanitize=..." before we do sth. - Remove improper param_st transfer. * Avoid adding llvmnative instrumentation when linking rust sanitizer runtime (#1969) * Dynamic instrumentation filtering for LLVM native (#1971) * Add two dynamic instrumentation filter methods to runtime * Always use pc-table with native pcguard * Add make_symbol_list.py and README * changelog * todos * new forkserver check * fix * nyx test for CI * improve nyx docs * Fixes to afl-cc and documentation (#1974) * Always compile with -ldl when building for CODE_COVERAGE When building with CODE_COVERAGE, the afl runtime contains code that calls `dladdr` which requires -ldl. Under most circumstances, clang already adds this (e.g. when building with pc-table), but there are some circumstances where it isn't added automatically. * Add visibility declaration to __afl_connected When building with hidden visibility, the use of __AFL_LOOP inside such code can cause linker errors due to __afl_connected being declared "hidden". * Update docs to clarify that CODE_COVERAGE=1 is required for dynamic_covfilter * nits * nyx build script updates * test error output * debug ci * debug ci * Improve afl-cc (#1975) * update response file support - full support of rsp file - fix some segv issues * Improve afl-cc - remove dead code about allow/denylist options of sancov - missing `if (!aflcc->have_msan)` - add docs for each function - typo * enable nyx * debug ci * debug ci * debug ci * debug ci * debug ci * debug ci * debug ci * debug ci * fix ci * clean test script * NO_NYX * NO_NYX * fix ci * debug ci * fix ci * finalize ci fix --------- Signed-off-by: Xeonacid Co-authored-by: Sonic <50692172+SonicStark@users.noreply.github.com> Co-authored-by: Xeonacid Co-authored-by: Nils Bars Co-authored-by: Jean-Romain Garnier <7504819+JRomainG@users.noreply.github.com> Co-authored-by: Jean-Romain Garnier Co-authored-by: Sergej Schumilo Co-authored-by: Christian Holler (:decoder) --- src/afl-cc.c | 753 ++++++++++++++++++++++++++++++++++++--------------- src/afl-forkserver.c | 6 + src/afl-fuzz-init.c | 6 + src/afl-fuzz.c | 11 +- 4 files changed, 554 insertions(+), 222 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 192c5423..c300ddfc 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -51,7 +51,7 @@ #define MAX_PARAMS_NUM 2048 #endif -/* Global declarations */ +/** Global declarations -----BEGIN----- **/ typedef enum { @@ -170,8 +170,11 @@ typedef struct aflcc_state { u8 have_instr_env, have_gcc, have_clang, have_llvm, have_gcc_plugin, have_lto, have_optimized_pcguard, have_instr_list; - u8 fortify_set, asan_set, x_set, bit_mode, preprocessor_only, have_unroll, - have_o, have_pic, have_c, shared_linking, partial_linking, non_dash; + u8 fortify_set, x_set, bit_mode, preprocessor_only, have_unroll, have_o, + have_pic, have_c, shared_linking, partial_linking, non_dash, have_fp, + have_flto, have_hidden, have_fortify, have_fcf, have_staticasan, + have_rust_asanrt, have_asan, have_msan, have_ubsan, have_lsan, have_tsan, + have_cfisan; // u8 *march_opt; u8 need_aflpplib; @@ -184,25 +187,27 @@ typedef struct aflcc_state { void aflcc_state_init(aflcc_state_t *, u8 *argv0); -/* Try to find a specific runtime we need, the path to obj would be - allocated and returned. Otherwise it returns NULL on fail. */ u8 *find_object(aflcc_state_t *, u8 *obj); void find_built_deps(aflcc_state_t *); -static inline void limit_params(aflcc_state_t *aflcc, u32 add) { +/* Insert param into the new argv, raise error if MAX_PARAMS_NUM exceeded. */ +static inline void insert_param(aflcc_state_t *aflcc, u8 *param) { - if (aflcc->cc_par_cnt + add >= MAX_PARAMS_NUM) + if (unlikely(aflcc->cc_par_cnt + 1 >= MAX_PARAMS_NUM)) FATAL("Too many command line parameters, please increase MAX_PARAMS_NUM."); -} - -static inline void insert_param(aflcc_state_t *aflcc, u8 *param) { - aflcc->cc_params[aflcc->cc_par_cnt++] = param; } +/* + Insert a param which contains path to the object file. It uses find_object to + get the path based on the name `obj`, and then uses a sprintf like method to + format it with `fmt`. If `fmt` is NULL, the inserted arg is same as the path. + If `msg` provided, it should be an error msg raised if the path can't be + found. `obj` must not be NULL. +*/ static inline void insert_object(aflcc_state_t *aflcc, u8 *obj, u8 *fmt, u8 *msg) { @@ -232,6 +237,7 @@ static inline void insert_object(aflcc_state_t *aflcc, u8 *obj, u8 *fmt, } +/* Insert params into the new argv, make clang load the pass. */ static inline void load_llvm_pass(aflcc_state_t *aflcc, u8 *pass) { #if LLVM_MAJOR >= 11 /* use new pass manager */ @@ -292,8 +298,12 @@ void add_lto_linker(aflcc_state_t *); void add_lto_passes(aflcc_state_t *); void add_runtime(aflcc_state_t *); -/* Working state */ +/** Global declarations -----END----- **/ +/* + Init global state struct. We also extract the callname, + check debug options and if in C++ mode here. +*/ void aflcc_state_init(aflcc_state_t *aflcc, u8 *argv0) { // Default NULL/0 is a good start @@ -353,7 +363,7 @@ void aflcc_state_init(aflcc_state_t *aflcc, u8 *argv0) { } /* - in find_object() we look here: + Try to find a specific runtime we need, in here: 1. firstly we check the $AFL_PATH environment variable location if set 2. next we check argv[0] if it has path information and use it @@ -367,7 +377,6 @@ void aflcc_state_init(aflcc_state_t *aflcc, u8 *argv0) { if all these attempts fail - we return NULL and the caller has to decide what to do. Otherwise the path to obj would be allocated and returned. */ - u8 *find_object(aflcc_state_t *aflcc, u8 *obj) { u8 *argv0 = aflcc->argv0; @@ -500,6 +509,10 @@ u8 *find_object(aflcc_state_t *aflcc, u8 *obj) { } +/* + Deduce some info about compiler toolchains in current system, + from the building results of AFL++ +*/ void find_built_deps(aflcc_state_t *aflcc) { char *ptr = NULL; @@ -572,8 +585,9 @@ void find_built_deps(aflcc_state_t *aflcc) { } -/* compiler_mode & instrument_mode selecting */ +/** compiler_mode & instrument_mode selecting -----BEGIN----- **/ +/* Select compiler_mode by callname, such as "afl-clang-fast", etc. */ void compiler_mode_by_callname(aflcc_state_t *aflcc) { if (strncmp(aflcc->callname, "afl-clang-fast", 14) == 0) { @@ -611,30 +625,26 @@ void compiler_mode_by_callname(aflcc_state_t *aflcc) { aflcc->compiler_mode = GCC_PLUGIN; -#if defined(__x86_64__) - } else if (strncmp(aflcc->callname, "afl-gcc", 7) == 0 || strncmp(aflcc->callname, "afl-g++", 7) == 0) { aflcc->compiler_mode = GCC; -#endif - -#if defined(__x86_64__) - } else if (strcmp(aflcc->callname, "afl-clang") == 0 || strcmp(aflcc->callname, "afl-clang++") == 0) { aflcc->compiler_mode = CLANG; -#endif - } } +/* + Select compiler_mode by env AFL_CC_COMPILER. And passthrough mode can be + regarded as a special compiler_mode, so we check for it here, too. +*/ void compiler_mode_by_environ(aflcc_state_t *aflcc) { if (getenv("AFL_PASSTHROUGH") || getenv("AFL_NOOPT")) { @@ -675,22 +685,14 @@ void compiler_mode_by_environ(aflcc_state_t *aflcc) { aflcc->compiler_mode = GCC_PLUGIN; -#if defined(__x86_64__) - } else if (strcasecmp(ptr, "GCC") == 0) { aflcc->compiler_mode = GCC; -#endif - -#if defined(__x86_64__) - } else if (strcasecmp(ptr, "CLANG") == 0) { aflcc->compiler_mode = CLANG; -#endif - } else FATAL("Unknown AFL_CC_COMPILER mode: %s\n", ptr); @@ -699,7 +701,13 @@ void compiler_mode_by_environ(aflcc_state_t *aflcc) { } -// If it can be inferred, instrument_mode would also be set +/* + Select compiler_mode by command line options --afl-... + If it can be inferred, instrument_mode would also be set. + This can supersedes previous result based on callname + or AFL_CC_COMPILER. And "--afl_noopt"/"--afl-noopt" will + be overwritten by "-g". +*/ void compiler_mode_by_cmdline(aflcc_state_t *aflcc, int argc, char **argv) { char *ptr = NULL; @@ -774,22 +782,14 @@ void compiler_mode_by_cmdline(aflcc_state_t *aflcc, int argc, char **argv) { aflcc->compiler_mode = GCC_PLUGIN; -#if defined(__x86_64__) - } else if (strcasecmp(ptr, "GCC") == 0) { aflcc->compiler_mode = GCC; -#endif - -#if defined(__x86_64__) - } else if (strncasecmp(ptr, "CLANG", 5) == 0) { aflcc->compiler_mode = CLANG; -#endif - } else FATAL("Unknown --afl-... compiler mode: %s\n", argv[i]); @@ -800,6 +800,12 @@ void compiler_mode_by_cmdline(aflcc_state_t *aflcc, int argc, char **argv) { } +/* + Select instrument_mode by those envs in old style: + - USE_TRACE_PC, AFL_USE_TRACE_PC, AFL_LLVM_USE_TRACE_PC, AFL_TRACE_PC + - AFL_LLVM_CALLER, AFL_LLVM_CTX, AFL_LLVM_CTX_K + - AFL_LLVM_NGRAM_SIZE +*/ static void instrument_mode_old_environ(aflcc_state_t *aflcc) { if (getenv("AFL_LLVM_INSTRIM") || getenv("INSTRIM") || @@ -859,7 +865,11 @@ static void instrument_mode_old_environ(aflcc_state_t *aflcc) { } -// compiler_mode would also be set if depended by the instrument_mode +/* + Select instrument_mode by env 'AFL_LLVM_INSTRUMENT'. + Previous compiler_mode will be superseded, if required by some + values of instrument_mode. +*/ static void instrument_mode_new_environ(aflcc_state_t *aflcc) { if (!getenv("AFL_LLVM_INSTRUMENT")) { return; } @@ -960,7 +970,6 @@ static void instrument_mode_new_environ(aflcc_state_t *aflcc) { } -#if defined(__x86_64__) if (strcasecmp(ptr2, "gcc") == 0) { if (!aflcc->instrument_mode || aflcc->instrument_mode == INSTRUMENT_GCC) @@ -975,9 +984,6 @@ static void instrument_mode_new_environ(aflcc_state_t *aflcc) { } -#endif - -#if defined(__x86_64__) if (strcasecmp(ptr2, "clang") == 0) { if (!aflcc->instrument_mode || aflcc->instrument_mode == INSTRUMENT_CLANG) @@ -992,8 +998,6 @@ static void instrument_mode_new_environ(aflcc_state_t *aflcc) { } -#endif - if (strncasecmp(ptr2, "ctx-", strlen("ctx-")) == 0 || strncasecmp(ptr2, "kctx-", strlen("c-ctx-")) == 0 || strncasecmp(ptr2, "k-ctx-", strlen("k-ctx-")) == 0) { @@ -1089,6 +1093,11 @@ static void instrument_mode_new_environ(aflcc_state_t *aflcc) { } +/* + Select instrument_mode by envs, the top wrapper. We check + have_instr_env firstly, then call instrument_mode_old_environ + and instrument_mode_new_environ sequentially. +*/ void instrument_mode_by_environ(aflcc_state_t *aflcc) { if (getenv("AFL_LLVM_INSTRUMENT_FILE") || getenv("AFL_LLVM_WHITELIST") || @@ -1112,6 +1121,10 @@ void instrument_mode_by_environ(aflcc_state_t *aflcc) { } +/* + Workaround to ensure CALLER, CTX, K-CTX and NGRAM + instrumentation were used correctly. +*/ static void instrument_opt_mode_exclude(aflcc_state_t *aflcc) { if ((aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX) && @@ -1147,6 +1160,11 @@ static void instrument_opt_mode_exclude(aflcc_state_t *aflcc) { } +/* + Last step of compiler_mode & instrument_mode selecting. + We have a few of workarounds here, to check any corner cases, + prepare for a series of fallbacks, and raise warnings or errors. +*/ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) { if (aflcc->instrument_opt_mode && @@ -1180,11 +1198,11 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) { switch (aflcc->compiler_mode) { case GCC: - if (!aflcc->have_gcc) FATAL("afl-gcc not available on your platform!"); + if (!aflcc->have_gcc) FATAL("afl-gcc is not available on your platform!"); break; case CLANG: if (!aflcc->have_clang) - FATAL("afl-clang not available on your platform!"); + FATAL("afl-clang is not available on your platform!"); break; case LLVM: if (!aflcc->have_llvm) @@ -1351,6 +1369,10 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) { } +/* + Print welcome message on screen, giving brief notes about + compiler_mode and instrument_mode. +*/ void mode_notification(aflcc_state_t *aflcc) { char *ptr2 = alloc_printf(" + NGRAM-%u", aflcc->ngram_size); @@ -1389,6 +1411,17 @@ void mode_notification(aflcc_state_t *aflcc) { } +/* + Set argv[0] required by execvp. It can be + - specified by env AFL_CXX + - g++ or clang++ + - CLANGPP_BIN or LLVM_BINDIR/clang++ + when in C++ mode, or + - specified by env AFL_CC + - gcc or clang + - CLANG_BIN or LLVM_BINDIR/clang + otherwise. +*/ void add_real_argv0(aflcc_state_t *aflcc) { static u8 llvm_fullpath[PATH_MAX]; @@ -1455,7 +1488,9 @@ void add_real_argv0(aflcc_state_t *aflcc) { } -/* Macro defs for the preprocessor */ +/** compiler_mode & instrument_mode selecting -----END----- **/ + +/** Macro defs for the preprocessor -----BEGIN----- **/ void add_defs_common(aflcc_state_t *aflcc) { @@ -1464,8 +1499,11 @@ void add_defs_common(aflcc_state_t *aflcc) { } -/* See instrumentation/README.instrument_list.md# - 2-selective-instrumentation-with-_afl_coverage-directives */ +/* + __afl_coverage macro defs. See + instrumentation/README.instrument_list.md# + 2-selective-instrumentation-with-_afl_coverage-directives +*/ void add_defs_selective_instr(aflcc_state_t *aflcc) { if (aflcc->plusplus_mode) { @@ -1499,9 +1537,11 @@ void add_defs_selective_instr(aflcc_state_t *aflcc) { } -/* As documented in instrumentation/README.persistent_mode.md, deferred - forkserver initialization and persistent mode are not available in afl-gcc - and afl-clang. */ +/* + Macro defs for persistent mode. As documented in + instrumentation/README.persistent_mode.md, deferred forkserver initialization + and persistent mode are not available in afl-gcc and afl-clang. +*/ void add_defs_persistent_mode(aflcc_state_t *aflcc) { if (aflcc->compiler_mode == GCC || aflcc->compiler_mode == CLANG) return; @@ -1552,7 +1592,7 @@ void add_defs_persistent_mode(aflcc_state_t *aflcc) { "({ static volatile const char *_B __attribute__((used,unused)); " " _B = (const char*)\"" PERSIST_SIG "\"; " - "extern int __afl_connected;" + "extern __attribute__((visibility(\"default\"))) int __afl_connected;" #ifdef __APPLE__ "__attribute__((visibility(\"default\"))) " "int _L(unsigned int) __asm__(\"___afl_persistent_loop\"); " @@ -1580,9 +1620,15 @@ void add_defs_persistent_mode(aflcc_state_t *aflcc) { } -/* Control _FORTIFY_SOURCE */ +/* + Control macro def of _FORTIFY_SOURCE. It will do nothing + if we detect this routine has been called previously, or + the macro already here in these existing args. +*/ void add_defs_fortify(aflcc_state_t *aflcc, u8 action) { + if (aflcc->have_fortify) { return; } + switch (action) { case 1: @@ -1599,8 +1645,11 @@ void add_defs_fortify(aflcc_state_t *aflcc, u8 action) { } + aflcc->have_fortify = 1; + } +/* Macro defs of __AFL_LEAK_CHECK, __AFL_LSAN_ON and __AFL_LSAN_OFF */ void add_defs_lsan_ctrl(aflcc_state_t *aflcc) { insert_param(aflcc, "-includesanitizer/lsan_interface.h"); @@ -1613,7 +1662,9 @@ void add_defs_lsan_ctrl(aflcc_state_t *aflcc) { } -/* About fsanitize (including PCGUARD features) */ +/** Macro defs for the preprocessor -----END----- **/ + +/** About -fsanitize -----BEGIN----- **/ /* For input "-fsanitize=...", it: @@ -1692,26 +1743,59 @@ static u8 fsanitize_fuzzer_comma(char *string) { } +/* + Parse and process possible -fsanitize related args, return PARAM_MISS + if nothing matched. We have 3 main tasks here for these args: + - Check which one of those sanitizers present here. + - Check if libfuzzer present. We need to block the request of enable + libfuzzer, and link harness with our libAFLDriver.a later. + - Check if SanCov allow/denylist options present. We need to try switching + to LLVMNATIVE instead of using our optimized PCGUARD anyway. If we + can't make it finally for various reasons, just drop these options. +*/ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { param_st final_ = PARAM_MISS; - if (!strncmp(cur_argv, "-fsanitize-coverage-", 20) && - strstr(cur_argv, "list=")) { - - if (scan) { - - aflcc->have_instr_list = 1; - final_ = PARAM_SCAN; +// MACRO START +#define HAVE_SANITIZER_SCAN_KEEP(v, k) \ + do { \ + \ + if (strstr(cur_argv, "=" STRINGIFY(k)) || \ + strstr(cur_argv, "," STRINGIFY(k))) { \ + \ + if (scan) { \ + \ + aflcc->have_##v = 1; \ + final_ = PARAM_SCAN; \ + \ + } else { \ + \ + final_ = PARAM_KEEP; \ + \ + } \ + \ + } \ + \ + } while (0) - } else { + // MACRO END - final_ = PARAM_KEEP; // may be set to DROP next + if (!strncmp(cur_argv, "-fsanitize=", strlen("-fsanitize="))) { - } + HAVE_SANITIZER_SCAN_KEEP(asan, address); + HAVE_SANITIZER_SCAN_KEEP(msan, memory); + HAVE_SANITIZER_SCAN_KEEP(ubsan, undefined); + HAVE_SANITIZER_SCAN_KEEP(tsan, thread); + HAVE_SANITIZER_SCAN_KEEP(lsan, leak); + HAVE_SANITIZER_SCAN_KEEP(cfisan, cfi); } +#undef HAVE_SANITIZER_SCAN_KEEP + + // We can't use a "else if" there, because some of the following + // matching rules overlap with those in the if-statement above. if (!strcmp(cur_argv, "-fsanitize=fuzzer")) { if (scan) { @@ -1751,44 +1835,27 @@ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { } - } else if ((!strncmp(cur_argv, "-fsanitize=fuzzer-", + } else if (!strncmp(cur_argv, "-fsanitize-coverage-", 20) && - strlen("-fsanitize=fuzzer-")) || - !strncmp(cur_argv, "-fsanitize-coverage", - strlen("-fsanitize-coverage"))) && - (strncmp(cur_argv, "sanitize-coverage-allow", - strlen("sanitize-coverage-allow")) && - strncmp(cur_argv, "sanitize-coverage-deny", - strlen("sanitize-coverage-deny")) && - aflcc->instrument_mode != INSTRUMENT_LLVMNATIVE)) { + strstr(cur_argv, "list=")) { if (scan) { + aflcc->have_instr_list = 1; final_ = PARAM_SCAN; } else { - if (!be_quiet) { WARNF("Found '%s' - stripping!", cur_argv); } - final_ = PARAM_DROP; - - } + if (aflcc->instrument_mode != INSTRUMENT_LLVMNATIVE) { - } - - if (!strcmp(cur_argv, "-fsanitize=address") || - !strcmp(cur_argv, "-fsanitize=memory")) { - - if (scan) { + if (!be_quiet) { WARNF("Found '%s' - stripping!", cur_argv); } + final_ = PARAM_DROP; - // "-fsanitize=undefined,address" may be un-treated, but it's OK. - aflcc->asan_set = 1; - final_ = PARAM_SCAN; + } else { - } else { + final_ = PARAM_KEEP; - // It's impossible that final_ is PARAM_DROP before, - // so no checks are needed here. - final_ = PARAM_KEEP; + } } @@ -1800,76 +1867,125 @@ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { } +/* + Add params for sanitizers. Here we need to consider: + - Use static runtime for asan, as much as possible. + - ASAN, MSAN, AFL_HARDEN are mutually exclusive. + - Add options if not found there, on request of AFL_USE_ASAN, AFL_USE_MSAN, + etc. + - Update have_* so that functions called after this can have correct context. + However this also means any functions called before should NOT depend on + these have_*, otherwise they may not work as expected. +*/ void add_sanitizers(aflcc_state_t *aflcc, char **envp) { - if (!aflcc->asan_set) { + if (getenv("AFL_USE_ASAN") || aflcc->have_asan) { + + if (getenv("AFL_USE_MSAN") || aflcc->have_msan) + FATAL("ASAN and MSAN are mutually exclusive"); - if (getenv("AFL_USE_ASAN")) { + if (getenv("AFL_HARDEN")) + FATAL("ASAN and AFL_HARDEN are mutually exclusive"); - if (getenv("AFL_USE_MSAN")) FATAL("ASAN and MSAN are mutually exclusive"); + if (aflcc->compiler_mode == GCC_PLUGIN && !aflcc->have_staticasan) { - if (getenv("AFL_HARDEN")) - FATAL("ASAN and AFL_HARDEN are mutually exclusive"); + insert_param(aflcc, "-static-libasan"); - add_defs_fortify(aflcc, 0); - insert_param(aflcc, "-fsanitize=address"); + } - } else if (getenv("AFL_USE_MSAN")) { + add_defs_fortify(aflcc, 0); + if (!aflcc->have_asan) { insert_param(aflcc, "-fsanitize=address"); } + aflcc->have_asan = 1; - if (getenv("AFL_USE_ASAN")) FATAL("ASAN and MSAN are mutually exclusive"); + } else if (getenv("AFL_USE_MSAN") || aflcc->have_msan) { - if (getenv("AFL_HARDEN")) - FATAL("MSAN and AFL_HARDEN are mutually exclusive"); + if (getenv("AFL_USE_ASAN") || aflcc->have_asan) + FATAL("ASAN and MSAN are mutually exclusive"); - add_defs_fortify(aflcc, 0); - insert_param(aflcc, "-fsanitize=memory"); + if (getenv("AFL_HARDEN")) + FATAL("MSAN and AFL_HARDEN are mutually exclusive"); - } + add_defs_fortify(aflcc, 0); + if (!aflcc->have_msan) { insert_param(aflcc, "-fsanitize=memory"); } + aflcc->have_msan = 1; } - if (getenv("AFL_USE_UBSAN")) { + if (getenv("AFL_USE_UBSAN") || aflcc->have_ubsan) { + + if (!aflcc->have_ubsan) { + + insert_param(aflcc, "-fsanitize=undefined"); + insert_param(aflcc, "-fsanitize-undefined-trap-on-error"); + insert_param(aflcc, "-fno-sanitize-recover=all"); + + } + + if (!aflcc->have_fp) { - insert_param(aflcc, "-fsanitize=undefined"); - insert_param(aflcc, "-fsanitize-undefined-trap-on-error"); - insert_param(aflcc, "-fno-sanitize-recover=all"); - insert_param(aflcc, "-fno-omit-frame-pointer"); + insert_param(aflcc, "-fno-omit-frame-pointer"); + aflcc->have_fp = 1; + + } + + aflcc->have_ubsan = 1; } - if (getenv("AFL_USE_TSAN")) { + if (getenv("AFL_USE_TSAN") || aflcc->have_tsan) { + + if (!aflcc->have_fp) { + + insert_param(aflcc, "-fno-omit-frame-pointer"); + aflcc->have_fp = 1; + + } - insert_param(aflcc, "-fsanitize=thread"); - insert_param(aflcc, "-fno-omit-frame-pointer"); + if (!aflcc->have_tsan) { insert_param(aflcc, "-fsanitize=thread"); } + aflcc->have_tsan = 1; } - if (getenv("AFL_USE_LSAN")) { + if (getenv("AFL_USE_LSAN") && !aflcc->have_lsan) { insert_param(aflcc, "-fsanitize=leak"); add_defs_lsan_ctrl(aflcc); + aflcc->have_lsan = 1; } - if (getenv("AFL_USE_CFISAN")) { + if (getenv("AFL_USE_CFISAN") || aflcc->have_cfisan) { if (aflcc->compiler_mode == GCC_PLUGIN || aflcc->compiler_mode == GCC) { - insert_param(aflcc, "-fcf-protection=full"); + if (!aflcc->have_fcf) { insert_param(aflcc, "-fcf-protection=full"); } } else { - if (!aflcc->lto_mode) { + if (!aflcc->lto_mode && !aflcc->have_flto) { uint32_t i = 0, found = 0; - while (envp[i] != NULL && !found) + while (envp[i] != NULL && !found) { + if (strncmp("-flto", envp[i++], 5) == 0) found = 1; - if (!found) insert_param(aflcc, "-flto"); + + } + + if (!found) { insert_param(aflcc, "-flto"); } + aflcc->have_flto = 1; } - insert_param(aflcc, "-fsanitize=cfi"); - insert_param(aflcc, "-fvisibility=hidden"); + if (!aflcc->have_cfisan) { insert_param(aflcc, "-fsanitize=cfi"); } + + if (!aflcc->have_hidden) { + + insert_param(aflcc, "-fvisibility=hidden"); + aflcc->have_hidden = 1; + + } + + aflcc->have_cfisan = 1; } @@ -1877,42 +1993,48 @@ void add_sanitizers(aflcc_state_t *aflcc, char **envp) { } +/* Add params to enable LLVM SanCov, the native PCGUARD */ void add_native_pcguard(aflcc_state_t *aflcc) { + /* If there is a rust ASan runtime on the command line, it is likely we're + * linking from rust and adding native flags requiring the sanitizer runtime + * will trigger native clang to add yet another runtime, causing linker + * errors. For now we shouldn't add instrumentation here, we're linking + * anyway. + */ + if (aflcc->have_rust_asanrt) { return; } + /* If llvm-config doesn't figure out LLVM_MAJOR, just go on anyway and let compiler complain if doesn't work. */ - if (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CODECOV) { - #if LLVM_MAJOR > 0 && LLVM_MAJOR < 6 - FATAL("pcguard instrumentation with pc-table requires LLVM 6.0.1+"); + FATAL("pcguard instrumentation with pc-table requires LLVM 6.0.1+"); #else #if LLVM_MAJOR == 0 - WARNF( - "pcguard instrumentation with pc-table requires LLVM 6.0.1+" - " otherwise the compiler will fail"); + WARNF( + "pcguard instrumentation with pc-table requires LLVM 6.0.1+" + " otherwise the compiler will fail"); #endif + if (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CODECOV) { + insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table"); -#endif } else { -#if LLVM_MAJOR > 0 && LLVM_MAJOR < 4 - FATAL("pcguard instrumentation requires LLVM 4.0.1+"); -#else - #if LLVM_MAJOR == 0 - WARNF( - "pcguard instrumentation requires LLVM 4.0.1+" - " otherwise the compiler will fail"); - #endif - insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); -#endif + insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard,pc-table"); } +#endif + } +/* + Add params to launch our optimized PCGUARD on request. + It will fallback to use the native PCGUARD in some cases. If so, plz + bear in mind that instrument_mode will be set to INSTRUMENT_LLVMNATIVE. +*/ void add_optimized_pcguard(aflcc_state_t *aflcc) { #if LLVM_MAJOR >= 13 @@ -1929,7 +2051,7 @@ void add_optimized_pcguard(aflcc_state_t *aflcc) { SAYF( "Using unoptimized trace-pc-guard, due usage of " "-fsanitize-coverage-allow/denylist, you can use " - "AFL_LLVM_ALLOWLIST/AFL_LLMV_DENYLIST instead.\n"); + "AFL_LLVM_ALLOWLIST/AFL_LLVM_DENYLIST instead.\n"); insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; @@ -1964,8 +2086,14 @@ void add_optimized_pcguard(aflcc_state_t *aflcc) { } -/* Linking behaviors */ +/** About -fsanitize -----END----- **/ +/** Linking behaviors -----BEGIN----- **/ + +/* + Parse and process possible linking stage related args, + return PARAM_MISS if nothing matched. +*/ param_st parse_linking_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan, u8 *skip_next, char **argv) { @@ -2128,6 +2256,7 @@ param_st parse_linking_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan, } +/* Add params to specify the linker used in LTO */ void add_lto_linker(aflcc_state_t *aflcc) { unsetenv("AFL_LD"); @@ -2167,6 +2296,7 @@ void add_lto_linker(aflcc_state_t *aflcc) { } +/* Add params to launch SanitizerCoverageLTO.so when linking */ void add_lto_passes(aflcc_state_t *aflcc) { #if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 15 @@ -2185,6 +2315,7 @@ void add_lto_passes(aflcc_state_t *aflcc) { } +/* Add params to link with libAFLDriver.a on request */ static void add_aflpplib(aflcc_state_t *aflcc) { if (!aflcc->need_aflpplib) return; @@ -2220,6 +2351,7 @@ static void add_aflpplib(aflcc_state_t *aflcc) { } +/* Add params to link with runtimes depended by our instrumentation */ void add_runtime(aflcc_state_t *aflcc) { if (aflcc->preprocessor_only || aflcc->have_c || !aflcc->non_dash) { @@ -2281,6 +2413,11 @@ void add_runtime(aflcc_state_t *aflcc) { } + #if __AFL_CODE_COVERAGE + // Required for dladdr used in afl-compiler-rt.o + insert_param(aflcc, "-ldl"); + #endif + #if !defined(__APPLE__) && !defined(__sun) if (!aflcc->shared_linking && !aflcc->partial_linking) insert_object(aflcc, "dynamic_list.txt", "-Wl,--dynamic-list=%s", 0); @@ -2310,8 +2447,14 @@ void add_runtime(aflcc_state_t *aflcc) { } -/* Misc */ +/** Linking behaviors -----END----- **/ +/** Miscellaneous routines -----BEGIN----- **/ + +/* + Add params to make compiler driver use our afl-as + as assembler, required by the vanilla instrumentation. +*/ void add_assembler(aflcc_state_t *aflcc) { u8 *afl_as = find_object(aflcc, "as"); @@ -2328,6 +2471,7 @@ void add_assembler(aflcc_state_t *aflcc) { } +/* Add params to launch the gcc plugins for instrumentation. */ void add_gcc_plugin(aflcc_state_t *aflcc) { if (aflcc->cmplog_mode) { @@ -2344,6 +2488,7 @@ void add_gcc_plugin(aflcc_state_t *aflcc) { } +/* Add some miscellaneous params required by our instrumentation. */ void add_misc_params(aflcc_state_t *aflcc) { if (getenv("AFL_NO_BUILTIN") || getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES") || @@ -2390,6 +2535,10 @@ void add_misc_params(aflcc_state_t *aflcc) { } +/* + Parse and process a variety of args under our matching rules, + return PARAM_MISS if nothing matched. +*/ param_st parse_misc_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { param_st final_ = PARAM_MISS; @@ -2447,6 +2596,36 @@ param_st parse_misc_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { SCAN_KEEP(aflcc->have_c, 1); + } else if (!strcmp(cur_argv, "-static-libasan")) { + + SCAN_KEEP(aflcc->have_staticasan, 1); + + } else if (strstr(cur_argv, "librustc") && strstr(cur_argv, "_rt.asan.a")) { + + SCAN_KEEP(aflcc->have_rust_asanrt, 1); + + } else if (!strcmp(cur_argv, "-fno-omit-frame-pointer")) { + + SCAN_KEEP(aflcc->have_fp, 1); + + } else if (!strcmp(cur_argv, "-fvisibility=hidden")) { + + SCAN_KEEP(aflcc->have_hidden, 1); + + } else if (!strcmp(cur_argv, "-flto") || !strcmp(cur_argv, "-flto=full")) { + + SCAN_KEEP(aflcc->have_flto, 1); + + } else if (!strncmp(cur_argv, "-D_FORTIFY_SOURCE", + + strlen("-D_FORTIFY_SOURCE"))) { + + SCAN_KEEP(aflcc->have_fortify, 1); + + } else if (!strncmp(cur_argv, "-fcf-protection", strlen("-fcf-protection"))) { + + SCAN_KEEP(aflcc->have_cfisan, 1); + } else if (!strncmp(cur_argv, "-O", 2)) { SCAN_KEEP(aflcc->have_o, 1); @@ -2510,6 +2689,9 @@ param_st parse_misc_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { } +/** Miscellaneous routines -----END----- **/ + +/* Print help message on request */ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { if (argc < 2 || strncmp(argv[1], "-h", 2) == 0) { @@ -2538,11 +2720,11 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { "MODES: NCC PERSIST DICT LAF " "CMPLOG SELECT\n" " [LLVM] LLVM: %s%s\n" - " PCGUARD %s yes yes module yes yes " + " PCGUARD %s yes yes module yes yes " "yes\n" - " NATIVE AVAILABLE no yes no no " + " NATIVE AVAILABLE no yes no no " "part. yes\n" - " CLASSIC %s no yes module yes yes " + " CLASSIC %s no yes module yes yes " "yes\n" " - NORMAL\n" " - CALLER\n" @@ -2805,11 +2987,27 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { } +/* + Process params passed to afl-cc. + + We have two working modes, *scan* and *non-scan*. In scan mode, + the main task is to set some variables in aflcc according to current argv[i], + while in non-scan mode, is to choose keep or drop current argv[i]. + + We have several matching routines being called sequentially in the while-loop, + and each of them try to parse and match current argv[i] according to their own + rules. If one miss match, the next will then take over. In non-scan mode, each + argv[i] mis-matched by all the routines will be kept. + + These routines are: + 1. parse_misc_params + 2. parse_fsanitize + 3. parse_linking_params + 4. `if (*cur == '@') {...}`, i.e., parse response files +*/ static void process_params(aflcc_state_t *aflcc, u8 scan, u32 argc, char **argv) { - limit_params(aflcc, argc); - // for (u32 x = 0; x < argc; ++x) fprintf(stderr, "[%u] %s\n", x, argv[x]); /* Process the argument list. */ @@ -2833,134 +3031,249 @@ static void process_params(aflcc_state_t *aflcc, u8 scan, u32 argc, if (PARAM_MISS != parse_linking_params(aflcc, cur, scan, &skip_next, argv)) continue; + /* Response file support -----BEGIN----- + We have two choices - move everything to the command line or + rewrite the response files to temporary files and delete them + afterwards. We choose the first for easiness. + For clang, llvm::cl::ExpandResponseFiles does this, however it + only has C++ interface. And for gcc there is expandargv in libiberty, + written in C, but we can't simply copy-paste since its LGPL licensed. + So here we use an equivalent FSM as alternative, and try to be compatible + with the two above. See: + - https://gcc.gnu.org/onlinedocs/gcc/Overall-Options.html + - driver::expand_at_files in gcc.git/gcc/gcc.c + - expandargv in gcc.git/libiberty/argv.c + - llvm-project.git/clang/tools/driver/driver.cpp + - ExpandResponseFiles in + llvm-project.git/llvm/lib/Support/CommandLine.cpp + */ if (*cur == '@') { - // response file support. - // we have two choices - move everything to the command line or - // rewrite the response files to temporary files and delete them - // afterwards. We choose the first for easiness. - // We do *not* support quotes in the rsp files to cope with spaces in - // filenames etc! If you need that then send a patch! u8 *filename = cur + 1; if (aflcc->debug) { DEBUGF("response file=%s\n", filename); } - FILE *f = fopen(filename, "r"); - struct stat st; // Check not found or empty? let the compiler complain if so. - if (!f || fstat(fileno(f), &st) < 0 || st.st_size < 1) { + FILE *f = fopen(filename, "r"); + if (!f) { if (!scan) insert_param(aflcc, cur); continue; } - u8 *tmpbuf = malloc(st.st_size + 2), *ptr; - char **args = malloc(sizeof(char *) * (st.st_size >> 1)); - int count = 1, cont = 0, cont_act = 0; + struct stat st; + if (fstat(fileno(f), &st) || !S_ISREG(st.st_mode) || st.st_size < 1) { - while (fgets(tmpbuf, st.st_size + 1, f)) { + fclose(f); + if (!scan) insert_param(aflcc, cur); + continue; - ptr = tmpbuf; - // fprintf(stderr, "1: %s\n", ptr); - // no leading whitespace - while (isspace(*ptr)) { + } - ++ptr; - cont_act = 0; + // Limit the number of response files, the max value + // just keep consistent with expandargv. Only do this in + // scan mode, and not touch rsp_count anymore in the next. + static u32 rsp_count = 2000; + if (scan) { - } + if (rsp_count == 0) FATAL("Too many response files provided!"); - // no comments, no empty lines - if (*ptr == '#' || *ptr == '\n' || !*ptr) { continue; } - // remove LF - if (ptr[strlen(ptr) - 1] == '\n') { ptr[strlen(ptr) - 1] = 0; } - // remove CR - if (*ptr && ptr[strlen(ptr) - 1] == '\r') { ptr[strlen(ptr) - 1] = 0; } - // handle \ at end of line - if (*ptr && ptr[strlen(ptr) - 1] == '\\') { + --rsp_count; - cont = 1; - ptr[strlen(ptr) - 1] = 0; + } - } + // argc, argv acquired from this rsp file. Note that + // process_params ignores argv[0], we need to put a const "" here. + u32 argc_read = 1; + char **argv_read = ck_alloc(sizeof(char *)); + argv_read[0] = ""; + + char *arg_buf = NULL; + u64 arg_len = 0; + + enum fsm_state { + + fsm_whitespace, // whitespace seen so far + fsm_double_quote, // have unpaired double quote + fsm_single_quote, // have unpaired single quote + fsm_backslash, // a backslash is seen with no unpaired quote + fsm_normal // a normal char is seen + + }; + + // Workaround to append c to arg buffer, and append the buffer to argv +#define ARG_ALLOC(c) \ + do { \ + \ + ++arg_len; \ + arg_buf = ck_realloc(arg_buf, (arg_len + 1) * sizeof(char)); \ + arg_buf[arg_len] = '\0'; \ + arg_buf[arg_len - 1] = (char)c; \ + \ + } while (0) + +#define ARG_STORE() \ + do { \ + \ + ++argc_read; \ + argv_read = ck_realloc(argv_read, argc_read * sizeof(char *)); \ + argv_read[argc_read - 1] = arg_buf; \ + arg_buf = NULL; \ + arg_len = 0; \ + \ + } while (0) - // fprintf(stderr, "2: %s\n", ptr); + int cur_chr = (int)' '; // init as whitespace, as a good start :) + enum fsm_state state_ = fsm_whitespace; - // remove whitespace at end - while (*ptr && isspace(ptr[strlen(ptr) - 1])) { + while (cur_chr != EOF) { - ptr[strlen(ptr) - 1] = 0; - cont = 0; + switch (state_) { - } + case fsm_whitespace: - // fprintf(stderr, "3: %s\n", ptr); - if (*ptr) { + if (arg_buf) { + + ARG_STORE(); + break; + + } - do { + if (isspace(cur_chr)) { - u8 *value = ptr; - while (*ptr && !isspace(*ptr)) { + cur_chr = fgetc(f); - ++ptr; + } else if (cur_chr == (int)'\'') { + + state_ = fsm_single_quote; + cur_chr = fgetc(f); + + } else if (cur_chr == (int)'"') { + + state_ = fsm_double_quote; + cur_chr = fgetc(f); + + } else if (cur_chr == (int)'\\') { + + state_ = fsm_backslash; + cur_chr = fgetc(f); + + } else { + + state_ = fsm_normal; } - while (*ptr && isspace(*ptr)) { + break; + + case fsm_normal: + + if (isspace(cur_chr)) { + + state_ = fsm_whitespace; + + } else if (cur_chr == (int)'\'') { + + state_ = fsm_single_quote; + cur_chr = fgetc(f); + + } else if (cur_chr == (int)'\"') { - *ptr++ = 0; + state_ = fsm_double_quote; + cur_chr = fgetc(f); + + } else if (cur_chr == (int)'\\') { + + state_ = fsm_backslash; + cur_chr = fgetc(f); + + } else { + + ARG_ALLOC(cur_chr); + cur_chr = fgetc(f); } - if (cont_act) { + break; + + case fsm_backslash: + + ARG_ALLOC(cur_chr); + cur_chr = fgetc(f); + state_ = fsm_normal; - u32 len = strlen(args[count - 1]) + strlen(value) + 1; - u8 *tmp = malloc(len); - snprintf(tmp, len, "%s%s", args[count - 1], value); - free(args[count - 1]); - args[count - 1] = tmp; - cont_act = 0; + break; + + case fsm_single_quote: + + if (cur_chr == (int)'\\') { + + cur_chr = fgetc(f); + if (cur_chr == EOF) break; + ARG_ALLOC(cur_chr); + + } else if (cur_chr == (int)'\'') { + + state_ = fsm_normal; } else { - args[count++] = strdup(value); + ARG_ALLOC(cur_chr); } - } while (*ptr); + cur_chr = fgetc(f); + break; - } + case fsm_double_quote: + + if (cur_chr == (int)'\\') { - if (cont) { + cur_chr = fgetc(f); + if (cur_chr == EOF) break; + ARG_ALLOC(cur_chr); - cont_act = 1; - cont = 0; + } else if (cur_chr == (int)'"') { + + state_ = fsm_normal; + + } else { + + ARG_ALLOC(cur_chr); + + } + + cur_chr = fgetc(f); + break; + + default: + break; } } - if (count) { process_params(aflcc, scan, count, args); } + if (arg_buf) { ARG_STORE(); } // save the pending arg after EOF - // we cannot free args[] unless we don't need - // to keep any reference in cc_params - if (scan) { +#undef ARG_ALLOC +#undef ARG_STORE - if (count) do { + if (argc_read > 1) { process_params(aflcc, scan, argc_read, argv_read); } - free(args[--count]); + // We cannot free argv_read[] unless we don't need to keep any + // reference in cc_params. Never free argv[0], the const "". + if (scan) { - } while (count); + while (argc_read > 1) + ck_free(argv_read[--argc_read]); - free(args); + ck_free(argv_read); } - free(tmpbuf); - continue; - } + } /* Response file support -----END----- */ if (!scan) insert_param(aflcc, cur); @@ -2968,8 +3281,7 @@ static void process_params(aflcc_state_t *aflcc, u8 scan, u32 argc, } -/* Copy argv to cc_params, making the necessary edits. */ - +/* Process each of the existing argv, also add a few new args. */ static void edit_params(aflcc_state_t *aflcc, u32 argc, char **argv, char **envp) { @@ -3110,7 +3422,6 @@ static void edit_params(aflcc_state_t *aflcc, u32 argc, char **argv, } /* Main entry point */ - int main(int argc, char **argv, char **envp) { aflcc_state_t *aflcc = malloc(sizeof(aflcc_state_t)); diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 3f9bfa72..214b4fe9 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -1017,6 +1017,12 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if (rlen == 4) { + if (status >= 0x41464c00 && status <= 0x41464cff) { + + FATAL("Target uses the new forkserver model, you need to switch to a newer afl-fuzz too!"); + + } + if (!be_quiet) { OKF("All right - fork server is up."); } if (getenv("AFL_DEBUG")) { diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 35932913..8ab44a3b 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -124,6 +124,9 @@ void bind_to_free_cpu(afl_state_t *afl) { } WARNF("Not binding to a CPU core (AFL_NO_AFFINITY set)."); + #ifdef __linux__ + if (afl->fsrv.nyx_mode) { afl->fsrv.nyx_bind_cpu_id = 0; } + #endif return; } @@ -151,6 +154,9 @@ void bind_to_free_cpu(afl_state_t *afl) { } else { OKF("CPU binding request using -b %d successful.", afl->cpu_to_bind); + #ifdef __linux__ + if (afl->fsrv.nyx_mode) { afl->fsrv.nyx_bind_cpu_id = afl->cpu_to_bind; } + #endif } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 2d5787e8..8cf6c735 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -165,7 +165,7 @@ static void usage(u8 *argv0, int more_help) { "\n" "Mutator settings:\n" - " -a - target input format, \"text\" or \"binary\" (default: " + " -a type - target input format, \"text\" or \"binary\" (default: " "generic)\n" " -g minlength - set min length of generated fuzz input (default: 1)\n" " -G maxlength - set max length of generated fuzz input (default: " @@ -1915,6 +1915,15 @@ int main(int argc, char **argv_orig, char **envp) { bind_to_free_cpu(afl); #endif /* HAVE_AFFINITY */ + #ifdef __linux__ + if (afl->fsrv.nyx_mode && afl->fsrv.nyx_bind_cpu_id == 0xFFFFFFFF) { + + afl->fsrv.nyx_bind_cpu_id = 0; + + } + + #endif + #ifdef __HAIKU__ /* Prioritizes performance over power saving */ set_scheduler_mode(SCHEDULER_MODE_LOW_LATENCY); -- cgit v1.2.3 From 06f0982f0f4506e18872efb86b97993f2518988c Mon Sep 17 00:00:00 2001 From: Han Zheng <35988108+kdsjZh@users.noreply.github.com> Date: Thu, 1 Feb 2024 15:13:21 +0100 Subject: Enhancement on Deterministic stage (#1972) * fuzzer: init commit based on aflpp 60dc37a8cf09f8e9048e4b6a2204d6c90b27655a * fuzzers: adding the skip variables and initialize * log: profile the det/havoc finding * log: add profile log output * fuzzers: sperate log/skipdet module * fuzzers: add quick eff_map calc * fuzzers: add skip_eff_map in fuzz_one * fuzzers: mark whole input space in eff_map * fuzzers: add undet bit threshold to skip some seeds * fuzzers: fix one byte overflow * fuzzers: fix overflow * fix code format * add havoc only again * code format * remove log to INTROSPECTION, rename skipdet module * rename skipdet module * remove log to stats * clean redundant code * code format * remove redundant code format check * remove redundant doc * remove redundant objects * clean files * change -d to default skipdet * disable deterministic when using CUSTOM_MUTATOR * revert fix --- src/afl-fuzz-init.c | 15 ++ src/afl-fuzz-one.c | 166 ++++++++++++++------ src/afl-fuzz-queue.c | 11 ++ src/afl-fuzz-skipdet.c | 403 +++++++++++++++++++++++++++++++++++++++++++++++++ src/afl-fuzz-state.c | 10 +- src/afl-fuzz-stats.c | 38 +++++ src/afl-fuzz.c | 13 +- 7 files changed, 608 insertions(+), 48 deletions(-) create mode 100644 src/afl-fuzz-skipdet.c (limited to 'src') diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 8ab44a3b..057d8cf5 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -2236,6 +2236,21 @@ void setup_dirs_fds(afl_state_t *afl) { fflush(afl->fsrv.plot_file); +#ifdef INTROSPECTION + + tmp = alloc_printf("%s/plot_det_data", afl->out_dir); + + int fd = open(tmp, O_WRONLY | O_CREAT, DEFAULT_PERMISSION); + if (fd < 0) { PFATAL("Unable to create '%s'", tmp); } + ck_free(tmp); + + afl->fsrv.det_plot_file = fdopen(fd, "w"); + if (!afl->fsrv.det_plot_file) { PFATAL("fdopen() failed"); } + + if (afl->in_place_resume) { fseek(afl->fsrv.det_plot_file, 0, SEEK_END); } + +#endif + /* ignore errors */ } diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 01e34b69..4a7d3fad 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -545,12 +545,37 @@ u8 fuzz_one_original(afl_state_t *afl) { } + u64 before_det_time = get_cur_time(); +#ifdef INTROSPECTION + + u64 before_havoc_time; + u32 before_det_findings = afl->queued_items, + before_det_edges = count_non_255_bytes(afl, afl->virgin_bits), + before_havoc_findings, before_havoc_edges; + u8 is_logged = 0; + +#endif + if (!afl->skip_deterministic) { + + if (!skip_deterministic_stage(afl, in_buf, out_buf, len, before_det_time)) { + + goto abandon_entry; + + } + + } + + u8 *skip_eff_map = afl->queue_cur->skipdet_e->skip_eff_map; + /* Skip right away if -d is given, if it has not been chosen sufficiently often to warrant the expensive deterministic stage (fuzz_level), or if it has gone through deterministic testing in earlier, resumed runs (passed_det). */ + /* if skipdet decide to skip the seed or no interesting bytes found, + we skip the whole deterministic stage as well */ if (likely(afl->skip_deterministic) || likely(afl->queue_cur->passed_det) || + likely(!afl->queue_cur->skipdet_e->quick_eff_bytes) || likely(perf_score < (afl->queue_cur->depth * 30 <= afl->havoc_max_mult * 100 ? afl->queue_cur->depth * 30 @@ -609,6 +634,10 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->stage_cur_byte = afl->stage_cur >> 3; + if (!skip_eff_map[afl->stage_cur_byte]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + FLIP_BIT(out_buf, afl->stage_cur); #ifdef INTROSPECTION @@ -725,6 +754,10 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->stage_cur_byte = afl->stage_cur >> 3; + if (!skip_eff_map[afl->stage_cur_byte]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + FLIP_BIT(out_buf, afl->stage_cur); FLIP_BIT(out_buf, afl->stage_cur + 1); @@ -760,6 +793,10 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->stage_cur_byte = afl->stage_cur >> 3; + if (!skip_eff_map[afl->stage_cur_byte]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + FLIP_BIT(out_buf, afl->stage_cur); FLIP_BIT(out_buf, afl->stage_cur + 1); FLIP_BIT(out_buf, afl->stage_cur + 2); @@ -828,6 +865,10 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->stage_cur_byte = afl->stage_cur; + if (!skip_eff_map[afl->stage_cur_byte]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + out_buf[afl->stage_cur] ^= 0xFF; #ifdef INTROSPECTION @@ -837,37 +878,6 @@ u8 fuzz_one_original(afl_state_t *afl) { if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } - /* We also use this stage to pull off a simple trick: we identify - bytes that seem to have no effect on the current execution path - even when fully flipped - and we skip them during more expensive - deterministic stages, such as arithmetics or known ints. */ - - if (!eff_map[EFF_APOS(afl->stage_cur)]) { - - u64 cksum; - - /* If in non-instrumented mode or if the file is very short, just flag - everything without wasting time on checksums. */ - - if (!afl->non_instrumented_mode && len >= EFF_MIN_LEN) { - - cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); - - } else { - - cksum = ~prev_cksum; - - } - - if (cksum != prev_cksum) { - - eff_map[EFF_APOS(afl->stage_cur)] = 1; - ++eff_cnt; - - } - - } - out_buf[afl->stage_cur] ^= 0xFF; } @@ -876,18 +886,8 @@ u8 fuzz_one_original(afl_state_t *afl) { whole thing as worth fuzzing, since we wouldn't be saving much time anyway. */ - if (eff_cnt != (u32)EFF_ALEN(len) && - eff_cnt * 100 / EFF_ALEN(len) > EFF_MAX_PERC) { - - memset(eff_map, 1, EFF_ALEN(len)); - - afl->blocks_eff_select += EFF_ALEN(len); - - } else { - - afl->blocks_eff_select += eff_cnt; - - } + memset(eff_map, 1, EFF_ALEN(len)); + afl->blocks_eff_select += EFF_ALEN(len); afl->blocks_eff_total += EFF_ALEN(len); @@ -921,6 +921,10 @@ u8 fuzz_one_original(afl_state_t *afl) { } + if (!skip_eff_map[i]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + afl->stage_cur_byte = i; *(u16 *)(out_buf + i) ^= 0xFFFF; @@ -967,6 +971,10 @@ u8 fuzz_one_original(afl_state_t *afl) { } + if (!skip_eff_map[i]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + afl->stage_cur_byte = i; *(u32 *)(out_buf + i) ^= 0xFFFFFFFF; @@ -1023,6 +1031,10 @@ skip_bitflip: } + if (!skip_eff_map[i]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + afl->stage_cur_byte = i; for (j = 1; j <= ARITH_MAX; ++j) { @@ -1110,6 +1122,10 @@ skip_bitflip: } + if (!skip_eff_map[i]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + afl->stage_cur_byte = i; for (j = 1; j <= ARITH_MAX; ++j) { @@ -1244,6 +1260,10 @@ skip_bitflip: } + if (!skip_eff_map[i]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + afl->stage_cur_byte = i; for (j = 1; j <= ARITH_MAX; ++j) { @@ -1381,6 +1401,10 @@ skip_arith: } + if (!skip_eff_map[i]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + afl->stage_cur_byte = i; for (j = 0; j < (u32)sizeof(interesting_8); ++j) { @@ -1444,6 +1468,10 @@ skip_arith: } + if (!skip_eff_map[i]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + afl->stage_cur_byte = i; for (j = 0; j < sizeof(interesting_16) / 2; ++j) { @@ -1536,6 +1564,10 @@ skip_arith: } + if (!skip_eff_map[i]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + afl->stage_cur_byte = i; for (j = 0; j < sizeof(interesting_32) / 4; ++j) { @@ -1626,6 +1658,10 @@ skip_interest: u32 last_len = 0; + if (!skip_eff_map[i]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + afl->stage_cur_byte = i; /* Extras are sorted by size, from smallest to largest. This means @@ -1693,6 +1729,10 @@ skip_interest: for (i = 0; i <= (u32)len; ++i) { + if (!skip_eff_map[i % len]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + afl->stage_cur_byte = i; for (j = 0; j < afl->extras_cnt; ++j) { @@ -1755,6 +1795,10 @@ skip_user_extras: u32 last_len = 0; + if (!skip_eff_map[i]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + afl->stage_cur_byte = i; u32 min_extra_len = MIN(afl->a_extras_cnt, (u32)USE_AUTO_EXTRAS); @@ -1813,6 +1857,10 @@ skip_user_extras: for (i = 0; i <= (u32)len; ++i) { + if (!skip_eff_map[i % len]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + afl->stage_cur_byte = i; for (j = 0; j < afl->a_extras_cnt; ++j) { @@ -2020,6 +2068,19 @@ custom_mutator_stage: havoc_stage: +#ifdef INTROSPECTION + + if (!is_logged) { + + is_logged = 1; + before_havoc_findings = afl->queued_items; + before_havoc_edges = count_non_255_bytes(afl, afl->virgin_bits); + before_havoc_time = get_cur_time(); + + } + +#endif + if (unlikely(afl->custom_only)) { /* Force UI update */ @@ -3430,6 +3491,25 @@ retry_splicing: ret_val = 0; +#ifdef INTROSPECTION + + afl->havoc_prof->queued_det_stage = + before_havoc_findings - before_det_findings; + afl->havoc_prof->queued_havoc_stage = + afl->queued_items - before_havoc_findings; + afl->havoc_prof->total_queued_det += afl->havoc_prof->queued_det_stage; + afl->havoc_prof->edge_det_stage = before_havoc_edges - before_det_edges; + afl->havoc_prof->edge_havoc_stage = + count_non_255_bytes(afl, afl->virgin_bits) - before_havoc_edges; + afl->havoc_prof->total_det_edge += afl->havoc_prof->edge_det_stage; + afl->havoc_prof->det_stage_time = before_havoc_time - before_det_time; + afl->havoc_prof->havoc_stage_time = get_cur_time() - before_havoc_time; + afl->havoc_prof->total_det_time += afl->havoc_prof->det_stage_time; + + plot_profile_data(afl, afl->queue_cur); + +#endif + /* we are through with this queue entry - for this iteration */ abandon_entry: diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 4b9627f7..67931bba 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -664,6 +664,8 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { } + q->skipdet_e = (struct skipdet_entry *)ck_alloc(sizeof(struct skipdet_entry)); + } /* Destroy the entire queue. */ @@ -679,6 +681,15 @@ void destroy_queue(afl_state_t *afl) { q = afl->queue_buf[i]; ck_free(q->fname); ck_free(q->trace_mini); + if (q->skipdet_e) { + + if (q->skipdet_e->done_inf_map) ck_free(q->skipdet_e->done_inf_map); + if (q->skipdet_e->skip_eff_map) ck_free(q->skipdet_e->skip_eff_map); + + ck_free(q->skipdet_e); + + } + ck_free(q); } diff --git a/src/afl-fuzz-skipdet.c b/src/afl-fuzz-skipdet.c new file mode 100644 index 00000000..e52d59a3 --- /dev/null +++ b/src/afl-fuzz-skipdet.c @@ -0,0 +1,403 @@ + + +#include "afl-fuzz.h" + +void flip_range(u8 *input, u32 pos, u32 size) { + + for (u32 i = 0; i < size; i++) + input[pos + i] ^= 0xFF; + + return; + +} + +#define MAX_EFF_TIMEOUT (10 * 60 * 1000) +#define MAX_DET_TIMEOUT (15 * 60 * 1000) +u8 is_det_timeout(u64 cur_ms, u8 is_flip) { + + if (is_flip) { + + if (unlikely(get_cur_time() - cur_ms > MAX_EFF_TIMEOUT)) return 1; + + } else { + + if (unlikely(get_cur_time() - cur_ms > MAX_DET_TIMEOUT)) return 1; + + } + + return 0; + +} + +/* decide if the seed should be deterministically fuzzed */ + +u8 should_det_fuzz(afl_state_t *afl, struct queue_entry *q) { + + if (!afl->skipdet_g->virgin_det_bits) { + + afl->skipdet_g->virgin_det_bits = + (u8 *)ck_alloc(sizeof(u8) * afl->fsrv.map_size); + + } + + if (!q->favored || q->passed_det) return 0; + if (!q->trace_mini) return 0; + + if (!afl->skipdet_g->last_cov_undet) + afl->skipdet_g->last_cov_undet = get_cur_time(); + + if (get_cur_time() - afl->skipdet_g->last_cov_undet >= THRESHOLD_DEC_TIME) { + + if (afl->skipdet_g->undet_bits_threshold >= 2) { + + afl->skipdet_g->undet_bits_threshold *= 0.75; + afl->skipdet_g->last_cov_undet = get_cur_time(); + + } + + } + + u32 new_det_bits = 0; + + for (u32 i = 0; i < afl->fsrv.map_size; i++) { + + if (unlikely(q->trace_mini[i >> 3] & (1 << (i & 7)))) { + + if (!afl->skipdet_g->virgin_det_bits[i]) { new_det_bits++; } + + } + + } + + if (!afl->skipdet_g->undet_bits_threshold) + afl->skipdet_g->undet_bits_threshold = new_det_bits * 0.05; + + if (new_det_bits >= afl->skipdet_g->undet_bits_threshold) { + + afl->skipdet_g->last_cov_undet = get_cur_time(); + q->skipdet_e->undet_bits = new_det_bits; + + for (u32 i = 0; i < afl->fsrv.map_size; i++) { + + if (unlikely(q->trace_mini[i >> 3] & (1 << (i & 7)))) { + + if (!afl->skipdet_g->virgin_det_bits[i]) + afl->skipdet_g->virgin_det_bits[i] = 1; + + } + + } + + return 1; + + } + + return 0; + +} + +/* + consists of two stages that + return 0 if exec failed. +*/ + +u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf, + u32 len, u64 before_det_time) { + + u64 orig_hit_cnt, new_hit_cnt; + + if (afl->queue_cur->skipdet_e->done_eff) return 1; + + if (!should_det_fuzz(afl, afl->queue_cur)) return 1; + + /* Add check to make sure that for seeds without too much undet bits, + we ignore them */ + + /****************** + * SKIP INFERENCE * + ******************/ + + afl->stage_short = "inf"; + afl->stage_name = "inference"; + afl->stage_cur = 0; + orig_hit_cnt = afl->queued_items + afl->saved_crashes; + + u8 *inf_eff_map = (u8 *)ck_alloc(sizeof(u8) * len); + memset(inf_eff_map, 1, sizeof(u8) * len); + + if (common_fuzz_stuff(afl, orig_buf, len)) { return 0; } + + u64 prev_cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); + u64 _prev_cksum = prev_cksum; + + if (MINIMAL_BLOCK_SIZE * 8 < len) { + + // u64 size_skiped = 0, quick_skip_exec = total_execs, quick_skip_time = + // get_cur_time(); + u64 pre_inf_exec = afl->fsrv.total_execs, pre_inf_time = get_cur_time(); + + /* if determine stage time / input size is too small, just go ahead */ + + u32 pos = 0, cur_block_size = MINIMAL_BLOCK_SIZE, max_block_size = len / 8; + + while (pos < len - 1) { + + cur_block_size = MINIMAL_BLOCK_SIZE; + + while (cur_block_size < max_block_size) { + + u32 flip_block_size = + (cur_block_size + pos < len) ? cur_block_size : len - 1 - pos; + + afl->stage_cur += 1; + + flip_range(out_buf, pos, flip_block_size); + + if (common_fuzz_stuff(afl, out_buf, len)) return 0; + + flip_range(out_buf, pos, flip_block_size); + + u64 cksum = + hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); + + // printf("Now trying range %d with %d, %s.\n", pos, cur_block_size, + // (cksum == prev_cksum) ? (u8*)"Yes" : (u8*) "Not"); + + /* continue until we fail or exceed length */ + if (cksum == _prev_cksum) { + + cur_block_size *= 2; + + if (cur_block_size >= len - 1 - pos) break; + + } else { + + break; + + } + + } + + if (cur_block_size == MINIMAL_BLOCK_SIZE) { + + /* we failed early on*/ + + pos += cur_block_size; + + } else { + + u32 cur_skip_len = (cur_block_size / 2 + pos < len) + ? (cur_block_size / 2) + : (len - pos - 1); + + memset(inf_eff_map + pos, 0, cur_skip_len); + + afl->skipdet_g->inf_prof->inf_skipped_bytes += cur_skip_len; + + pos += cur_skip_len; + + } + + } + + afl->skipdet_g->inf_prof->inf_execs_cost += + (afl->fsrv.total_execs - pre_inf_exec); + afl->skipdet_g->inf_prof->inf_time_cost += (get_cur_time() - pre_inf_time); + // PFATAL("Done, now have %d bytes skipped, with exec %lld, time %lld.\n", + // afl->inf_skipped_bytes, afl->inf_execs_cost, afl->inf_time_cost); + + } else + + memset(inf_eff_map, 1, len); + + new_hit_cnt = afl->queued_items + afl->saved_crashes; + + afl->stage_finds[STAGE_INF] += new_hit_cnt - orig_hit_cnt; + afl->stage_cycles[STAGE_INF] += afl->stage_cur; + + /**************************** + * Quick Skip Effective Map * + ****************************/ + + /* Quick Effective Map Calculation */ + + afl->stage_short = "quick"; + afl->stage_name = "quick eff"; + afl->stage_cur = 0; + afl->stage_max = 32 * 1024; + + orig_hit_cnt = afl->queued_items + afl->saved_crashes; + + u32 before_skip_inf = afl->queued_items; + + /* clean all the eff bytes, since previous eff bytes are already fuzzed */ + u8 *skip_eff_map = afl->queue_cur->skipdet_e->skip_eff_map, + *done_inf_map = afl->queue_cur->skipdet_e->done_inf_map; + + if (!skip_eff_map) { + + skip_eff_map = (u8 *)ck_alloc(sizeof(u8) * len); + afl->queue_cur->skipdet_e->skip_eff_map = skip_eff_map; + + } else { + + memset(skip_eff_map, 0, sizeof(u8) * len); + + } + + /* restore the starting point */ + if (!done_inf_map) { + + done_inf_map = (u8 *)ck_alloc(sizeof(u8) * len); + afl->queue_cur->skipdet_e->done_inf_map = done_inf_map; + + } else { + + for (afl->stage_cur = 0; afl->stage_cur < len; afl->stage_cur++) { + + if (done_inf_map[afl->stage_cur] == 0) break; + + } + + } + + /* depending on the seed's performance, we could search eff bytes + for multiple rounds */ + + u8 eff_round_continue = 1, eff_round_done = 0, done_eff = 0, repeat_eff = 0, + fuzz_nearby = 0, *non_eff_bytes = 0; + + u64 before_eff_execs = afl->fsrv.total_execs; + + if (getenv("REPEAT_EFF")) repeat_eff = 1; + if (getenv("FUZZ_NEARBY")) fuzz_nearby = 1; + + if (fuzz_nearby) { + + non_eff_bytes = (u8 *)ck_alloc(sizeof(u8) * len); + + // clean exec cksum + if (common_fuzz_stuff(afl, out_buf, len)) { return 0; } + prev_cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); + + } + + do { + + eff_round_continue = 0; + afl->stage_max = 32 * 1024; + + for (; afl->stage_cur < afl->stage_max && afl->stage_cur < len; + ++afl->stage_cur) { + + afl->stage_cur_byte = afl->stage_cur; + + if (!inf_eff_map[afl->stage_cur_byte] || + skip_eff_map[afl->stage_cur_byte]) + continue; + + if (is_det_timeout(before_det_time, 1)) { goto cleanup_skipdet; } + + u8 orig = out_buf[afl->stage_cur_byte], replace = rand_below(afl, 256); + + while (replace == orig) { + + replace = rand_below(afl, 256); + + } + + out_buf[afl->stage_cur_byte] = replace; + + before_skip_inf = afl->queued_items; + + if (common_fuzz_stuff(afl, out_buf, len)) { return 0; } + + out_buf[afl->stage_cur_byte] = orig; + + if (fuzz_nearby) { + + if (prev_cksum == + hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST)) { + + non_eff_bytes[afl->stage_cur_byte] = 1; + + } + + } + + if (afl->queued_items != before_skip_inf) { + + skip_eff_map[afl->stage_cur_byte] = 1; + afl->queue_cur->skipdet_e->quick_eff_bytes += 1; + + if (afl->stage_max < MAXIMUM_QUICK_EFF_EXECS) { afl->stage_max *= 2; } + + if (afl->stage_max == MAXIMUM_QUICK_EFF_EXECS && repeat_eff) + eff_round_continue = 1; + + } + + done_inf_map[afl->stage_cur_byte] = 1; + + } + + afl->stage_cur = 0; + done_eff = 1; + + if (++eff_round_done >= 8) break; + + } while (eff_round_continue); + + new_hit_cnt = afl->queued_items + afl->saved_crashes; + + afl->stage_finds[STAGE_QUICK] += new_hit_cnt - orig_hit_cnt; + afl->stage_cycles[STAGE_QUICK] += (afl->fsrv.total_execs - before_eff_execs); + +cleanup_skipdet: + + if (fuzz_nearby) { + + u8 *nearby_bytes = (u8 *)ck_alloc(sizeof(u8) * len); + + u32 i = 3; + while (i < len) { + + // assume DWORD size, from i - 3 -> i + 3 + if (skip_eff_map[i]) { + + u32 fill_length = (i + 3 < len) ? 7 : len - i + 2; + memset(nearby_bytes + i - 3, 1, fill_length); + i += 3; + + } else + + i += 1; + + } + + for (i = 0; i < len; i++) { + + if (nearby_bytes[i] && !non_eff_bytes[i]) skip_eff_map[i] = 1; + + } + + ck_free(nearby_bytes); + ck_free(non_eff_bytes); + + } + + if (done_eff) { + + afl->queue_cur->skipdet_e->continue_inf = 0; + afl->queue_cur->skipdet_e->done_eff = 1; + + } else { + + afl->queue_cur->skipdet_e->continue_inf = 1; + + } + + return 1; + +} + diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 7d6fdfb9..6cf580ce 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -102,7 +102,7 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) { afl->stats_update_freq = 1; afl->stats_file_update_freq_msecs = STATS_UPDATE_SEC * 1000; afl->stats_avg_exec = 0; - afl->skip_deterministic = 1; + afl->skip_deterministic = 0; afl->sync_time = SYNC_TIME; afl->cmplog_lvl = 2; afl->min_length = 1; @@ -140,6 +140,14 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) { afl->fsrv.child_pid = -1; afl->fsrv.out_dir_fd = -1; + /* Init SkipDet */ + afl->skipdet_g = + (struct skipdet_global *)ck_alloc(sizeof(struct skipdet_global)); + afl->skipdet_g->inf_prof = + (struct inf_profile *)ck_alloc(sizeof(struct inf_profile)); + afl->havoc_prof = + (struct havoc_profile *)ck_alloc(sizeof(struct havoc_profile)); + init_mopt_globals(afl); list_append(&afl_states, afl); diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index deb28b7a..4b83ad29 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -502,6 +502,44 @@ void maybe_update_plot_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, } +/* Log deterministic stage efficiency */ + +void plot_profile_data(afl_state_t *afl, struct queue_entry *q) { + + u64 current_ms = get_cur_time() - afl->start_time; + + u32 current_edges = count_non_255_bytes(afl, afl->virgin_bits); + double det_finding_rate = (double)afl->havoc_prof->total_det_edge * 100.0 / + (double)current_edges, + det_time_rate = (double)afl->havoc_prof->total_det_time * 100.0 / + (double)current_ms; + + u32 ndet_bits = 0; + for (u32 i = 0; i < afl->fsrv.map_size; i++) { + + if (afl->skipdet_g->virgin_det_bits[i]) ndet_bits += 1; + + } + + double det_fuzzed_rate = (double)ndet_bits * 100.0 / (double)current_edges; + + fprintf(afl->fsrv.det_plot_file, + "[%02lld:%02lld:%02lld] fuzz %d (%d), find %d/%d among %d(%02.2f) " + "and spend %lld/%lld(%02.2f), cover %02.2f yet, %d/%d undet bits, " + "continue %d.\n", + current_ms / 1000 / 3600, (current_ms / 1000 / 60) % 60, + (current_ms / 1000) % 60, afl->current_entry, q->fuzz_level, + afl->havoc_prof->edge_det_stage, afl->havoc_prof->edge_havoc_stage, + current_edges, det_finding_rate, + afl->havoc_prof->det_stage_time / 1000, + afl->havoc_prof->havoc_stage_time / 1000, det_time_rate, + det_fuzzed_rate, q->skipdet_e->undet_bits, + afl->skipdet_g->undet_bits_threshold, q->skipdet_e->continue_inf); + + fflush(afl->fsrv.det_plot_file); + +} + /* Check terminal dimensions after resize. */ static void check_term_size(afl_state_t *afl) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 8cf6c735..7db1aeb3 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -955,14 +955,14 @@ int main(int argc, char **argv_orig, char **envp) { break; - case 'D': /* enforce deterministic */ + case 'D': /* no deterministic */ - afl->skip_deterministic = 0; + afl->skip_deterministic = 1; break; - case 'd': /* skip deterministic */ + case 'd': /* partial deterministic */ - afl->skip_deterministic = 1; + afl->skip_deterministic = 0; break; case 'B': /* load bitmap */ @@ -3031,6 +3031,11 @@ stop_fuzzing: if (frida_afl_preload) { ck_free(frida_afl_preload); } fclose(afl->fsrv.plot_file); + + #ifdef INTROSPECTION + fclose(afl->fsrv.det_plot_file); + #endif + destroy_queue(afl); destroy_extras(afl); destroy_custom_mutators(afl); -- cgit v1.2.3 From 5ba66a8860657b21c45480f1d565634cfe38a7dc Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 1 Feb 2024 15:22:51 +0100 Subject: final touches for skipdet --- src/afl-forkserver.c | 4 +++- src/afl-fuzz-state.c | 2 +- src/afl-fuzz.c | 22 ++++++++++++++-------- 3 files changed, 18 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 214b4fe9..ded0c21d 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -1019,7 +1019,9 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if (status >= 0x41464c00 && status <= 0x41464cff) { - FATAL("Target uses the new forkserver model, you need to switch to a newer afl-fuzz too!"); + FATAL( + "Target uses the new forkserver model, you need to switch to a newer " + "afl-fuzz too!"); } diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 6cf580ce..b647ac84 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -102,7 +102,7 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) { afl->stats_update_freq = 1; afl->stats_file_update_freq_msecs = STATS_UPDATE_SEC * 1000; afl->stats_avg_exec = 0; - afl->skip_deterministic = 0; + afl->skip_deterministic = 1; afl->sync_time = SYNC_TIME; afl->cmplog_lvl = 2; afl->min_length = 1; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 7db1aeb3..69064d51 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -170,7 +170,7 @@ static void usage(u8 *argv0, int more_help) { " -g minlength - set min length of generated fuzz input (default: 1)\n" " -G maxlength - set max length of generated fuzz input (default: " "%lu)\n" - " -D - enable deterministic fuzzing (once per queue entry)\n" + " -D - enable (a new) effective deterministic fuzzing\n" " -L minutes - use MOpt(imize) mode and set the time limit for " "entering the\n" " pacemaker mode (minutes of no new finds). 0 = " @@ -955,14 +955,20 @@ int main(int argc, char **argv_orig, char **envp) { break; - case 'D': /* no deterministic */ + case 'D': /* partial deterministic */ - afl->skip_deterministic = 1; + afl->skip_deterministic = 0; break; - case 'd': /* partial deterministic */ + case 'd': /* no deterministic */ - afl->skip_deterministic = 0; + // this is the default and currently a lot of infrastructure enforces + // it (e.g. clusterfuzz, fuzzbench) based on that this feature + // originally was bad performance wise. We now have a better + // implementation, hence if it is activated, we do not want to + // deactivate it by such setups. + + // afl->skip_deterministic = 1; break; case 'B': /* load bitmap */ @@ -1424,11 +1430,11 @@ int main(int argc, char **argv_orig, char **envp) { } #endif + + // silently disable deterministic mutation if custom mutators are used if (!afl->skip_deterministic && afl->afl_env.afl_custom_mutator_only) { - FATAL( - "Using -D determinstic fuzzing is incompatible with " - "AFL_CUSTOM_MUTATOR_ONLY!"); + afl->skip_deterministic = 1; } -- cgit v1.2.3 From ba28f5fbfa32564891c87b4395bdb8a59b3df1f4 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 1 Feb 2024 16:01:16 +0100 Subject: remove unused var --- src/afl-fuzz-one.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 4a7d3fad..35841738 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -331,7 +331,7 @@ u8 fuzz_one_original(afl_state_t *afl) { u32 i; u8 *in_buf, *out_buf, *orig_in, *ex_tmp, *eff_map = 0; u64 havoc_queued = 0, orig_hit_cnt, new_hit_cnt = 0, prev_cksum, _prev_cksum; - u32 splice_cycle = 0, perf_score = 100, orig_perf, eff_cnt = 1; + u32 splice_cycle = 0, perf_score = 100, orig_perf; u8 ret_val = 1, doing_det = 0; @@ -848,7 +848,6 @@ u8 fuzz_one_original(afl_state_t *afl) { if (EFF_APOS(len - 1) != 0) { eff_map[EFF_APOS(len - 1)] = 1; - ++eff_cnt; } -- cgit v1.2.3 From 028d4c8c6483be765ec4a346b0f568992cbcc34b Mon Sep 17 00:00:00 2001 From: Han Zheng <35988108+kdsjZh@users.noreply.github.com> Date: Thu, 1 Feb 2024 17:53:07 +0100 Subject: remove redundant eff struct (#1977) --- src/afl-fuzz-one.c | 108 +++++------------------------------------------------ 1 file changed, 10 insertions(+), 98 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 35841738..c163a420 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -329,7 +329,7 @@ u8 fuzz_one_original(afl_state_t *afl) { u32 len, temp_len; u32 j; u32 i; - u8 *in_buf, *out_buf, *orig_in, *ex_tmp, *eff_map = 0; + u8 *in_buf, *out_buf, *orig_in, *ex_tmp; u64 havoc_queued = 0, orig_hit_cnt, new_hit_cnt = 0, prev_cksum, _prev_cksum; u32 splice_cycle = 0, perf_score = 100, orig_perf; @@ -824,33 +824,6 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->queue_cur->stats_mutated += afl->stage_max; #endif - /* Effector map setup. These macros calculate: - - EFF_APOS - position of a particular file offset in the map. - EFF_ALEN - length of a map with a particular number of bytes. - EFF_SPAN_ALEN - map span for a sequence of bytes. - - */ - -#define EFF_APOS(_p) ((_p) >> EFF_MAP_SCALE2) -#define EFF_REM(_x) ((_x) & ((1 << EFF_MAP_SCALE2) - 1)) -#define EFF_ALEN(_l) (EFF_APOS(_l) + !!EFF_REM(_l)) -#define EFF_SPAN_ALEN(_p, _l) (EFF_APOS((_p) + (_l)-1) - EFF_APOS(_p) + 1) - - /* Initialize effector map for the next step (see comments below). Always - flag first and last byte as doing something. */ - - eff_map = afl_realloc(AFL_BUF_PARAM(eff), EFF_ALEN(len)); - if (unlikely(!eff_map)) { PFATAL("alloc"); } - memset(eff_map, 0, EFF_ALEN(len)); - eff_map[0] = 1; - - if (EFF_APOS(len - 1) != 0) { - - eff_map[EFF_APOS(len - 1)] = 1; - - } - /* Walking byte. */ afl->stage_name = "bitflip 8/8"; @@ -881,14 +854,15 @@ u8 fuzz_one_original(afl_state_t *afl) { } - /* If the effector map is more than EFF_MAX_PERC dense, just flag the - whole thing as worth fuzzing, since we wouldn't be saving much time - anyway. */ + /* New effective bytes calculation. */ - memset(eff_map, 1, EFF_ALEN(len)); - afl->blocks_eff_select += EFF_ALEN(len); + for (i = 0; i < len; i++) { - afl->blocks_eff_total += EFF_ALEN(len); + if (skip_eff_map[i]) afl->blocks_eff_select += 1; + + } + + afl->blocks_eff_total += len; new_hit_cnt = afl->queued_items + afl->saved_crashes; @@ -913,13 +887,6 @@ u8 fuzz_one_original(afl_state_t *afl) { /* Let's consult the effector map... */ - if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)]) { - - --afl->stage_max; - continue; - - } - if (!skip_eff_map[i]) continue; if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } @@ -962,13 +929,6 @@ u8 fuzz_one_original(afl_state_t *afl) { for (i = 0; i < len - 3; ++i) { /* Let's consult the effector map... */ - if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)] && - !eff_map[EFF_APOS(i + 2)] && !eff_map[EFF_APOS(i + 3)]) { - - --afl->stage_max; - continue; - - } if (!skip_eff_map[i]) continue; @@ -1023,13 +983,6 @@ skip_bitflip: /* Let's consult the effector map... */ - if (!eff_map[EFF_APOS(i)]) { - - afl->stage_max -= 2 * ARITH_MAX; - continue; - - } - if (!skip_eff_map[i]) continue; if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } @@ -1114,13 +1067,6 @@ skip_bitflip: /* Let's consult the effector map... */ - if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)]) { - - afl->stage_max -= 4 * ARITH_MAX; - continue; - - } - if (!skip_eff_map[i]) continue; if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } @@ -1251,14 +1197,6 @@ skip_bitflip: /* Let's consult the effector map... */ - if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)] && - !eff_map[EFF_APOS(i + 2)] && !eff_map[EFF_APOS(i + 3)]) { - - afl->stage_max -= 4 * ARITH_MAX; - continue; - - } - if (!skip_eff_map[i]) continue; if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } @@ -1393,13 +1331,6 @@ skip_arith: /* Let's consult the effector map... */ - if (!eff_map[EFF_APOS(i)]) { - - afl->stage_max -= sizeof(interesting_8); - continue; - - } - if (!skip_eff_map[i]) continue; if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } @@ -1460,13 +1391,6 @@ skip_arith: /* Let's consult the effector map... */ - if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)]) { - - afl->stage_max -= sizeof(interesting_16); - continue; - - } - if (!skip_eff_map[i]) continue; if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } @@ -1555,14 +1479,6 @@ skip_arith: /* Let's consult the effector map... */ - if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)] && - !eff_map[EFF_APOS(i + 2)] && !eff_map[EFF_APOS(i + 3)]) { - - afl->stage_max -= sizeof(interesting_32) >> 1; - continue; - - } - if (!skip_eff_map[i]) continue; if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } @@ -1678,9 +1594,7 @@ skip_interest: if ((afl->extras_cnt > afl->max_det_extras && rand_below(afl, afl->extras_cnt) >= afl->max_det_extras) || afl->extras[j].len > len - i || - !memcmp(afl->extras[j].data, out_buf + i, afl->extras[j].len) || - !memchr(eff_map + EFF_APOS(i), 1, - EFF_SPAN_ALEN(i, afl->extras[j].len))) { + !memcmp(afl->extras[j].data, out_buf + i, afl->extras[j].len)) { --afl->stage_max; continue; @@ -1806,9 +1720,7 @@ skip_user_extras: /* See the comment in the earlier code; extras are sorted by size. */ if (afl->a_extras[j].len > len - i || - !memcmp(afl->a_extras[j].data, out_buf + i, afl->a_extras[j].len) || - !memchr(eff_map + EFF_APOS(i), 1, - EFF_SPAN_ALEN(i, afl->a_extras[j].len))) { + !memcmp(afl->a_extras[j].data, out_buf + i, afl->a_extras[j].len)) { --afl->stage_max; continue; -- cgit v1.2.3 From bd13d32437ebf0c1f7304dc4c8f9797dc4cce7fb Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 2 Feb 2024 09:54:24 +0100 Subject: final touches --- src/afl-cc.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 4f6745ed..fd466541 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1103,8 +1103,6 @@ static void instrument_opt_mode_exclude(aflcc_state_t *aflcc) { } - fprintf(stderr, "X %u %u\n", aflcc->compiler_mode, LTO); - if (aflcc->instrument_opt_mode && aflcc->compiler_mode != LLVM && !((aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER) && aflcc->compiler_mode == LTO)) -- cgit v1.2.3 From 1e7485dcee1f19d8eb78562d62c30f2aae5a101d Mon Sep 17 00:00:00 2001 From: Khaled Yakdan Date: Sat, 3 Feb 2024 10:49:45 +0100 Subject: Fix type in AFL_NOOPT env variable in afl-cc help message (#1982) --- src/afl-cc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index c300ddfc..98310545 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -2830,7 +2830,7 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { " AFL_DONT_OPTIMIZE: disable optimization instead of -O3\n" " AFL_NO_BUILTIN: no builtins for string compare functions (for " "libtokencap.so)\n" - " AFL_NOOP: behave like a normal compiler (to pass configure " + " AFL_NOOPT: behave like a normal compiler (to pass configure " "tests)\n" " AFL_PATH: path to instrumenting pass and runtime " "(afl-compiler-rt.*o)\n" -- cgit v1.2.3 From ed1a6f8a570c6fcabee962f402d8d58f6cea77b7 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 3 Feb 2024 11:01:31 +0100 Subject: 2024 v4.10c release --- src/afl-analyze.c | 2 +- src/afl-as.c | 2 +- src/afl-cc.c | 2 +- src/afl-common.c | 2 +- src/afl-forkserver.c | 2 +- src/afl-fuzz-bitmap.c | 2 +- src/afl-fuzz-cmplog.c | 2 +- src/afl-fuzz-extras.c | 2 +- src/afl-fuzz-init.c | 2 +- src/afl-fuzz-mutators.c | 2 +- src/afl-fuzz-one.c | 2 +- src/afl-fuzz-python.c | 2 +- src/afl-fuzz-queue.c | 2 +- src/afl-fuzz-redqueen.c | 2 +- src/afl-fuzz-run.c | 2 +- src/afl-fuzz-state.c | 2 +- src/afl-fuzz-stats.c | 2 +- src/afl-fuzz.c | 2 +- src/afl-gotcpu.c | 2 +- src/afl-ld-lto.c | 2 +- src/afl-sharedmem.c | 2 +- src/afl-showmap.c | 2 +- src/afl-tmin.c | 2 +- 23 files changed, 23 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/afl-analyze.c b/src/afl-analyze.c index 5b122741..95f32fee 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-as.c b/src/afl-as.c index 772e31b3..09ba75bf 100644 --- a/src/afl-as.c +++ b/src/afl-as.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-cc.c b/src/afl-cc.c index 98310545..e9564277 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -5,7 +5,7 @@ Written by Michal Zalewski, Laszlo Szekeres and Marc Heuse Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-common.c b/src/afl-common.c index ba498b3b..87003b03 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index ded0c21d..0a77d61c 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -13,7 +13,7 @@ Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 5f67347c..d056ac9f 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c index 3e6432ca..21f34e12 100644 --- a/src/afl-fuzz-cmplog.c +++ b/src/afl-fuzz-cmplog.c @@ -11,7 +11,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c index 905431d1..3b1d13f1 100644 --- a/src/afl-fuzz-extras.c +++ b/src/afl-fuzz-extras.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 057d8cf5..76291cc4 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index 17fb9368..ae4d6668 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -10,7 +10,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index c163a420..d9c074ec 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c index 4c7da774..16a398fd 100644 --- a/src/afl-fuzz-python.c +++ b/src/afl-fuzz-python.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 67931bba..1ea50418 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 9e9b3822..eead7a8b 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -11,7 +11,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 1ee8ebe7..d764952c 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -10,7 +10,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index b647ac84..4467cae8 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 4b83ad29..76577081 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 69064d51..12d67fe7 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-gotcpu.c b/src/afl-gotcpu.c index 4f851099..7aee2985 100644 --- a/src/afl-gotcpu.c +++ b/src/afl-gotcpu.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c index 7ce5de41..513c1ae9 100644 --- a/src/afl-ld-lto.c +++ b/src/afl-ld-lto.c @@ -9,7 +9,7 @@ Andrea Fioraldi Dominik Maier - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-sharedmem.c b/src/afl-sharedmem.c index a2c81586..daea8f46 100644 --- a/src/afl-sharedmem.c +++ b/src/afl-sharedmem.c @@ -11,7 +11,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 7a639cf6..20ba5a5e 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -12,7 +12,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-tmin.c b/src/afl-tmin.c index e7442d1d..4e5dab41 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -12,7 +12,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. -- cgit v1.2.3 From 602eceed8b56eef62d673a54b6011541bf1ab60a Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sat, 3 Feb 2024 11:55:51 +0100 Subject: push to stable (#1983) * Output afl-clang-fast stuffs only if necessary (#1912) * afl-cc header * afl-cc common declarations - Add afl-cc-state.c - Strip includes, find_object, debug/be_quiet/have_*/callname setting from afl-cc.c - Use debugf_args in main - Modify execvp stuffs to fit new aflcc struct * afl-cc show usage * afl-cc mode selecting 1. compiler_mode by callname in argv[0] 2. compiler_mode by env "AFL_CC_COMPILER" 3. compiler_mode/instrument_mode by command line options "--afl-..." 4. instrument_mode/compiler_mode by various env vars including "AFL_LLVM_INSTRUMENT" 5. final checking steps 6. print "... - mode: %s-%s\n" 7. determine real argv[0] according to compiler_mode * afl-cc macro defs * afl-cc linking behaviors * afl-cc fsanitize behaviors * afl-cc misc * afl-cc body update * afl-cc all-in-one formated with custom-format.py * nits --------- Co-authored-by: vanhauser-thc * changelog * update grammar mutator * lto llvm 12+ * docs(custom_mutators): fix missing ':' (#1953) * Fix broken LTO mode and response file support (#1948) * Strip `-Wl,-no-undefined` during compilation (#1952) Make the compiler wrapper stripping `-Wl,-no-undefined` in addition to `-Wl,--no-undefined`. Both versions of the flag are accepted by clang and, therefore, used by building systems in the wild (e.g., samba will not build without this fix). * Remove dead code in write_to_testcase (#1955) The custom_mutators_count check in if case is duplicate with if condition. The else case is custom_mutators_count == 0, neither custom_mutator_list iteration nor sent check needed. Signed-off-by: Xeonacid * update qemuafl * WIP: Add ability to generate drcov trace using QEMU backend (#1956) * Document new drcov QEMU plugin * Add link to lightkeeper for QEMU drcov file loading --------- Co-authored-by: Jean-Romain Garnier * code format * changelog * sleep on uid != 0 afl-system-config * fix segv about skip_next, warn on unsupported cases of linking options (#1958) * todos * ensure afl-cc only allows available compiler modes * update grammar mutator * disable aslr on apple * fix for arm64 * help selective instrumentation * typos * macos * add compiler test script * apple fixes * bump nyx submodules (#1963) * fix docs * update changelog * update grammar mutator * improve compiler test script * gcc asan workaround (#1966) * fix github merge fuckup * fix * Fix afl-cc (#1968) - Check if too many cmdline params here, each time before insert a new param. - Check if it is "-fsanitize=..." before we do sth. - Remove improper param_st transfer. * Avoid adding llvmnative instrumentation when linking rust sanitizer runtime (#1969) * Dynamic instrumentation filtering for LLVM native (#1971) * Add two dynamic instrumentation filter methods to runtime * Always use pc-table with native pcguard * Add make_symbol_list.py and README * changelog * todos * new forkserver check * fix * nyx test for CI * improve nyx docs * Fixes to afl-cc and documentation (#1974) * Always compile with -ldl when building for CODE_COVERAGE When building with CODE_COVERAGE, the afl runtime contains code that calls `dladdr` which requires -ldl. Under most circumstances, clang already adds this (e.g. when building with pc-table), but there are some circumstances where it isn't added automatically. * Add visibility declaration to __afl_connected When building with hidden visibility, the use of __AFL_LOOP inside such code can cause linker errors due to __afl_connected being declared "hidden". * Update docs to clarify that CODE_COVERAGE=1 is required for dynamic_covfilter * nits * nyx build script updates * test error output * debug ci * debug ci * Improve afl-cc (#1975) * update response file support - full support of rsp file - fix some segv issues * Improve afl-cc - remove dead code about allow/denylist options of sancov - missing `if (!aflcc->have_msan)` - add docs for each function - typo * enable nyx * debug ci * debug ci * debug ci * debug ci * debug ci * debug ci * debug ci * debug ci * fix ci * clean test script * NO_NYX * NO_NYX * fix ci * debug ci * fix ci * finalize ci fix * Enhancement on Deterministic stage (#1972) * fuzzer: init commit based on aflpp 60dc37a8cf09f8e9048e4b6a2204d6c90b27655a * fuzzers: adding the skip variables and initialize * log: profile the det/havoc finding * log: add profile log output * fuzzers: sperate log/skipdet module * fuzzers: add quick eff_map calc * fuzzers: add skip_eff_map in fuzz_one * fuzzers: mark whole input space in eff_map * fuzzers: add undet bit threshold to skip some seeds * fuzzers: fix one byte overflow * fuzzers: fix overflow * fix code format * add havoc only again * code format * remove log to INTROSPECTION, rename skipdet module * rename skipdet module * remove log to stats * clean redundant code * code format * remove redundant code format check * remove redundant doc * remove redundant objects * clean files * change -d to default skipdet * disable deterministic when using CUSTOM_MUTATOR * revert fix * final touches for skipdet * remove unused var * remove redundant eff struct (#1977) * update QEMU-Nyx submodule (#1978) * update QEMU-Nyx submodule (#1980) * Fix type in AFL_NOOPT env variable in afl-cc help message (#1982) * nits * 2024 v4.10c release * fixes --------- Signed-off-by: Xeonacid Co-authored-by: Sonic <50692172+SonicStark@users.noreply.github.com> Co-authored-by: Xeonacid Co-authored-by: Nils Bars Co-authored-by: Jean-Romain Garnier <7504819+JRomainG@users.noreply.github.com> Co-authored-by: Jean-Romain Garnier Co-authored-by: Sergej Schumilo Co-authored-by: Christian Holler (:decoder) Co-authored-by: Han Zheng <35988108+kdsjZh@users.noreply.github.com> Co-authored-by: Khaled Yakdan --- src/afl-analyze.c | 2 +- src/afl-as.c | 2 +- src/afl-cc.c | 4 +- src/afl-common.c | 2 +- src/afl-forkserver.c | 6 +- src/afl-fuzz-bitmap.c | 2 +- src/afl-fuzz-cmplog.c | 2 +- src/afl-fuzz-extras.c | 2 +- src/afl-fuzz-init.c | 17 +- src/afl-fuzz-mutators.c | 2 +- src/afl-fuzz-one.c | 237 ++++++++++++++-------------- src/afl-fuzz-python.c | 2 +- src/afl-fuzz-queue.c | 13 +- src/afl-fuzz-redqueen.c | 2 +- src/afl-fuzz-run.c | 2 +- src/afl-fuzz-skipdet.c | 403 ++++++++++++++++++++++++++++++++++++++++++++++++ src/afl-fuzz-state.c | 10 +- src/afl-fuzz-stats.c | 40 ++++- src/afl-fuzz.c | 27 +++- src/afl-gotcpu.c | 2 +- src/afl-ld-lto.c | 2 +- src/afl-sharedmem.c | 2 +- src/afl-showmap.c | 2 +- src/afl-tmin.c | 2 +- 24 files changed, 633 insertions(+), 154 deletions(-) create mode 100644 src/afl-fuzz-skipdet.c (limited to 'src') diff --git a/src/afl-analyze.c b/src/afl-analyze.c index 5b122741..95f32fee 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-as.c b/src/afl-as.c index 772e31b3..09ba75bf 100644 --- a/src/afl-as.c +++ b/src/afl-as.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-cc.c b/src/afl-cc.c index c300ddfc..e9564277 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -5,7 +5,7 @@ Written by Michal Zalewski, Laszlo Szekeres and Marc Heuse Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -2830,7 +2830,7 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { " AFL_DONT_OPTIMIZE: disable optimization instead of -O3\n" " AFL_NO_BUILTIN: no builtins for string compare functions (for " "libtokencap.so)\n" - " AFL_NOOP: behave like a normal compiler (to pass configure " + " AFL_NOOPT: behave like a normal compiler (to pass configure " "tests)\n" " AFL_PATH: path to instrumenting pass and runtime " "(afl-compiler-rt.*o)\n" diff --git a/src/afl-common.c b/src/afl-common.c index ba498b3b..87003b03 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 214b4fe9..0a77d61c 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -13,7 +13,7 @@ Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -1019,7 +1019,9 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if (status >= 0x41464c00 && status <= 0x41464cff) { - FATAL("Target uses the new forkserver model, you need to switch to a newer afl-fuzz too!"); + FATAL( + "Target uses the new forkserver model, you need to switch to a newer " + "afl-fuzz too!"); } diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 5f67347c..d056ac9f 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c index 3e6432ca..21f34e12 100644 --- a/src/afl-fuzz-cmplog.c +++ b/src/afl-fuzz-cmplog.c @@ -11,7 +11,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c index 905431d1..3b1d13f1 100644 --- a/src/afl-fuzz-extras.c +++ b/src/afl-fuzz-extras.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 8ab44a3b..76291cc4 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -2236,6 +2236,21 @@ void setup_dirs_fds(afl_state_t *afl) { fflush(afl->fsrv.plot_file); +#ifdef INTROSPECTION + + tmp = alloc_printf("%s/plot_det_data", afl->out_dir); + + int fd = open(tmp, O_WRONLY | O_CREAT, DEFAULT_PERMISSION); + if (fd < 0) { PFATAL("Unable to create '%s'", tmp); } + ck_free(tmp); + + afl->fsrv.det_plot_file = fdopen(fd, "w"); + if (!afl->fsrv.det_plot_file) { PFATAL("fdopen() failed"); } + + if (afl->in_place_resume) { fseek(afl->fsrv.det_plot_file, 0, SEEK_END); } + +#endif + /* ignore errors */ } diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index 17fb9368..ae4d6668 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -10,7 +10,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 01e34b69..d9c074ec 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -329,9 +329,9 @@ u8 fuzz_one_original(afl_state_t *afl) { u32 len, temp_len; u32 j; u32 i; - u8 *in_buf, *out_buf, *orig_in, *ex_tmp, *eff_map = 0; + u8 *in_buf, *out_buf, *orig_in, *ex_tmp; u64 havoc_queued = 0, orig_hit_cnt, new_hit_cnt = 0, prev_cksum, _prev_cksum; - u32 splice_cycle = 0, perf_score = 100, orig_perf, eff_cnt = 1; + u32 splice_cycle = 0, perf_score = 100, orig_perf; u8 ret_val = 1, doing_det = 0; @@ -545,12 +545,37 @@ u8 fuzz_one_original(afl_state_t *afl) { } + u64 before_det_time = get_cur_time(); +#ifdef INTROSPECTION + + u64 before_havoc_time; + u32 before_det_findings = afl->queued_items, + before_det_edges = count_non_255_bytes(afl, afl->virgin_bits), + before_havoc_findings, before_havoc_edges; + u8 is_logged = 0; + +#endif + if (!afl->skip_deterministic) { + + if (!skip_deterministic_stage(afl, in_buf, out_buf, len, before_det_time)) { + + goto abandon_entry; + + } + + } + + u8 *skip_eff_map = afl->queue_cur->skipdet_e->skip_eff_map; + /* Skip right away if -d is given, if it has not been chosen sufficiently often to warrant the expensive deterministic stage (fuzz_level), or if it has gone through deterministic testing in earlier, resumed runs (passed_det). */ + /* if skipdet decide to skip the seed or no interesting bytes found, + we skip the whole deterministic stage as well */ if (likely(afl->skip_deterministic) || likely(afl->queue_cur->passed_det) || + likely(!afl->queue_cur->skipdet_e->quick_eff_bytes) || likely(perf_score < (afl->queue_cur->depth * 30 <= afl->havoc_max_mult * 100 ? afl->queue_cur->depth * 30 @@ -609,6 +634,10 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->stage_cur_byte = afl->stage_cur >> 3; + if (!skip_eff_map[afl->stage_cur_byte]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + FLIP_BIT(out_buf, afl->stage_cur); #ifdef INTROSPECTION @@ -725,6 +754,10 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->stage_cur_byte = afl->stage_cur >> 3; + if (!skip_eff_map[afl->stage_cur_byte]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + FLIP_BIT(out_buf, afl->stage_cur); FLIP_BIT(out_buf, afl->stage_cur + 1); @@ -760,6 +793,10 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->stage_cur_byte = afl->stage_cur >> 3; + if (!skip_eff_map[afl->stage_cur_byte]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + FLIP_BIT(out_buf, afl->stage_cur); FLIP_BIT(out_buf, afl->stage_cur + 1); FLIP_BIT(out_buf, afl->stage_cur + 2); @@ -787,34 +824,6 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->queue_cur->stats_mutated += afl->stage_max; #endif - /* Effector map setup. These macros calculate: - - EFF_APOS - position of a particular file offset in the map. - EFF_ALEN - length of a map with a particular number of bytes. - EFF_SPAN_ALEN - map span for a sequence of bytes. - - */ - -#define EFF_APOS(_p) ((_p) >> EFF_MAP_SCALE2) -#define EFF_REM(_x) ((_x) & ((1 << EFF_MAP_SCALE2) - 1)) -#define EFF_ALEN(_l) (EFF_APOS(_l) + !!EFF_REM(_l)) -#define EFF_SPAN_ALEN(_p, _l) (EFF_APOS((_p) + (_l)-1) - EFF_APOS(_p) + 1) - - /* Initialize effector map for the next step (see comments below). Always - flag first and last byte as doing something. */ - - eff_map = afl_realloc(AFL_BUF_PARAM(eff), EFF_ALEN(len)); - if (unlikely(!eff_map)) { PFATAL("alloc"); } - memset(eff_map, 0, EFF_ALEN(len)); - eff_map[0] = 1; - - if (EFF_APOS(len - 1) != 0) { - - eff_map[EFF_APOS(len - 1)] = 1; - ++eff_cnt; - - } - /* Walking byte. */ afl->stage_name = "bitflip 8/8"; @@ -828,6 +837,10 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->stage_cur_byte = afl->stage_cur; + if (!skip_eff_map[afl->stage_cur_byte]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + out_buf[afl->stage_cur] ^= 0xFF; #ifdef INTROSPECTION @@ -837,59 +850,19 @@ u8 fuzz_one_original(afl_state_t *afl) { if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } - /* We also use this stage to pull off a simple trick: we identify - bytes that seem to have no effect on the current execution path - even when fully flipped - and we skip them during more expensive - deterministic stages, such as arithmetics or known ints. */ - - if (!eff_map[EFF_APOS(afl->stage_cur)]) { - - u64 cksum; - - /* If in non-instrumented mode or if the file is very short, just flag - everything without wasting time on checksums. */ - - if (!afl->non_instrumented_mode && len >= EFF_MIN_LEN) { - - cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); - - } else { - - cksum = ~prev_cksum; - - } - - if (cksum != prev_cksum) { - - eff_map[EFF_APOS(afl->stage_cur)] = 1; - ++eff_cnt; - - } - - } - out_buf[afl->stage_cur] ^= 0xFF; } - /* If the effector map is more than EFF_MAX_PERC dense, just flag the - whole thing as worth fuzzing, since we wouldn't be saving much time - anyway. */ - - if (eff_cnt != (u32)EFF_ALEN(len) && - eff_cnt * 100 / EFF_ALEN(len) > EFF_MAX_PERC) { + /* New effective bytes calculation. */ - memset(eff_map, 1, EFF_ALEN(len)); + for (i = 0; i < len; i++) { - afl->blocks_eff_select += EFF_ALEN(len); - - } else { - - afl->blocks_eff_select += eff_cnt; + if (skip_eff_map[i]) afl->blocks_eff_select += 1; } - afl->blocks_eff_total += EFF_ALEN(len); + afl->blocks_eff_total += len; new_hit_cnt = afl->queued_items + afl->saved_crashes; @@ -914,12 +887,9 @@ u8 fuzz_one_original(afl_state_t *afl) { /* Let's consult the effector map... */ - if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)]) { - - --afl->stage_max; - continue; + if (!skip_eff_map[i]) continue; - } + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } afl->stage_cur_byte = i; @@ -959,13 +929,10 @@ u8 fuzz_one_original(afl_state_t *afl) { for (i = 0; i < len - 3; ++i) { /* Let's consult the effector map... */ - if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)] && - !eff_map[EFF_APOS(i + 2)] && !eff_map[EFF_APOS(i + 3)]) { - --afl->stage_max; - continue; + if (!skip_eff_map[i]) continue; - } + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } afl->stage_cur_byte = i; @@ -1016,12 +983,9 @@ skip_bitflip: /* Let's consult the effector map... */ - if (!eff_map[EFF_APOS(i)]) { - - afl->stage_max -= 2 * ARITH_MAX; - continue; + if (!skip_eff_map[i]) continue; - } + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } afl->stage_cur_byte = i; @@ -1103,12 +1067,9 @@ skip_bitflip: /* Let's consult the effector map... */ - if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)]) { - - afl->stage_max -= 4 * ARITH_MAX; - continue; + if (!skip_eff_map[i]) continue; - } + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } afl->stage_cur_byte = i; @@ -1236,13 +1197,9 @@ skip_bitflip: /* Let's consult the effector map... */ - if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)] && - !eff_map[EFF_APOS(i + 2)] && !eff_map[EFF_APOS(i + 3)]) { - - afl->stage_max -= 4 * ARITH_MAX; - continue; + if (!skip_eff_map[i]) continue; - } + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } afl->stage_cur_byte = i; @@ -1374,12 +1331,9 @@ skip_arith: /* Let's consult the effector map... */ - if (!eff_map[EFF_APOS(i)]) { - - afl->stage_max -= sizeof(interesting_8); - continue; + if (!skip_eff_map[i]) continue; - } + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } afl->stage_cur_byte = i; @@ -1437,12 +1391,9 @@ skip_arith: /* Let's consult the effector map... */ - if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)]) { + if (!skip_eff_map[i]) continue; - afl->stage_max -= sizeof(interesting_16); - continue; - - } + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } afl->stage_cur_byte = i; @@ -1528,13 +1479,9 @@ skip_arith: /* Let's consult the effector map... */ - if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)] && - !eff_map[EFF_APOS(i + 2)] && !eff_map[EFF_APOS(i + 3)]) { + if (!skip_eff_map[i]) continue; - afl->stage_max -= sizeof(interesting_32) >> 1; - continue; - - } + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } afl->stage_cur_byte = i; @@ -1626,6 +1573,10 @@ skip_interest: u32 last_len = 0; + if (!skip_eff_map[i]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + afl->stage_cur_byte = i; /* Extras are sorted by size, from smallest to largest. This means @@ -1643,9 +1594,7 @@ skip_interest: if ((afl->extras_cnt > afl->max_det_extras && rand_below(afl, afl->extras_cnt) >= afl->max_det_extras) || afl->extras[j].len > len - i || - !memcmp(afl->extras[j].data, out_buf + i, afl->extras[j].len) || - !memchr(eff_map + EFF_APOS(i), 1, - EFF_SPAN_ALEN(i, afl->extras[j].len))) { + !memcmp(afl->extras[j].data, out_buf + i, afl->extras[j].len)) { --afl->stage_max; continue; @@ -1693,6 +1642,10 @@ skip_interest: for (i = 0; i <= (u32)len; ++i) { + if (!skip_eff_map[i % len]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + afl->stage_cur_byte = i; for (j = 0; j < afl->extras_cnt; ++j) { @@ -1755,6 +1708,10 @@ skip_user_extras: u32 last_len = 0; + if (!skip_eff_map[i]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + afl->stage_cur_byte = i; u32 min_extra_len = MIN(afl->a_extras_cnt, (u32)USE_AUTO_EXTRAS); @@ -1763,9 +1720,7 @@ skip_user_extras: /* See the comment in the earlier code; extras are sorted by size. */ if (afl->a_extras[j].len > len - i || - !memcmp(afl->a_extras[j].data, out_buf + i, afl->a_extras[j].len) || - !memchr(eff_map + EFF_APOS(i), 1, - EFF_SPAN_ALEN(i, afl->a_extras[j].len))) { + !memcmp(afl->a_extras[j].data, out_buf + i, afl->a_extras[j].len)) { --afl->stage_max; continue; @@ -1813,6 +1768,10 @@ skip_user_extras: for (i = 0; i <= (u32)len; ++i) { + if (!skip_eff_map[i % len]) continue; + + if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } + afl->stage_cur_byte = i; for (j = 0; j < afl->a_extras_cnt; ++j) { @@ -2020,6 +1979,19 @@ custom_mutator_stage: havoc_stage: +#ifdef INTROSPECTION + + if (!is_logged) { + + is_logged = 1; + before_havoc_findings = afl->queued_items; + before_havoc_edges = count_non_255_bytes(afl, afl->virgin_bits); + before_havoc_time = get_cur_time(); + + } + +#endif + if (unlikely(afl->custom_only)) { /* Force UI update */ @@ -3430,6 +3402,25 @@ retry_splicing: ret_val = 0; +#ifdef INTROSPECTION + + afl->havoc_prof->queued_det_stage = + before_havoc_findings - before_det_findings; + afl->havoc_prof->queued_havoc_stage = + afl->queued_items - before_havoc_findings; + afl->havoc_prof->total_queued_det += afl->havoc_prof->queued_det_stage; + afl->havoc_prof->edge_det_stage = before_havoc_edges - before_det_edges; + afl->havoc_prof->edge_havoc_stage = + count_non_255_bytes(afl, afl->virgin_bits) - before_havoc_edges; + afl->havoc_prof->total_det_edge += afl->havoc_prof->edge_det_stage; + afl->havoc_prof->det_stage_time = before_havoc_time - before_det_time; + afl->havoc_prof->havoc_stage_time = get_cur_time() - before_havoc_time; + afl->havoc_prof->total_det_time += afl->havoc_prof->det_stage_time; + + plot_profile_data(afl, afl->queue_cur); + +#endif + /* we are through with this queue entry - for this iteration */ abandon_entry: diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c index 4c7da774..16a398fd 100644 --- a/src/afl-fuzz-python.c +++ b/src/afl-fuzz-python.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 4b9627f7..1ea50418 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: @@ -664,6 +664,8 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { } + q->skipdet_e = (struct skipdet_entry *)ck_alloc(sizeof(struct skipdet_entry)); + } /* Destroy the entire queue. */ @@ -679,6 +681,15 @@ void destroy_queue(afl_state_t *afl) { q = afl->queue_buf[i]; ck_free(q->fname); ck_free(q->trace_mini); + if (q->skipdet_e) { + + if (q->skipdet_e->done_inf_map) ck_free(q->skipdet_e->done_inf_map); + if (q->skipdet_e->skip_eff_map) ck_free(q->skipdet_e->skip_eff_map); + + ck_free(q->skipdet_e); + + } + ck_free(q); } diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 9e9b3822..eead7a8b 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -11,7 +11,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 1ee8ebe7..d764952c 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -10,7 +10,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-skipdet.c b/src/afl-fuzz-skipdet.c new file mode 100644 index 00000000..e52d59a3 --- /dev/null +++ b/src/afl-fuzz-skipdet.c @@ -0,0 +1,403 @@ + + +#include "afl-fuzz.h" + +void flip_range(u8 *input, u32 pos, u32 size) { + + for (u32 i = 0; i < size; i++) + input[pos + i] ^= 0xFF; + + return; + +} + +#define MAX_EFF_TIMEOUT (10 * 60 * 1000) +#define MAX_DET_TIMEOUT (15 * 60 * 1000) +u8 is_det_timeout(u64 cur_ms, u8 is_flip) { + + if (is_flip) { + + if (unlikely(get_cur_time() - cur_ms > MAX_EFF_TIMEOUT)) return 1; + + } else { + + if (unlikely(get_cur_time() - cur_ms > MAX_DET_TIMEOUT)) return 1; + + } + + return 0; + +} + +/* decide if the seed should be deterministically fuzzed */ + +u8 should_det_fuzz(afl_state_t *afl, struct queue_entry *q) { + + if (!afl->skipdet_g->virgin_det_bits) { + + afl->skipdet_g->virgin_det_bits = + (u8 *)ck_alloc(sizeof(u8) * afl->fsrv.map_size); + + } + + if (!q->favored || q->passed_det) return 0; + if (!q->trace_mini) return 0; + + if (!afl->skipdet_g->last_cov_undet) + afl->skipdet_g->last_cov_undet = get_cur_time(); + + if (get_cur_time() - afl->skipdet_g->last_cov_undet >= THRESHOLD_DEC_TIME) { + + if (afl->skipdet_g->undet_bits_threshold >= 2) { + + afl->skipdet_g->undet_bits_threshold *= 0.75; + afl->skipdet_g->last_cov_undet = get_cur_time(); + + } + + } + + u32 new_det_bits = 0; + + for (u32 i = 0; i < afl->fsrv.map_size; i++) { + + if (unlikely(q->trace_mini[i >> 3] & (1 << (i & 7)))) { + + if (!afl->skipdet_g->virgin_det_bits[i]) { new_det_bits++; } + + } + + } + + if (!afl->skipdet_g->undet_bits_threshold) + afl->skipdet_g->undet_bits_threshold = new_det_bits * 0.05; + + if (new_det_bits >= afl->skipdet_g->undet_bits_threshold) { + + afl->skipdet_g->last_cov_undet = get_cur_time(); + q->skipdet_e->undet_bits = new_det_bits; + + for (u32 i = 0; i < afl->fsrv.map_size; i++) { + + if (unlikely(q->trace_mini[i >> 3] & (1 << (i & 7)))) { + + if (!afl->skipdet_g->virgin_det_bits[i]) + afl->skipdet_g->virgin_det_bits[i] = 1; + + } + + } + + return 1; + + } + + return 0; + +} + +/* + consists of two stages that + return 0 if exec failed. +*/ + +u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf, + u32 len, u64 before_det_time) { + + u64 orig_hit_cnt, new_hit_cnt; + + if (afl->queue_cur->skipdet_e->done_eff) return 1; + + if (!should_det_fuzz(afl, afl->queue_cur)) return 1; + + /* Add check to make sure that for seeds without too much undet bits, + we ignore them */ + + /****************** + * SKIP INFERENCE * + ******************/ + + afl->stage_short = "inf"; + afl->stage_name = "inference"; + afl->stage_cur = 0; + orig_hit_cnt = afl->queued_items + afl->saved_crashes; + + u8 *inf_eff_map = (u8 *)ck_alloc(sizeof(u8) * len); + memset(inf_eff_map, 1, sizeof(u8) * len); + + if (common_fuzz_stuff(afl, orig_buf, len)) { return 0; } + + u64 prev_cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); + u64 _prev_cksum = prev_cksum; + + if (MINIMAL_BLOCK_SIZE * 8 < len) { + + // u64 size_skiped = 0, quick_skip_exec = total_execs, quick_skip_time = + // get_cur_time(); + u64 pre_inf_exec = afl->fsrv.total_execs, pre_inf_time = get_cur_time(); + + /* if determine stage time / input size is too small, just go ahead */ + + u32 pos = 0, cur_block_size = MINIMAL_BLOCK_SIZE, max_block_size = len / 8; + + while (pos < len - 1) { + + cur_block_size = MINIMAL_BLOCK_SIZE; + + while (cur_block_size < max_block_size) { + + u32 flip_block_size = + (cur_block_size + pos < len) ? cur_block_size : len - 1 - pos; + + afl->stage_cur += 1; + + flip_range(out_buf, pos, flip_block_size); + + if (common_fuzz_stuff(afl, out_buf, len)) return 0; + + flip_range(out_buf, pos, flip_block_size); + + u64 cksum = + hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); + + // printf("Now trying range %d with %d, %s.\n", pos, cur_block_size, + // (cksum == prev_cksum) ? (u8*)"Yes" : (u8*) "Not"); + + /* continue until we fail or exceed length */ + if (cksum == _prev_cksum) { + + cur_block_size *= 2; + + if (cur_block_size >= len - 1 - pos) break; + + } else { + + break; + + } + + } + + if (cur_block_size == MINIMAL_BLOCK_SIZE) { + + /* we failed early on*/ + + pos += cur_block_size; + + } else { + + u32 cur_skip_len = (cur_block_size / 2 + pos < len) + ? (cur_block_size / 2) + : (len - pos - 1); + + memset(inf_eff_map + pos, 0, cur_skip_len); + + afl->skipdet_g->inf_prof->inf_skipped_bytes += cur_skip_len; + + pos += cur_skip_len; + + } + + } + + afl->skipdet_g->inf_prof->inf_execs_cost += + (afl->fsrv.total_execs - pre_inf_exec); + afl->skipdet_g->inf_prof->inf_time_cost += (get_cur_time() - pre_inf_time); + // PFATAL("Done, now have %d bytes skipped, with exec %lld, time %lld.\n", + // afl->inf_skipped_bytes, afl->inf_execs_cost, afl->inf_time_cost); + + } else + + memset(inf_eff_map, 1, len); + + new_hit_cnt = afl->queued_items + afl->saved_crashes; + + afl->stage_finds[STAGE_INF] += new_hit_cnt - orig_hit_cnt; + afl->stage_cycles[STAGE_INF] += afl->stage_cur; + + /**************************** + * Quick Skip Effective Map * + ****************************/ + + /* Quick Effective Map Calculation */ + + afl->stage_short = "quick"; + afl->stage_name = "quick eff"; + afl->stage_cur = 0; + afl->stage_max = 32 * 1024; + + orig_hit_cnt = afl->queued_items + afl->saved_crashes; + + u32 before_skip_inf = afl->queued_items; + + /* clean all the eff bytes, since previous eff bytes are already fuzzed */ + u8 *skip_eff_map = afl->queue_cur->skipdet_e->skip_eff_map, + *done_inf_map = afl->queue_cur->skipdet_e->done_inf_map; + + if (!skip_eff_map) { + + skip_eff_map = (u8 *)ck_alloc(sizeof(u8) * len); + afl->queue_cur->skipdet_e->skip_eff_map = skip_eff_map; + + } else { + + memset(skip_eff_map, 0, sizeof(u8) * len); + + } + + /* restore the starting point */ + if (!done_inf_map) { + + done_inf_map = (u8 *)ck_alloc(sizeof(u8) * len); + afl->queue_cur->skipdet_e->done_inf_map = done_inf_map; + + } else { + + for (afl->stage_cur = 0; afl->stage_cur < len; afl->stage_cur++) { + + if (done_inf_map[afl->stage_cur] == 0) break; + + } + + } + + /* depending on the seed's performance, we could search eff bytes + for multiple rounds */ + + u8 eff_round_continue = 1, eff_round_done = 0, done_eff = 0, repeat_eff = 0, + fuzz_nearby = 0, *non_eff_bytes = 0; + + u64 before_eff_execs = afl->fsrv.total_execs; + + if (getenv("REPEAT_EFF")) repeat_eff = 1; + if (getenv("FUZZ_NEARBY")) fuzz_nearby = 1; + + if (fuzz_nearby) { + + non_eff_bytes = (u8 *)ck_alloc(sizeof(u8) * len); + + // clean exec cksum + if (common_fuzz_stuff(afl, out_buf, len)) { return 0; } + prev_cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); + + } + + do { + + eff_round_continue = 0; + afl->stage_max = 32 * 1024; + + for (; afl->stage_cur < afl->stage_max && afl->stage_cur < len; + ++afl->stage_cur) { + + afl->stage_cur_byte = afl->stage_cur; + + if (!inf_eff_map[afl->stage_cur_byte] || + skip_eff_map[afl->stage_cur_byte]) + continue; + + if (is_det_timeout(before_det_time, 1)) { goto cleanup_skipdet; } + + u8 orig = out_buf[afl->stage_cur_byte], replace = rand_below(afl, 256); + + while (replace == orig) { + + replace = rand_below(afl, 256); + + } + + out_buf[afl->stage_cur_byte] = replace; + + before_skip_inf = afl->queued_items; + + if (common_fuzz_stuff(afl, out_buf, len)) { return 0; } + + out_buf[afl->stage_cur_byte] = orig; + + if (fuzz_nearby) { + + if (prev_cksum == + hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST)) { + + non_eff_bytes[afl->stage_cur_byte] = 1; + + } + + } + + if (afl->queued_items != before_skip_inf) { + + skip_eff_map[afl->stage_cur_byte] = 1; + afl->queue_cur->skipdet_e->quick_eff_bytes += 1; + + if (afl->stage_max < MAXIMUM_QUICK_EFF_EXECS) { afl->stage_max *= 2; } + + if (afl->stage_max == MAXIMUM_QUICK_EFF_EXECS && repeat_eff) + eff_round_continue = 1; + + } + + done_inf_map[afl->stage_cur_byte] = 1; + + } + + afl->stage_cur = 0; + done_eff = 1; + + if (++eff_round_done >= 8) break; + + } while (eff_round_continue); + + new_hit_cnt = afl->queued_items + afl->saved_crashes; + + afl->stage_finds[STAGE_QUICK] += new_hit_cnt - orig_hit_cnt; + afl->stage_cycles[STAGE_QUICK] += (afl->fsrv.total_execs - before_eff_execs); + +cleanup_skipdet: + + if (fuzz_nearby) { + + u8 *nearby_bytes = (u8 *)ck_alloc(sizeof(u8) * len); + + u32 i = 3; + while (i < len) { + + // assume DWORD size, from i - 3 -> i + 3 + if (skip_eff_map[i]) { + + u32 fill_length = (i + 3 < len) ? 7 : len - i + 2; + memset(nearby_bytes + i - 3, 1, fill_length); + i += 3; + + } else + + i += 1; + + } + + for (i = 0; i < len; i++) { + + if (nearby_bytes[i] && !non_eff_bytes[i]) skip_eff_map[i] = 1; + + } + + ck_free(nearby_bytes); + ck_free(non_eff_bytes); + + } + + if (done_eff) { + + afl->queue_cur->skipdet_e->continue_inf = 0; + afl->queue_cur->skipdet_e->done_eff = 1; + + } else { + + afl->queue_cur->skipdet_e->continue_inf = 1; + + } + + return 1; + +} + diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 7d6fdfb9..4467cae8 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -140,6 +140,14 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) { afl->fsrv.child_pid = -1; afl->fsrv.out_dir_fd = -1; + /* Init SkipDet */ + afl->skipdet_g = + (struct skipdet_global *)ck_alloc(sizeof(struct skipdet_global)); + afl->skipdet_g->inf_prof = + (struct inf_profile *)ck_alloc(sizeof(struct inf_profile)); + afl->havoc_prof = + (struct havoc_profile *)ck_alloc(sizeof(struct havoc_profile)); + init_mopt_globals(afl); list_append(&afl_states, afl); diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index deb28b7a..76577081 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -502,6 +502,44 @@ void maybe_update_plot_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, } +/* Log deterministic stage efficiency */ + +void plot_profile_data(afl_state_t *afl, struct queue_entry *q) { + + u64 current_ms = get_cur_time() - afl->start_time; + + u32 current_edges = count_non_255_bytes(afl, afl->virgin_bits); + double det_finding_rate = (double)afl->havoc_prof->total_det_edge * 100.0 / + (double)current_edges, + det_time_rate = (double)afl->havoc_prof->total_det_time * 100.0 / + (double)current_ms; + + u32 ndet_bits = 0; + for (u32 i = 0; i < afl->fsrv.map_size; i++) { + + if (afl->skipdet_g->virgin_det_bits[i]) ndet_bits += 1; + + } + + double det_fuzzed_rate = (double)ndet_bits * 100.0 / (double)current_edges; + + fprintf(afl->fsrv.det_plot_file, + "[%02lld:%02lld:%02lld] fuzz %d (%d), find %d/%d among %d(%02.2f) " + "and spend %lld/%lld(%02.2f), cover %02.2f yet, %d/%d undet bits, " + "continue %d.\n", + current_ms / 1000 / 3600, (current_ms / 1000 / 60) % 60, + (current_ms / 1000) % 60, afl->current_entry, q->fuzz_level, + afl->havoc_prof->edge_det_stage, afl->havoc_prof->edge_havoc_stage, + current_edges, det_finding_rate, + afl->havoc_prof->det_stage_time / 1000, + afl->havoc_prof->havoc_stage_time / 1000, det_time_rate, + det_fuzzed_rate, q->skipdet_e->undet_bits, + afl->skipdet_g->undet_bits_threshold, q->skipdet_e->continue_inf); + + fflush(afl->fsrv.det_plot_file); + +} + /* Check terminal dimensions after resize. */ static void check_term_size(afl_state_t *afl) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 8cf6c735..12d67fe7 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -170,7 +170,7 @@ static void usage(u8 *argv0, int more_help) { " -g minlength - set min length of generated fuzz input (default: 1)\n" " -G maxlength - set max length of generated fuzz input (default: " "%lu)\n" - " -D - enable deterministic fuzzing (once per queue entry)\n" + " -D - enable (a new) effective deterministic fuzzing\n" " -L minutes - use MOpt(imize) mode and set the time limit for " "entering the\n" " pacemaker mode (minutes of no new finds). 0 = " @@ -955,14 +955,20 @@ int main(int argc, char **argv_orig, char **envp) { break; - case 'D': /* enforce deterministic */ + case 'D': /* partial deterministic */ afl->skip_deterministic = 0; break; - case 'd': /* skip deterministic */ + case 'd': /* no deterministic */ - afl->skip_deterministic = 1; + // this is the default and currently a lot of infrastructure enforces + // it (e.g. clusterfuzz, fuzzbench) based on that this feature + // originally was bad performance wise. We now have a better + // implementation, hence if it is activated, we do not want to + // deactivate it by such setups. + + // afl->skip_deterministic = 1; break; case 'B': /* load bitmap */ @@ -1424,11 +1430,11 @@ int main(int argc, char **argv_orig, char **envp) { } #endif + + // silently disable deterministic mutation if custom mutators are used if (!afl->skip_deterministic && afl->afl_env.afl_custom_mutator_only) { - FATAL( - "Using -D determinstic fuzzing is incompatible with " - "AFL_CUSTOM_MUTATOR_ONLY!"); + afl->skip_deterministic = 1; } @@ -3031,6 +3037,11 @@ stop_fuzzing: if (frida_afl_preload) { ck_free(frida_afl_preload); } fclose(afl->fsrv.plot_file); + + #ifdef INTROSPECTION + fclose(afl->fsrv.det_plot_file); + #endif + destroy_queue(afl); destroy_extras(afl); destroy_custom_mutators(afl); diff --git a/src/afl-gotcpu.c b/src/afl-gotcpu.c index 4f851099..7aee2985 100644 --- a/src/afl-gotcpu.c +++ b/src/afl-gotcpu.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c index 7ce5de41..513c1ae9 100644 --- a/src/afl-ld-lto.c +++ b/src/afl-ld-lto.c @@ -9,7 +9,7 @@ Andrea Fioraldi Dominik Maier - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-sharedmem.c b/src/afl-sharedmem.c index a2c81586..daea8f46 100644 --- a/src/afl-sharedmem.c +++ b/src/afl-sharedmem.c @@ -11,7 +11,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 7a639cf6..20ba5a5e 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -12,7 +12,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-tmin.c b/src/afl-tmin.c index e7442d1d..4e5dab41 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -12,7 +12,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. -- cgit v1.2.3 From d85722a4f6329940545dd66bf16718d591fca681 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 3 Feb 2024 13:31:31 +0100 Subject: deterministic fuzzing and -z --- src/afl-fuzz-state.c | 2 +- src/afl-fuzz.c | 19 +++++++------------ 2 files changed, 8 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 4467cae8..ae327117 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -102,7 +102,7 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) { afl->stats_update_freq = 1; afl->stats_file_update_freq_msecs = STATS_UPDATE_SEC * 1000; afl->stats_avg_exec = 0; - afl->skip_deterministic = 1; + afl->skip_deterministic = 0; afl->sync_time = SYNC_TIME; afl->cmplog_lvl = 2; afl->min_length = 1; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 12d67fe7..b556b4b6 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -170,7 +170,6 @@ static void usage(u8 *argv0, int more_help) { " -g minlength - set min length of generated fuzz input (default: 1)\n" " -G maxlength - set max length of generated fuzz input (default: " "%lu)\n" - " -D - enable (a new) effective deterministic fuzzing\n" " -L minutes - use MOpt(imize) mode and set the time limit for " "entering the\n" " pacemaker mode (minutes of no new finds). 0 = " @@ -213,7 +212,8 @@ static void usage(u8 *argv0, int more_help) { " -F path - sync to a foreign fuzzer queue directory (requires " "-M, can\n" " be specified up to %u times)\n" - // " -d - skip deterministic fuzzing in -M mode\n" + " -z - skip the enhanced deterministic fuzzing\n" + " (note that the old -d and -D flags are ignored.)\n" " -T text - text banner to show on the screen\n" " -I command - execute this command/script when a new crash is " "found\n" @@ -955,20 +955,15 @@ int main(int argc, char **argv_orig, char **envp) { break; - case 'D': /* partial deterministic */ + case 'd': + case 'D': /* old deterministic */ - afl->skip_deterministic = 0; + WARNF("Parameters -d and -D are deprecated, a new enhanced deterministic fuzzing is active by default, to disable it use -z"); break; - case 'd': /* no deterministic */ + case 'z': /* no deterministic */ - // this is the default and currently a lot of infrastructure enforces - // it (e.g. clusterfuzz, fuzzbench) based on that this feature - // originally was bad performance wise. We now have a better - // implementation, hence if it is activated, we do not want to - // deactivate it by such setups. - - // afl->skip_deterministic = 1; + afl->skip_deterministic = 1; break; case 'B': /* load bitmap */ -- cgit v1.2.3 From dc151caa1839162e470e003837e630db6d5d543e Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 3 Feb 2024 15:53:54 +0100 Subject: add lto caller instrumentation --- src/afl-cc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 7d33b9f5..4d586ce8 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -2921,11 +2921,12 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { " AFL_LLVM_DOCUMENT_IDS: write all edge IDs and the corresponding " "functions\n" " into this file (LTO mode)\n" + " AFL_LLVM_LTO_CALLER: activate CALLER/CTX instrumentation\n" + " AFL_LLVM_LTO_CALLER_DEPTH: skip how many empty functions\n" " AFL_LLVM_LTO_DONTWRITEID: don't write the highest ID used to a " "global var\n" " AFL_LLVM_LTO_STARTID: from which ID to start counting from for " - "a " - "bb\n" + "a bb\n" " AFL_REAL_LD: use this lld linker instead of the compiled in " "path\n" " AFL_LLVM_LTO_SKIPINIT: don't inject initialization code " -- cgit v1.2.3 From 9fab7e892d4e2ba09305aac40392a4df598464c9 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 3 Feb 2024 16:48:38 +0100 Subject: new forkserver - server part --- src/afl-forkserver.c | 368 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 267 insertions(+), 101 deletions(-) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 0a77d61c..1f796e53 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -389,7 +389,7 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) { while (1) { uint32_t was_killed; - int status; + u32 status; /* Wait for parent by reading from the pipe. Exit if read fails. */ @@ -524,7 +524,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, volatile u8 *stop_soon_p, u8 debug_child_output) { int st_pipe[2], ctl_pipe[2]; - s32 status; + u32 status; s32 rlen; char *ignore_autodict = getenv("AFL_NO_AUTODICT"); @@ -1017,69 +1017,95 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if (rlen == 4) { + /* + * The new fork server model works like this: + * Client: sends "AFLx" in little endian, with x being the forkserver + * protocol version. + * Server: replies with XOR of the message or exits with an error if it + * is not a supported version. + * Client: sends 32 bit of options and then sends all parameters of + * the options, one after another, increasing by option number. + * Ends with "AFLx". + * After the initial protocol version confirmation the server does not + * send any data anymore - except a future option requires this. + */ + if (status >= 0x41464c00 && status <= 0x41464cff) { - FATAL( - "Target uses the new forkserver model, you need to switch to a newer " - "afl-fuzz too!"); + u32 version = status - 0x41464c00; - } + if (!version) { - if (!be_quiet) { OKF("All right - fork server is up."); } + FATAL( + "Fork server version is not assigned, this should not happen. " + "Recompile target."); - if (getenv("AFL_DEBUG")) { + } else if (version < FS_NEW_VERSION_MIN || version > FS_NEW_VERSION_MAX) { - ACTF("Extended forkserver functions received (%08x).", status); + FATAL( + "Fork server version is not not supported. Recompile the target."); - } + } - if ((status & FS_OPT_ERROR) == FS_OPT_ERROR) - report_error_and_exit(FS_OPT_GET_ERROR(status)); + status ^= 0xffffffff; + if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) { - if ((status & FS_OPT_ENABLED) == FS_OPT_ENABLED) { + FATAL("Writing to forkserver failed."); - // workaround for recent AFL++ versions - if ((status & FS_OPT_OLD_AFLPP_WORKAROUND) == FS_OPT_OLD_AFLPP_WORKAROUND) - status = (status & 0xf0ffffff); + } - if ((status & FS_OPT_NEWCMPLOG) == 0 && fsrv->cmplog_binary) { + if (!be_quiet) { - if (fsrv->qemu_mode || fsrv->frida_mode) { + OKF("All right - new fork server model v%u is up.", version); - report_error_and_exit(FS_ERROR_OLD_CMPLOG_QEMU); + } - } else { + rlen = read(fsrv->fsrv_st_fd, &status, 4); - report_error_and_exit(FS_ERROR_OLD_CMPLOG); + if (getenv("AFL_DEBUG")) { - } + ACTF("Forkserver options received: (%08x)", status); } - if ((status & FS_OPT_SNAPSHOT) == FS_OPT_SNAPSHOT) { + if ((status & FS_NEW_OPT_MAPSIZE)) { - fsrv->snapshot = 1; - if (!be_quiet) { ACTF("Using SNAPSHOT feature."); } + u32 tmp_map_size; + rlen = read(fsrv->fsrv_st_fd, &tmp_map_size, 4); - } + if (!fsrv->map_size) { fsrv->map_size = MAP_SIZE; } - if ((status & FS_OPT_SHDMEM_FUZZ) == FS_OPT_SHDMEM_FUZZ) { + fsrv->real_map_size = tmp_map_size; - if (fsrv->support_shmem_fuzz) { + if (tmp_map_size % 64) { - fsrv->use_shmem_fuzz = 1; - if (!be_quiet) { ACTF("Using SHARED MEMORY FUZZING feature."); } + tmp_map_size = (((tmp_map_size + 63) >> 6) << 6); + + } - if ((status & FS_OPT_AUTODICT) == 0 || ignore_autodict) { + if (!be_quiet) { ACTF("Target map size: %u", fsrv->real_map_size); } + if (tmp_map_size > fsrv->map_size) { - u32 send_status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ); - if (write(fsrv->fsrv_ctl_fd, &send_status, 4) != 4) { + FATAL( + "Target's coverage map size of %u is larger than the one this " + "AFL++ is set with (%u). Either set AFL_MAP_SIZE=%u and " + "restart " + " afl-fuzz, or change MAP_SIZE_POW2 in config.h and recompile " + "afl-fuzz", + tmp_map_size, fsrv->map_size, tmp_map_size); - FATAL("Writing to forkserver failed."); + } - } + fsrv->map_size = tmp_map_size; - } + } + + if ((status & FS_NEW_OPT_SHDMEM_FUZZ)) { + + if (fsrv->support_shmem_fuzz) { + + fsrv->use_shmem_fuzz = 1; + if (!be_quiet) { ACTF("Using SHARED MEMORY FUZZING feature."); } } else { @@ -1091,134 +1117,274 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } - if ((status & FS_OPT_MAPSIZE) == FS_OPT_MAPSIZE) { + if ((status & FS_NEW_OPT_AUTODICT)) { - u32 tmp_map_size = FS_OPT_GET_MAPSIZE(status); + u32 dict_size; + if (read(fsrv->fsrv_st_fd, &dict_size, 4) != 4) { - if (!fsrv->map_size) { fsrv->map_size = MAP_SIZE; } + FATAL("Reading from forkserver failed."); - fsrv->real_map_size = tmp_map_size; + } - if (tmp_map_size % 64) { + if (dict_size < 2 || dict_size > 0xffffff) { - tmp_map_size = (((tmp_map_size + 63) >> 6) << 6); + FATAL("Dictionary has an illegal size: %d", dict_size); } - if (!be_quiet) { ACTF("Target map size: %u", fsrv->real_map_size); } - if (tmp_map_size > fsrv->map_size) { + u32 offset = 0, count = 0; + u8 *dict = ck_alloc(dict_size); + if (dict == NULL) { - FATAL( - "Target's coverage map size of %u is larger than the one this " - "AFL++ is set with (%u). Either set AFL_MAP_SIZE=%u and restart " - " afl-fuzz, or change MAP_SIZE_POW2 in config.h and recompile " - "afl-fuzz", - tmp_map_size, fsrv->map_size, tmp_map_size); + FATAL("Could not allocate %u bytes of autodictionary memory", + dict_size); } - fsrv->map_size = tmp_map_size; + while (dict_size != 0) { + + rlen = read(fsrv->fsrv_st_fd, dict + offset, dict_size); + if (rlen > 0) { + + dict_size -= rlen; + offset += rlen; + + } else { + + FATAL( + "Reading autodictionary fail at position %u with %u bytes " + "left.", + offset, dict_size); + + } + + } + + offset = 0; + while (offset < dict_size && (u8)dict[offset] + offset < dict_size) { + + fsrv->add_extra_func(fsrv->afl_ptr, dict + offset + 1, + (u8)dict[offset]); + offset += (1 + dict[offset]); + count++; + + } + + if (!be_quiet) { ACTF("Loaded %u autodictionary entries", count); } + ck_free(dict); } - if ((status & FS_OPT_AUTODICT) == FS_OPT_AUTODICT) { + u32 status2; + rlen = read(fsrv->fsrv_st_fd, &status2, 4); - if (!ignore_autodict) { + if (status2 != status) { FATAL("Error in forkserver communication"); } - if (fsrv->add_extra_func == NULL || fsrv->afl_ptr == NULL) { + } else { - // this is not afl-fuzz - or it is cmplog - we deny and return - if (fsrv->use_shmem_fuzz) { + WARNF( + "Old fork server model is used by the target, this still works " + "though."); - status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ); + if (!be_quiet) { OKF("All right - old fork server is up."); } - } else { + if (getenv("AFL_DEBUG")) { - status = (FS_OPT_ENABLED); + ACTF("Extended forkserver functions received (%08x).", status); - } + } - if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) { + if ((status & FS_OPT_ERROR) == FS_OPT_ERROR) + report_error_and_exit(FS_OPT_GET_ERROR(status)); - FATAL("Writing to forkserver failed."); + if ((status & FS_OPT_ENABLED) == FS_OPT_ENABLED) { - } + // workaround for recent AFL++ versions + if ((status & FS_OPT_OLD_AFLPP_WORKAROUND) == + FS_OPT_OLD_AFLPP_WORKAROUND) + status = (status & 0xf0ffffff); + + if ((status & FS_OPT_NEWCMPLOG) == 0 && fsrv->cmplog_binary) { + + if (fsrv->qemu_mode || fsrv->frida_mode) { + + report_error_and_exit(FS_ERROR_OLD_CMPLOG_QEMU); + + } else { - return; + report_error_and_exit(FS_ERROR_OLD_CMPLOG); } - if (!be_quiet) { ACTF("Using AUTODICT feature."); } + } + + if ((status & FS_OPT_SNAPSHOT) == FS_OPT_SNAPSHOT) { + + fsrv->snapshot = 1; + if (!be_quiet) { ACTF("Using SNAPSHOT feature."); } + + } + + if ((status & FS_OPT_SHDMEM_FUZZ) == FS_OPT_SHDMEM_FUZZ) { + + if (fsrv->support_shmem_fuzz) { + + fsrv->use_shmem_fuzz = 1; + if (!be_quiet) { ACTF("Using SHARED MEMORY FUZZING feature."); } + + if ((status & FS_OPT_AUTODICT) == 0 || ignore_autodict) { - if (fsrv->use_shmem_fuzz) { + u32 send_status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ); + if (write(fsrv->fsrv_ctl_fd, &send_status, 4) != 4) { - status = (FS_OPT_ENABLED | FS_OPT_AUTODICT | FS_OPT_SHDMEM_FUZZ); + FATAL("Writing to forkserver failed."); + + } + + } } else { - status = (FS_OPT_ENABLED | FS_OPT_AUTODICT); + FATAL( + "Target requested sharedmem fuzzing, but we failed to enable " + "it."); } - if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) { + } - FATAL("Writing to forkserver failed."); + if ((status & FS_OPT_MAPSIZE) == FS_OPT_MAPSIZE) { - } + u32 tmp_map_size = FS_OPT_GET_MAPSIZE(status); - if (read(fsrv->fsrv_st_fd, &status, 4) != 4) { + if (!fsrv->map_size) { fsrv->map_size = MAP_SIZE; } - FATAL("Reading from forkserver failed."); + fsrv->real_map_size = tmp_map_size; + + if (tmp_map_size % 64) { + + tmp_map_size = (((tmp_map_size + 63) >> 6) << 6); } - if (status < 2 || (u32)status > 0xffffff) { + if (!be_quiet) { ACTF("Target map size: %u", fsrv->real_map_size); } + if (tmp_map_size > fsrv->map_size) { - FATAL("Dictionary has an illegal size: %d", status); + FATAL( + "Target's coverage map size of %u is larger than the one this " + "AFL++ is set with (%u). Either set AFL_MAP_SIZE=%u and " + "restart " + " afl-fuzz, or change MAP_SIZE_POW2 in config.h and recompile " + "afl-fuzz", + tmp_map_size, fsrv->map_size, tmp_map_size); } - u32 offset = 0, count = 0; - u32 len = status; - u8 *dict = ck_alloc(len); - if (dict == NULL) { + fsrv->map_size = tmp_map_size; + + } - FATAL("Could not allocate %u bytes of autodictionary memory", len); + if ((status & FS_OPT_AUTODICT) == FS_OPT_AUTODICT) { - } + if (!ignore_autodict) { - while (len != 0) { + if (fsrv->add_extra_func == NULL || fsrv->afl_ptr == NULL) { - rlen = read(fsrv->fsrv_st_fd, dict + offset, len); - if (rlen > 0) { + // this is not afl-fuzz - or it is cmplog - we deny and return + if (fsrv->use_shmem_fuzz) { - len -= rlen; - offset += rlen; + status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ); + + } else { + + status = (FS_OPT_ENABLED); + + } + + if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) { + + FATAL("Writing to forkserver failed."); + + } + + return; + + } + + if (!be_quiet) { ACTF("Using AUTODICT feature."); } + + if (fsrv->use_shmem_fuzz) { + + status = (FS_OPT_ENABLED | FS_OPT_AUTODICT | FS_OPT_SHDMEM_FUZZ); } else { - FATAL( - "Reading autodictionary fail at position %u with %u bytes " - "left.", - offset, len); + status = (FS_OPT_ENABLED | FS_OPT_AUTODICT); } - } + if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) { - offset = 0; - while (offset < (u32)status && - (u8)dict[offset] + offset < (u32)status) { + FATAL("Writing to forkserver failed."); - fsrv->add_extra_func(fsrv->afl_ptr, dict + offset + 1, - (u8)dict[offset]); - offset += (1 + dict[offset]); - count++; + } - } + if (read(fsrv->fsrv_st_fd, &status, 4) != 4) { - if (!be_quiet) { ACTF("Loaded %u autodictionary entries", count); } - ck_free(dict); + FATAL("Reading from forkserver failed."); + + } + + if (status < 2 || (u32)status > 0xffffff) { + + FATAL("Dictionary has an illegal size: %d", status); + + } + + u32 offset = 0, count = 0; + u32 len = status; + u8 *dict = ck_alloc(len); + if (dict == NULL) { + + FATAL("Could not allocate %u bytes of autodictionary memory", + len); + + } + + while (len != 0) { + + rlen = read(fsrv->fsrv_st_fd, dict + offset, len); + if (rlen > 0) { + + len -= rlen; + offset += rlen; + + } else { + + FATAL( + "Reading autodictionary fail at position %u with %u bytes " + "left.", + offset, len); + + } + + } + + offset = 0; + while (offset < (u32)status && + (u8)dict[offset] + offset < (u32)status) { + + fsrv->add_extra_func(fsrv->afl_ptr, dict + offset + 1, + (u8)dict[offset]); + offset += (1 + dict[offset]); + count++; + + } + + if (!be_quiet) { ACTF("Loaded %u autodictionary entries", count); } + ck_free(dict); + + } } -- cgit v1.2.3 From 27338fcef121c7700a1e2e99cb31cb7106159293 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 3 Feb 2024 18:27:01 +0100 Subject: new forkserver - client side --- src/afl-forkserver.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 1f796e53..a3a869d7 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -1030,6 +1030,12 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, * send any data anymore - except a future option requires this. */ + if ((status & FS_NEW_ERROR) == FS_NEW_ERROR) { + + report_error_and_exit(status & 0x0000ffff); + + } + if (status >= 0x41464c00 && status <= 0x41464cff) { u32 version = status - 0x41464c00; @@ -1047,6 +1053,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } + u32 keep = status; status ^= 0xffffffff; if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) { @@ -1064,7 +1071,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if (getenv("AFL_DEBUG")) { - ACTF("Forkserver options received: (%08x)", status); + ACTF("Forkserver options received: (0x%08x)", status); } @@ -1178,7 +1185,11 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, u32 status2; rlen = read(fsrv->fsrv_st_fd, &status2, 4); - if (status2 != status) { FATAL("Error in forkserver communication"); } + if (status2 != keep) { + + FATAL("Error in forkserver communication (%08x=>%08x)", keep, status2); + + } } else { -- cgit v1.2.3 From c77709cdd9b50832ed537dfd65d30bc7ffa79e7b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 4 Feb 2024 16:03:12 +0100 Subject: add U256/32byte support --- src/afl-forkserver.c | 10 ++++++++++ src/afl-fuzz-redqueen.c | 10 +++++----- src/afl-fuzz.c | 6 ++++-- 3 files changed, 19 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index a3a869d7..c5184639 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -1105,6 +1105,10 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, fsrv->map_size = tmp_map_size; + } else { + + fsrv->real_map_size = fsrv->map_size = MAP_SIZE; + } if ((status & FS_NEW_OPT_SHDMEM_FUZZ)) { @@ -1208,6 +1212,12 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if ((status & FS_OPT_ERROR) == FS_OPT_ERROR) report_error_and_exit(FS_OPT_GET_ERROR(status)); + if (fsrv->cmplog_binary) { + + FATAL("Target was recompiled with outdated CMPLOG, recompile it!\n"); + + } + if ((status & FS_OPT_ENABLED) == FS_OPT_ENABLED) { // workaround for recent AFL++ versions diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index eead7a8b..eb96de68 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -11,7 +11,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2024 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -2219,15 +2219,15 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, } - if (l0 == 0 || l1 == 0 || ol0 == 0 || ol1 == 0 || l0 > 31 || l1 > 31 || - ol0 > 31 || ol1 > 31) { + if (l0 == 0 || l1 == 0 || ol0 == 0 || ol1 == 0 || l0 > 32 || l1 > 32 || + ol0 > 32 || ol1 > 32) { l0 = ol0 = hshape; } u8 lmax = MAX(l0, ol0); - u8 save[40]; + u8 save[80]; u32 saved_idx = idx, pre, from = 0, to = 0, i, j; u32 its_len = MIN(MIN(lmax, hshape), len - idx); its_len = MIN(its_len, taint_len); @@ -2330,7 +2330,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, u32 tob64 = 0, fromb64 = 0; u32 from_0 = 0, from_x = 0, from_X = 0, from_slash = 0, from_up = 0; u32 to_0 = 0, to_x = 0, to_slash = 0, to_up = 0; - u8 xor_val[32], arith_val[32], tmp[48]; + u8 xor_val[64], arith_val[64], tmp[64]; idx = saved_idx; its_len = saved_its_len; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index b556b4b6..34268113 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -956,9 +956,11 @@ int main(int argc, char **argv_orig, char **envp) { break; case 'd': - case 'D': /* old deterministic */ + case 'D': /* old deterministic */ - WARNF("Parameters -d and -D are deprecated, a new enhanced deterministic fuzzing is active by default, to disable it use -z"); + WARNF( + "Parameters -d and -D are deprecated, a new enhanced deterministic " + "fuzzing is active by default, to disable it use -z"); break; case 'z': /* no deterministic */ -- cgit v1.2.3 From 6d209ce045c651089e4e55d7bb9995b496a378c0 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 4 Feb 2024 16:16:32 +0100 Subject: fix -z --- src/afl-fuzz-stats.c | 2 +- src/afl-fuzz.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 76577081..b6900506 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -1112,7 +1112,7 @@ void show_stats_normal(afl_state_t *afl) { } else if (likely(afl->skip_deterministic)) { - strcpy(tmp, "disabled (default, enable with -D)"); + strcpy(tmp, "disabled (-z switch used)"); } else { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 34268113..abb1d82a 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -539,7 +539,7 @@ int main(int argc, char **argv_orig, char **envp) { // still available: HjJkKqruvwz while ((opt = getopt(argc, argv, "+a:Ab:B:c:CdDe:E:f:F:g:G:hi:I:l:L:m:M:nNo:Op:P:QRs:S:t:" - "T:UV:WXx:YZ")) > 0) { + "T:UV:WXx:YzZ")) > 0) { switch (opt) { -- cgit v1.2.3 From 40df85d1e6fb80e9d641064e645a48b623aee681 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 5 Feb 2024 15:05:46 +0100 Subject: adjust cmplog header --- src/afl-fuzz-redqueen.c | 43 ++++++++++++-- src/hashmap.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 186 insertions(+), 6 deletions(-) create mode 100644 src/hashmap.c (limited to 'src') diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index eb96de68..bc83c9ed 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -87,6 +87,11 @@ static u32 hshape; static u64 screen_update; static u64 last_update; +// hashmap functions +void hashmap_reset(); +bool hashmap_search_and_add(uint8_t type, uint64_t key); +bool hashmap_search_and_add_ptr(uint8_t type, u8 *key); + static struct range *add_range(struct range *ranges, u32 start, u32 end) { struct range *r = ck_alloc_nozero(sizeof(struct range)); @@ -795,7 +800,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, u64 *o_buf_64 = (u64 *)&orig_buf[idx]; u32 *o_buf_32 = (u32 *)&orig_buf[idx]; u16 *o_buf_16 = (u16 *)&orig_buf[idx]; - u8 *o_buf_8 = &orig_buf[idx]; + // u8 *o_buf_8 = &orig_buf[idx]; u32 its_len = MIN(len - idx, taint_len); @@ -836,6 +841,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, // necessary for preventing heap access overflow bytes = MIN(bytes, len - idx); + if (unlikely(bytes <= 1)) { return 0; } // reverse atoi()/strnu?toll() is expensive, so we only to it in lvl 3 if (afl->cmplog_enable_transform && (lvl & LVL3)) { @@ -1266,6 +1272,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, } + /* if (*status != 1) { // u8 // if (its_len >= 1) @@ -1290,6 +1297,8 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, } + */ + } // If 'S' is set for cmplog mode then we try a scale encoding of the value. @@ -1881,6 +1890,8 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, hshape = SHAPE_BYTES(h->shape); + if (hshape < 2) { return 0; } + if (h->hits > CMP_MAP_H) { loggeds = CMP_MAP_H; @@ -1906,8 +1917,6 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, #endif - if (hshape < 2) { return 0; } - for (i = 0; i < loggeds; ++i) { struct cmp_operands *o = &afl->shm.cmp_map->log[key][i]; @@ -1945,6 +1954,16 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, } + // TODO: add attribute? not sure + if (hshape <= 8 && !hashmap_search_and_add(hshape - 1, o->v0) && + !hashmap_search_and_add(hshape - 1, orig_o->v0) && + !hashmap_search_and_add(hshape - 1, o->v1) && + !hashmap_search_and_add(hshape - 1, orig_o->v1)) { + + continue; + + } + #ifdef _DEBUG fprintf(stderr, "Handling: %llx->%llx vs %llx->%llx attr=%u shape=%u\n", orig_o->v0, o->v0, orig_o->v1, o->v1, h->attribute, hshape); @@ -2615,12 +2634,13 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, } - memcpy(buf + idx, tmp, hlen + 1 + off); + u32 tmp_l = hlen + 1 + off; + memcpy(buf + idx, tmp, tmp_l); if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } - tmp[hlen + 1 + off] = 0; + tmp[tmp_l] = 0; // fprintf(stderr, "RTN ATTEMPT idx=%u len=%u fromhex %u %s %s result // %u\n", idx, len, fromhex, tmp, repl, *status); - memcpy(buf + idx, save, hlen + 1 + off); + memcpy(buf + idx, save, tmp_l); } @@ -2755,6 +2775,15 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, fprintf(stderr, "\n"); #endif + if (hshape <= 8 && !hashmap_search_and_add_ptr(hshape - 1, o->v0) && + !hashmap_search_and_add_ptr(hshape - 1, orig_o->v0) && + !hashmap_search_and_add_ptr(hshape - 1, o->v1) && + !hashmap_search_and_add_ptr(hshape - 1, orig_o->v1)) { + + continue; + + } + t = taint; while (t->next) { @@ -3021,6 +3050,8 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) { // Start insertion loop + hashmap_reset(); + u64 orig_hit_cnt, new_hit_cnt; u64 orig_execs = afl->fsrv.total_execs; orig_hit_cnt = afl->queued_items + afl->saved_crashes; diff --git a/src/hashmap.c b/src/hashmap.c new file mode 100644 index 00000000..a0a9283c --- /dev/null +++ b/src/hashmap.c @@ -0,0 +1,149 @@ +#include +#include +#include +#include +#include "types.h" +#define TABLE_SIZE 10007 // Use a prime number for better distribution + +typedef struct HashNode { + + uint64_t key; + struct HashNode *next; + +} HashNode; + +typedef struct HashMap { + + HashNode **table; + +} HashMap; + +static HashMap *_hashmap; + +void hashmap_reset() { + + if (unlikely(!_hashmap)) { + + _hashmap = (HashMap *)malloc(sizeof(HashMap)); + _hashmap->table = (HashNode **)malloc(sizeof(HashNode *) * TABLE_SIZE); + memset((char *)_hashmap->table, 0, sizeof(HashNode *) * TABLE_SIZE); + + } else { + + for (int i = 0; i < TABLE_SIZE; i++) { + + HashNode *node = _hashmap->table[i]; + while (node) { + + HashNode *temp = node; + node = node->next; + free(temp); + + } + + } + + memset((char *)_hashmap->table, 0, sizeof(HashNode *) * TABLE_SIZE); + + } + +} + +static inline unsigned int hash(uint64_t key) { + + return key % TABLE_SIZE; + +} + +// type must be below 8 +bool hashmap_search_and_add(uint8_t type, uint64_t key) { + + if (unlikely(type >= 8)) return false; + uint64_t val = (key & 0xf8ffffffffffffff) + (type << 56); + unsigned int index = hash(val); + HashNode *node = _hashmap->table[index]; + while (node) { + + if (node->key == val) return true; + node = node->next; + + } + + // not found so add it + node = (HashNode *)malloc(sizeof(HashNode)); + node->key = val; + node->next = _hashmap->table[index]; + _hashmap->table[index] = node; + + return false; + +} + +// type must be below 8 +bool hashmap_search_and_add_ptr(uint8_t type, u8 *key) { + + if (unlikely(type >= 8)) return false; + uint64_t key_t = 0; + memcpy(((char *)key_t) + (7 - type), key, type + 1); + return hashmap_search_and_add(type, key_t); + +} + +/* below is not used */ + +void hashmap_insert(uint64_t key) { + + unsigned int index = hash(key); + HashNode *node = (HashNode *)malloc(sizeof(HashNode)); + node->key = key; + node->next = _hashmap->table[index]; + _hashmap->table[index] = node; + +} + +bool hashmap_search(uint64_t key) { + + unsigned int index = hash(key); + HashNode *node = _hashmap->table[index]; + while (node) { + + if (node->key == key) return true; + node = node->next; + + } + + return false; + +} + +void delete(uint64_t key) { + + unsigned int index = hash(key); + HashNode *prev = NULL, *node = _hashmap->table[index]; + while (node) { + + if (node->key == key) { + + if (prev) + prev->next = node->next; + else + _hashmap->table[index] = node->next; + free(node); + return; + + } + + prev = node; + node = node->next; + + } + +} + +void freeHashMap(HashMap *map) { + + free(_hashmap->table); + free(map); + +} + -- cgit v1.2.3 From 023fc19ce04bffcbd623e27a1f2d1810c3ec0c3c Mon Sep 17 00:00:00 2001 From: Davide Quarta Date: Mon, 5 Feb 2024 18:26:46 +0100 Subject: better replay mode error handling, added replay mode documentation, code formatting --- src/afl-forkserver.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index f8dd783f..36e46444 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -1593,7 +1593,7 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, #ifdef AFL_PERSISTENT_RECORD fsrv_run_result_t retval = FSRV_RUN_OK; - char *persistent_out_fmt; + char *persistent_out_fmt; #endif #ifdef __linux__ @@ -1803,6 +1803,7 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, persistent_out_fmt = "%s/hangs/RECORD:%06u,cnt:%06u"; goto store_persistent_record; #endif + } /* Did we crash? @@ -1841,7 +1842,7 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, #ifdef AFL_PERSISTENT_RECORD store_persistent_record: - if (unlikely(retval == FSRV_RUN_CRASH || retval == FSRV_RUN_TMOUT) && + if (unlikely(retval == FSRV_RUN_CRASH || retval == FSRV_RUN_TMOUT) && unlikely(fsrv->persistent_record)) { char fn[PATH_MAX]; -- cgit v1.2.3 From 698f1e272b8738cd1145ed687861fa5664f14c9b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 6 Feb 2024 09:34:21 +0100 Subject: fix hashmap test --- src/afl-fuzz-redqueen.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index bc83c9ed..03a25903 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -1955,10 +1955,10 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, } // TODO: add attribute? not sure - if (hshape <= 8 && !hashmap_search_and_add(hshape - 1, o->v0) && - !hashmap_search_and_add(hshape - 1, orig_o->v0) && - !hashmap_search_and_add(hshape - 1, o->v1) && - !hashmap_search_and_add(hshape - 1, orig_o->v1)) { + if (hshape <= 8 && hashmap_search_and_add(hshape - 1, o->v0) && + hashmap_search_and_add(hshape - 1, orig_o->v0) && + hashmap_search_and_add(hshape - 1, o->v1) && + hashmap_search_and_add(hshape - 1, orig_o->v1)) { continue; @@ -2775,10 +2775,10 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, fprintf(stderr, "\n"); #endif - if (hshape <= 8 && !hashmap_search_and_add_ptr(hshape - 1, o->v0) && - !hashmap_search_and_add_ptr(hshape - 1, orig_o->v0) && - !hashmap_search_and_add_ptr(hshape - 1, o->v1) && - !hashmap_search_and_add_ptr(hshape - 1, orig_o->v1)) { + if (hshape <= 8 && hashmap_search_and_add_ptr(hshape - 1, o->v0) && + hashmap_search_and_add_ptr(hshape - 1, orig_o->v0) && + hashmap_search_and_add_ptr(hshape - 1, o->v1) && + hashmap_search_and_add_ptr(hshape - 1, orig_o->v1)) { continue; -- cgit v1.2.3 From a7fd84e186bf0151c9495817db1a2e0173344e9e Mon Sep 17 00:00:00 2001 From: Davide Quarta Date: Tue, 6 Feb 2024 21:25:40 +0100 Subject: fix typo --- src/afl-forkserver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 36e46444..08368061 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -1689,7 +1689,7 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, } -#ifdef AFL_eERSISTENT_RECORD +#ifdef AFL_PERSISTENT_RECORD // end of persistent loop? if (unlikely(fsrv->persistent_record && fsrv->persistent_record_pid != fsrv->child_pid)) { -- cgit v1.2.3 From ea0ea88ed3eb7c8cdc313284a6d434dcf01d7455 Mon Sep 17 00:00:00 2001 From: Davide Quarta Date: Wed, 7 Feb 2024 12:00:01 +0100 Subject: add conditional check for persistent record mode on forkserver handling of hang/crash --- src/afl-forkserver.c | 74 +++++++++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 08368061..6b97f737 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -1796,14 +1796,19 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, fsrv->last_kill_signal = fsrv->child_kill_signal; -#ifndef AFL_PERSISTENT_RECORD - return FSRV_RUN_TMOUT; -#else - retval = FSRV_RUN_TMOUT; - persistent_out_fmt = "%s/hangs/RECORD:%06u,cnt:%06u"; - goto store_persistent_record; +#ifdef AFL_PERSISTENT_RECORD + if (unlikely(fsrv->persistent_record)) { + + retval = FSRV_RUN_TMOUT; + persistent_out_fmt = "%s/hangs/RECORD:%06u,cnt:%06u"; + goto store_persistent_record; + + } + #endif + return FSRV_RUN_TMOUT; + } /* Did we crash? @@ -1827,53 +1832,56 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, fsrv->last_kill_signal = WIFSIGNALED(fsrv->child_status) ? WTERMSIG(fsrv->child_status) : 0; -#ifndef AFL_PERSISTENT_RECORD - return FSRV_RUN_CRASH; -#else - retval = FSRV_RUN_CRASH; - persistent_out_fmt = "%s/crashes/RECORD:%06u,cnt:%06u"; - goto store_persistent_record; +#ifdef AFL_PERSISTENT_RECORD + if (unlikely(fsrv->persistent_record)) { + + retval = FSRV_RUN_CRASH; + persistent_out_fmt = "%s/crashes/RECORD:%06u,cnt:%06u"; + goto store_persistent_record; + + } + #endif + return FSRV_RUN_CRASH; + } /* success :) */ return FSRV_RUN_OK; #ifdef AFL_PERSISTENT_RECORD -store_persistent_record: - if (unlikely(retval == FSRV_RUN_CRASH || retval == FSRV_RUN_TMOUT) && - unlikely(fsrv->persistent_record)) { - - char fn[PATH_MAX]; - u32 i, writecnt = 0; - for (i = 0; i < fsrv->persistent_record; ++i) { +store_persistent_record: { - u32 entry = (i + fsrv->persistent_record_idx) % fsrv->persistent_record; - u8 *data = fsrv->persistent_record_data[entry]; - u32 len = fsrv->persistent_record_len[entry]; - if (likely(len && data)) { + char fn[PATH_MAX]; + u32 i, writecnt = 0; + for (i = 0; i < fsrv->persistent_record; ++i) { - snprintf(fn, sizeof(fn), persistent_out_fmt, - fsrv->persistent_record_dir, fsrv->persistent_record_cnt, - writecnt++); - int fd = open(fn, O_CREAT | O_TRUNC | O_WRONLY, 0644); - if (fd >= 0) { + u32 entry = (i + fsrv->persistent_record_idx) % fsrv->persistent_record; + u8 *data = fsrv->persistent_record_data[entry]; + u32 len = fsrv->persistent_record_len[entry]; + if (likely(len && data)) { - ck_write(fd, data, len, fn); - close(fd); + snprintf(fn, sizeof(fn), persistent_out_fmt, fsrv->persistent_record_dir, + fsrv->persistent_record_cnt, writecnt++); + int fd = open(fn, O_CREAT | O_TRUNC | O_WRONLY, 0644); + if (fd >= 0) { - } + ck_write(fd, data, len, fn); + close(fd); } } - ++fsrv->persistent_record_cnt; - } + ++fsrv->persistent_record_cnt; + return retval; + +} + #endif } -- cgit v1.2.3 From 038fef962c3d85fe7e37fcd8717270654f927881 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 8 Feb 2024 12:46:00 +0100 Subject: performance --- src/afl-fuzz.c | 4 ++++ src/afl-performance.c | 9 +++++++++ 2 files changed, 13 insertions(+) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index ea8f1423..48e32996 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -401,6 +401,10 @@ static void usage(u8 *argv0, int more_help) { SAYF("Compiled with _AFL_DOCUMENT_MUTATIONS.\n"); #endif +#ifdef _AFL_SPECIAL_PERFORMANCE + SAYF("Compiled with special performance options for this specific system, it might not work on other platforms!\n"); +#endif + SAYF("For additional help please consult %s/README.md :)\n\n", doc_path); exit(1); diff --git a/src/afl-performance.c b/src/afl-performance.c index 07c1b527..22cf4dec 100644 --- a/src/afl-performance.c +++ b/src/afl-performance.c @@ -2,9 +2,18 @@ #include "afl-fuzz.h" #include "types.h" +#ifdef _HAVE_AVX2 +#define T1HA0_AESNI_AVAILABLE 1 +#define T1HA_USE_FAST_ONESHOT_READ 1 +#define T1HA_USE_INDIRECT_FUNCTIONS 1 +#define T1HA_IA32AES_NAME XXH3_64bits +#include "t1ha0_ia32aes_b.h" +#else #define XXH_INLINE_ALL #include "xxhash.h" #undef XXH_INLINE_ALL +#endif + void rand_set_seed(afl_state_t *afl, s64 init_seed) { -- cgit v1.2.3 From c23bbddde97d81fdb27351bade8f74fe71e49c21 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 8 Feb 2024 14:31:36 +0100 Subject: workaround for MOpt bug with -S --- src/afl-fuzz.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 48e32996..85feabe6 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1236,6 +1236,7 @@ int main(int argc, char **argv_orig, char **envp) { } + afl->old_seed_selection = 1; u64 limit_time_puppet2 = afl->limit_time_puppet * 60 * 1000; if ((s32)limit_time_puppet2 < afl->limit_time_puppet) { -- cgit v1.2.3 From eaf4a29930fb5a397716cb34db71f1f14530923a Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 8 Feb 2024 14:54:10 +0100 Subject: make redqueen hashmap not default --- src/afl-fuzz-redqueen.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src') diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 03a25903..3342445a 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -29,6 +29,7 @@ #include "cmplog.h" // #define _DEBUG +// #define USE_HASHMAP // #define CMPLOG_INTROSPECTION // CMP attribute enum @@ -87,10 +88,12 @@ static u32 hshape; static u64 screen_update; static u64 last_update; +#ifdef USE_HASHMAP // hashmap functions void hashmap_reset(); bool hashmap_search_and_add(uint8_t type, uint64_t key); bool hashmap_search_and_add_ptr(uint8_t type, u8 *key); +#endif static struct range *add_range(struct range *ranges, u32 start, u32 end) { @@ -1954,6 +1957,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, } +#ifdef USE_HASHMAP // TODO: add attribute? not sure if (hshape <= 8 && hashmap_search_and_add(hshape - 1, o->v0) && hashmap_search_and_add(hshape - 1, orig_o->v0) && @@ -1963,6 +1967,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, continue; } +#endif #ifdef _DEBUG fprintf(stderr, "Handling: %llx->%llx vs %llx->%llx attr=%u shape=%u\n", @@ -2775,6 +2780,7 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, fprintf(stderr, "\n"); #endif +#ifdef USE_HASHMAP if (hshape <= 8 && hashmap_search_and_add_ptr(hshape - 1, o->v0) && hashmap_search_and_add_ptr(hshape - 1, orig_o->v0) && hashmap_search_and_add_ptr(hshape - 1, o->v1) && @@ -2783,6 +2789,7 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, continue; } +#endif t = taint; while (t->next) { @@ -3050,7 +3057,9 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) { // Start insertion loop +#ifdef USE_HASHMAP hashmap_reset(); +#endif u64 orig_hit_cnt, new_hit_cnt; u64 orig_execs = afl->fsrv.total_execs; -- cgit v1.2.3 From 369fce9c85bf3b850a7109e4604fee71f694d2cb Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 8 Feb 2024 15:13:46 +0100 Subject: code format --- src/afl-fuzz-redqueen.c | 2 ++ src/afl-fuzz.c | 4 +++- src/afl-performance.c | 17 ++++++++--------- 3 files changed, 13 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 3342445a..be41d6c4 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -1967,6 +1967,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, continue; } + #endif #ifdef _DEBUG @@ -2789,6 +2790,7 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, continue; } + #endif t = taint; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 7c47f060..9c89b2a1 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -402,7 +402,9 @@ static void usage(u8 *argv0, int more_help) { #endif #ifdef _AFL_SPECIAL_PERFORMANCE - SAYF("Compiled with special performance options for this specific system, it might not work on other platforms!\n"); + SAYF( + "Compiled with special performance options for this specific system, it " + "might not work on other platforms!\n"); #endif SAYF("For additional help please consult %s/README.md :)\n\n", doc_path); diff --git a/src/afl-performance.c b/src/afl-performance.c index 22cf4dec..f730ca53 100644 --- a/src/afl-performance.c +++ b/src/afl-performance.c @@ -3,18 +3,17 @@ #include "types.h" #ifdef _HAVE_AVX2 -#define T1HA0_AESNI_AVAILABLE 1 -#define T1HA_USE_FAST_ONESHOT_READ 1 -#define T1HA_USE_INDIRECT_FUNCTIONS 1 -#define T1HA_IA32AES_NAME XXH3_64bits -#include "t1ha0_ia32aes_b.h" + #define T1HA0_AESNI_AVAILABLE 1 + #define T1HA_USE_FAST_ONESHOT_READ 1 + #define T1HA_USE_INDIRECT_FUNCTIONS 1 + #define T1HA_IA32AES_NAME XXH3_64bits + #include "t1ha0_ia32aes_b.h" #else -#define XXH_INLINE_ALL -#include "xxhash.h" -#undef XXH_INLINE_ALL + #define XXH_INLINE_ALL + #include "xxhash.h" + #undef XXH_INLINE_ALL #endif - void rand_set_seed(afl_state_t *afl, s64 init_seed) { afl->init_seed = init_seed; -- cgit v1.2.3 From 88e41f01c839ed5c46882222ad7e1f5c3e7d9e20 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 8 Feb 2024 15:28:19 +0100 Subject: env fix --- src/afl-cc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 4d586ce8..3a32a0d1 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -828,7 +828,7 @@ static void instrument_mode_old_environ(aflcc_state_t *aflcc) { } if (getenv("AFL_LLVM_CTX")) aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CTX; - if (getenv("AFL_LLVM_CALLER")) + if (getenv("AFL_LLVM_CALLER") || getenv("AFL_LLVM_LTO_CALLER") || getenv("AFL_LLVM_LTO_CTX")) aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CALLER; if (getenv("AFL_LLVM_NGRAM_SIZE")) { -- cgit v1.2.3 From f2b7357ff3efedca53a7cd856469b439c2e547ef Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 9 Feb 2024 13:09:16 +0100 Subject: fixes --- src/afl-forkserver.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 7253e6d7..1d42adf5 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -1197,9 +1197,17 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } else { - WARNF( - "Old fork server model is used by the target, this still works " - "though."); + if (!fsrv->qemu_mode && !fsrv->cs_mode +#ifdef __linux__ + && !fsrv->nyx_mode +#endif + ) { + + WARNF( + "Old fork server model is used by the target, this still works " + "though."); + + } if (!be_quiet) { OKF("All right - old fork server is up."); } -- cgit v1.2.3 From 07bc202e0ad940e0cc7c8770f69ceb32ed851384 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 9 Feb 2024 13:51:05 +0100 Subject: fixes --- src/afl-forkserver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 1d42adf5..8853458a 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -1222,7 +1222,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if (fsrv->cmplog_binary) { - FATAL("Target was recompiled with outdated CMPLOG, recompile it!\n"); + FATAL("Target was compiled with outdated CMPLOG, recompile it!\n"); } -- cgit v1.2.3 From dd8806971131fafc5563d0cd993b4a2222b3b486 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 9 Feb 2024 13:57:45 +0100 Subject: fix --- src/afl-forkserver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 8853458a..508b5fa7 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -1220,7 +1220,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if ((status & FS_OPT_ERROR) == FS_OPT_ERROR) report_error_and_exit(FS_OPT_GET_ERROR(status)); - if (fsrv->cmplog_binary) { + if (fsrv->cmplog_binary && !fsrv->qemu_mode) { FATAL("Target was compiled with outdated CMPLOG, recompile it!\n"); -- cgit v1.2.3 From 6dc58750cf2b321b5cb42a2080410e6d9420548b Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Thu, 15 Feb 2024 19:19:51 -0500 Subject: issue #2001: fix passing rpath to linker on macOS Seems on macOS, `ld` does not want an `=` when specifying `-rpath`. --- src/afl-cc.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 3a32a0d1..6aa0da6a 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -2379,7 +2379,11 @@ void add_runtime(aflcc_state_t *aflcc) { if (aflcc->plusplus_mode && strlen(libdir) && strncmp(libdir, "/usr", 4) && strncmp(libdir, "/lib", 4)) { +#ifdef __APPLE__ + u8 *libdir_opt = strdup("-Wl,-rpath," LLVM_LIBDIR); +#else u8 *libdir_opt = strdup("-Wl,-rpath=" LLVM_LIBDIR); +#endif insert_param(aflcc, libdir_opt); } -- cgit v1.2.3 From 98238ed7630e6a5b135f520b8511548776b1b2ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20Wei=C3=9F?= Date: Thu, 22 Feb 2024 15:28:55 +0100 Subject: Convert from microseconds (us) to milliseconds (ms) --- src/afl-fuzz.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 9c89b2a1..30babad3 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2493,8 +2493,8 @@ int main(int argc, char **argv_orig, char **envp) { for (entry = 0; entry < afl->queued_items; ++entry) if (!afl->queue_buf[entry]->disabled) - if (afl->queue_buf[entry]->exec_us > max_ms) - max_ms = afl->queue_buf[entry]->exec_us; + if ((afl->queue_buf[entry]->exec_us/1000) > max_ms) + max_ms = afl->queue_buf[entry]->exec_us/1000; afl->fsrv.exec_tmout = max_ms; afl->timeout_given = 1; -- cgit v1.2.3 From 07e0b391260d007f9dc52329dc51887fe568f109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20Wei=C3=9F?= Date: Thu, 22 Feb 2024 15:55:18 +0100 Subject: Do not circumvent sanity checks from arg parsing --- src/afl-fuzz.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 30babad3..0ddb8880 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2495,8 +2495,9 @@ int main(int argc, char **argv_orig, char **envp) { if (!afl->queue_buf[entry]->disabled) if ((afl->queue_buf[entry]->exec_us/1000) > max_ms) max_ms = afl->queue_buf[entry]->exec_us/1000; - - afl->fsrv.exec_tmout = max_ms; + + if (max_ms > afl->fsrv.exec_tmout) + afl->fsrv.exec_tmout = max_ms; afl->timeout_given = 1; } -- cgit v1.2.3 From eaedf2e62f77310fc0981c1c6d3ca573662d1522 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20Wei=C3=9F?= Date: Fri, 23 Feb 2024 12:52:11 +0100 Subject: Adhere to documented behavior --- src/afl-fuzz.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 0ddb8880..803a1acc 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2496,8 +2496,7 @@ int main(int argc, char **argv_orig, char **envp) { if ((afl->queue_buf[entry]->exec_us/1000) > max_ms) max_ms = afl->queue_buf[entry]->exec_us/1000; - if (max_ms > afl->fsrv.exec_tmout) - afl->fsrv.exec_tmout = max_ms; + afl->fsrv.exec_tmout = max_ms; afl->timeout_given = 1; } -- cgit v1.2.3 From 01f442d81016188e847eae5320882cb1fbfa6dc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20Wei=C3=9F?= Date: Fri, 23 Feb 2024 12:53:20 +0100 Subject: Be specific about the unit of time --- src/afl-forkserver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 508b5fa7..1381236c 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -1931,7 +1931,7 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, if (exec_ms > timeout) { - /* If there was no response from forkserver after timeout seconds, + /* If there was no response from forkserver after timeout milliseconds, we kill the child. The forkserver should inform us afterwards */ s32 tmp_pid = fsrv->child_pid; -- cgit v1.2.3 From fae760fc9e4c63385c24fe07e5d5c3ab077b56bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20Wei=C3=9F?= Date: Fri, 23 Feb 2024 13:39:46 +0100 Subject: Add upper and lower safety margins --- src/afl-fuzz.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 803a1acc..08f716fa 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2496,6 +2496,15 @@ int main(int argc, char **argv_orig, char **envp) { if ((afl->queue_buf[entry]->exec_us/1000) > max_ms) max_ms = afl->queue_buf[entry]->exec_us/1000; + // Add 20% as a safety margin, capped to exec_tmout given in -t option + max_ms *= 1.2; + if(max_ms > afl->fsrv.exec_tmout) + max_ms = afl->fsrv.exec_tmout; + + // Ensure that there is a sensible timeout even for very fast binaries + if(max_ms < 5) + max_ms = 5; + afl->fsrv.exec_tmout = max_ms; afl->timeout_given = 1; -- cgit v1.2.3 From b2b887d04decdcdadf702c585bb1992a0a821bf1 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Thu, 22 Feb 2024 10:47:53 -0500 Subject: Issue #2007: add filename extension to /crashes files This is very helpful for code that inpects a file name extension when determining what code to run. It's also useful for applications that constrain the user to choose files by extension. --- src/afl-forkserver.c | 8 +++++--- src/afl-fuzz-bitmap.c | 34 +++++++++++++++++++++++----------- src/afl-fuzz-extras.c | 5 ++++- src/afl-fuzz-init.c | 26 ++++++++++++++++++-------- 4 files changed, 50 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 508b5fa7..0d7c19c6 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -2003,7 +2003,7 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, if (unlikely(fsrv->persistent_record)) { retval = FSRV_RUN_TMOUT; - persistent_out_fmt = "%s/hangs/RECORD:%06u,cnt:%06u"; + persistent_out_fmt = "%s/hangs/RECORD:%06u,cnt:%06u%s%s"; goto store_persistent_record; } @@ -2039,7 +2039,7 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, if (unlikely(fsrv->persistent_record)) { retval = FSRV_RUN_CRASH; - persistent_out_fmt = "%s/crashes/RECORD:%06u,cnt:%06u"; + persistent_out_fmt = "%s/crashes/RECORD:%06u,cnt:%06u%s%s"; goto store_persistent_record; } @@ -2066,7 +2066,9 @@ store_persistent_record: { if (likely(len && data)) { snprintf(fn, sizeof(fn), persistent_out_fmt, fsrv->persistent_record_dir, - fsrv->persistent_record_cnt, writecnt++); + fsrv->persistent_record_cnt, writecnt++, + afl->file_extension ? "." : "", + afl->file_extension ? (const char*)afl->file_extension : ""); int fd = open(fn, O_CREAT | O_TRUNC | O_WRONLY, 0644); if (fd >= 0) { diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index d056ac9f..0ad68835 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -528,14 +528,18 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { #ifndef SIMPLE_FILES queue_fn = - alloc_printf("%s/queue/id:%06u,%s", afl->out_dir, afl->queued_items, + alloc_printf("%s/queue/id:%06u,%s%s%s", afl->out_dir, afl->queued_items, describe_op(afl, new_bits + is_timeout, - NAME_MAX - strlen("id:000000,"))); + NAME_MAX - strlen("id:000000,")), + afl->file_extension ? "." : "", + afl->file_extension ? (const char*)afl->file_extension : ""); #else queue_fn = - alloc_printf("%s/queue/id_%06u", afl->out_dir, afl->queued_items); + alloc_printf("%s/queue/id_%06u", afl->out_dir, afl->queued_items, + afl->file_extension ? "." : "", + afl->file_extension ? (const char*)afl->file_extension : ""); #endif /* ^!SIMPLE_FILES */ fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); @@ -739,14 +743,18 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { #ifndef SIMPLE_FILES - snprintf(fn, PATH_MAX, "%s/hangs/id:%06llu,%s", afl->out_dir, + snprintf(fn, PATH_MAX, "%s/hangs/id:%06llu,%s%s%s", afl->out_dir, afl->saved_hangs, - describe_op(afl, 0, NAME_MAX - strlen("id:000000,"))); + describe_op(afl, 0, NAME_MAX - strlen("id:000000,")), + afl->file_extension ? "." : "", + afl->file_extension ? (const char*)afl->file_extension : ""); #else - snprintf(fn, PATH_MAX, "%s/hangs/id_%06llu", afl->out_dir, - afl->saved_hangs); + snprintf(fn, PATH_MAX, "%s/hangs/id_%06llu%s%s", afl->out_dir, + afl->saved_hangs, + afl->file_extension ? "." : "", + afl->file_extension ? (const char*)afl->file_extension : ""); #endif /* ^!SIMPLE_FILES */ @@ -792,14 +800,18 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { #ifndef SIMPLE_FILES - snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s", afl->out_dir, + snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s%s", afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal, - describe_op(afl, 0, NAME_MAX - strlen("id:000000,sig:00,"))); + describe_op(afl, 0, NAME_MAX - strlen("id:000000,sig:00,")), + afl->file_extension ? "." : "", + afl->file_extension ? (const char*)afl->file_extension : ""); #else - snprintf(fn, PATH_MAX, "%s/crashes/id_%06llu_%02u", afl->out_dir, - afl->saved_crashes, afl->fsrv.last_kill_signal); + snprintf(fn, PATH_MAX, "%s/crashes/id_%06llu_%02u%s%s", afl->out_dir, + afl->saved_crashes, afl->fsrv.last_kill_signal, + afl->file_extension ? "." : "", + afl->file_extension ? (const char*)afl->file_extension : ""); #endif /* ^!SIMPLE_FILES */ diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c index 3b1d13f1..5735db0c 100644 --- a/src/afl-fuzz-extras.c +++ b/src/afl-fuzz-extras.c @@ -743,7 +743,10 @@ void save_auto(afl_state_t *afl) { for (i = 0; i < MIN((u32)USE_AUTO_EXTRAS, afl->a_extras_cnt); ++i) { u8 *fn = - alloc_printf("%s/queue/.state/auto_extras/auto_%06u", afl->out_dir, i); + alloc_printf("%s/queue/.state/auto_extras/auto_%06u%s%s", afl->out_dir, i, + afl->file_extension ? "." : "", + afl->file_extension ? (const char*)afl->file_extension : ""); + s32 fd; fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION); diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 54760744..102c0f15 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1157,18 +1157,22 @@ void perform_dry_run(afl_state_t *afl) { #ifndef SIMPLE_FILES - snprintf(crash_fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s", + snprintf(crash_fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s%s%s", afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal, describe_op(afl, 0, NAME_MAX - strlen("id:000000,sig:00,") - strlen(use_name)), - use_name); + use_name, + afl->file_extension ? "." : "", + afl->file_extension ? (const char*)afl->file_extension : ""); #else - snprintf(crash_fn, PATH_MAX, "%s/crashes/id_%06llu_%02u", + snprintf(crash_fn, PATH_MAX, "%s/crashes/id_%06llu_%02u%s%s", afl->out_dir, afl->saved_crashes, - afl->fsrv.last_kill_signal); + afl->fsrv.last_kill_signal, + afl->file_extension ? "." : "", + afl->file_extension ? (const char*)afl->file_extension : ""); #endif @@ -1439,7 +1443,9 @@ void pivot_inputs(afl_state_t *afl) { u32 src_id; afl->resuming_fuzz = 1; - nfn = alloc_printf("%s/queue/%s", afl->out_dir, rsl); + nfn = alloc_printf("%s/queue/%s%s%s", afl->out_dir, rsl, + afl->file_extension ? "." : "", + afl->file_extension ? (const char*)afl->file_extension : ""); /* Since we're at it, let's also get the parent and figure out the appropriate depth for this entry. */ @@ -1479,12 +1485,16 @@ void pivot_inputs(afl_state_t *afl) { } - nfn = alloc_printf("%s/queue/id:%06u,time:0,execs:%llu,orig:%s", - afl->out_dir, id, afl->fsrv.total_execs, use_name); + nfn = alloc_printf("%s/queue/id:%06u,time:0,execs:%llu,orig:%s%s%s", + afl->out_dir, id, afl->fsrv.total_execs, use_name, + afl->file_extension ? "." : "", + afl->file_extension ? (const char*)afl->file_extension : ""); #else - nfn = alloc_printf("%s/queue/id_%06u", afl->out_dir, id); + nfn = alloc_printf("%s/queue/id_%06u%s%s", afl->out_dir, id, + afl->file_extension ? "." : "", + afl->file_extension ? (const char*)afl->file_extension : ""); #endif /* ^!SIMPLE_FILES */ -- cgit v1.2.3 From 335b2d4542d951b6742ca02646ab1c254f64f8f2 Mon Sep 17 00:00:00 2001 From: Martin Nyhus Date: Wed, 28 Feb 2024 22:29:55 +0100 Subject: Load autodictionary when using new forkserver Fixes a bug where the new fork server would decrement dict_size until zero then try to use it as the upper bound for the number of bytes to pass to add_extra_func, causing it to never store any of the tokens. --- src/afl-forkserver.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 1381236c..d9207d45 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -1152,12 +1152,11 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } - while (dict_size != 0) { + while (offset < dict_size) { - rlen = read(fsrv->fsrv_st_fd, dict + offset, dict_size); + rlen = read(fsrv->fsrv_st_fd, dict + offset, dict_size - offset); if (rlen > 0) { - dict_size -= rlen; offset += rlen; } else { @@ -1165,7 +1164,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, FATAL( "Reading autodictionary fail at position %u with %u bytes " "left.", - offset, dict_size); + offset, dict_size - offset); } -- cgit v1.2.3 From 036a79268b48a0e3e061d5e3387711f69bed8d56 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 29 Feb 2024 09:10:22 +0100 Subject: gcc cmplog fix --- src/afl-cc.c | 3 ++- src/afl-fuzz.c | 14 ++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 6aa0da6a..faa46103 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -828,7 +828,8 @@ static void instrument_mode_old_environ(aflcc_state_t *aflcc) { } if (getenv("AFL_LLVM_CTX")) aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CTX; - if (getenv("AFL_LLVM_CALLER") || getenv("AFL_LLVM_LTO_CALLER") || getenv("AFL_LLVM_LTO_CTX")) + if (getenv("AFL_LLVM_CALLER") || getenv("AFL_LLVM_LTO_CALLER") || + getenv("AFL_LLVM_LTO_CTX")) aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CALLER; if (getenv("AFL_LLVM_NGRAM_SIZE")) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 08f716fa..443d93b0 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2493,17 +2493,15 @@ int main(int argc, char **argv_orig, char **envp) { for (entry = 0; entry < afl->queued_items; ++entry) if (!afl->queue_buf[entry]->disabled) - if ((afl->queue_buf[entry]->exec_us/1000) > max_ms) - max_ms = afl->queue_buf[entry]->exec_us/1000; - + if ((afl->queue_buf[entry]->exec_us / 1000) > max_ms) + max_ms = afl->queue_buf[entry]->exec_us / 1000; + // Add 20% as a safety margin, capped to exec_tmout given in -t option max_ms *= 1.2; - if(max_ms > afl->fsrv.exec_tmout) - max_ms = afl->fsrv.exec_tmout; - + if (max_ms > afl->fsrv.exec_tmout) max_ms = afl->fsrv.exec_tmout; + // Ensure that there is a sensible timeout even for very fast binaries - if(max_ms < 5) - max_ms = 5; + if (max_ms < 5) max_ms = 5; afl->fsrv.exec_tmout = max_ms; afl->timeout_given = 1; -- cgit v1.2.3 From 6062668679300af97248a59775cde45537601480 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 29 Feb 2024 14:31:47 +0100 Subject: fix not using autodict --- src/afl-forkserver.c | 27 ++++++++++++++++++++------- src/afl-fuzz-bitmap.c | 35 +++++++++++++++++------------------ src/afl-fuzz-extras.c | 8 ++++---- src/afl-fuzz-init.c | 47 ++++++++++++++++++++++++----------------------- 4 files changed, 65 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 4877843d..158651af 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -724,7 +724,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } /* autodict in Nyx mode */ - if (!ignore_autodict) { + if (!ignore_autodict && fsrv->add_extra_func) { char *x = alloc_printf("%s/workdir/dump/afl_autodict.txt", fsrv->out_dir_path); @@ -1111,7 +1111,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } - if ((status & FS_NEW_OPT_SHDMEM_FUZZ)) { + if ((status & FS_NEW_OPT_SHDMEM_FUZZ) && fsrv->add_extra_func && + !ignore_autodict) { if (fsrv->support_shmem_fuzz) { @@ -1130,6 +1131,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if ((status & FS_NEW_OPT_AUTODICT)) { + // even if we do not need the dictionary we have to read it + u32 dict_size; if (read(fsrv->fsrv_st_fd, &dict_size, 4) != 4) { @@ -1173,14 +1176,24 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, offset = 0; while (offset < dict_size && (u8)dict[offset] + offset < dict_size) { - fsrv->add_extra_func(fsrv->afl_ptr, dict + offset + 1, - (u8)dict[offset]); + if (!ignore_autodict && fsrv->add_extra_func) { + + fsrv->add_extra_func(fsrv->afl_ptr, dict + offset + 1, + (u8)dict[offset]); + count++; + + } + offset += (1 + dict[offset]); - count++; } - if (!be_quiet) { ACTF("Loaded %u autodictionary entries", count); } + if (!be_quiet && count) { + + ACTF("Loaded %u autodictionary entries", count); + + } + ck_free(dict); } @@ -2067,7 +2080,7 @@ store_persistent_record: { snprintf(fn, sizeof(fn), persistent_out_fmt, fsrv->persistent_record_dir, fsrv->persistent_record_cnt, writecnt++, afl->file_extension ? "." : "", - afl->file_extension ? (const char*)afl->file_extension : ""); + afl->file_extension ? (const char *)afl->file_extension : ""); int fd = open(fn, O_CREAT | O_TRUNC | O_WRONLY, 0644); if (fd >= 0) { diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 0ad68835..d8561dde 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -527,19 +527,19 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { #ifndef SIMPLE_FILES - queue_fn = - alloc_printf("%s/queue/id:%06u,%s%s%s", afl->out_dir, afl->queued_items, - describe_op(afl, new_bits + is_timeout, - NAME_MAX - strlen("id:000000,")), - afl->file_extension ? "." : "", - afl->file_extension ? (const char*)afl->file_extension : ""); + queue_fn = alloc_printf( + "%s/queue/id:%06u,%s%s%s", afl->out_dir, afl->queued_items, + describe_op(afl, new_bits + is_timeout, + NAME_MAX - strlen("id:000000,")), + afl->file_extension ? "." : "", + afl->file_extension ? (const char *)afl->file_extension : ""); #else - queue_fn = - alloc_printf("%s/queue/id_%06u", afl->out_dir, afl->queued_items, - afl->file_extension ? "." : "", - afl->file_extension ? (const char*)afl->file_extension : ""); + queue_fn = alloc_printf( + "%s/queue/id_%06u", afl->out_dir, afl->queued_items, + afl->file_extension ? "." : "", + afl->file_extension ? (const char *)afl->file_extension : ""); #endif /* ^!SIMPLE_FILES */ fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); @@ -747,14 +747,13 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { afl->saved_hangs, describe_op(afl, 0, NAME_MAX - strlen("id:000000,")), afl->file_extension ? "." : "", - afl->file_extension ? (const char*)afl->file_extension : ""); + afl->file_extension ? (const char *)afl->file_extension : ""); #else snprintf(fn, PATH_MAX, "%s/hangs/id_%06llu%s%s", afl->out_dir, - afl->saved_hangs, - afl->file_extension ? "." : "", - afl->file_extension ? (const char*)afl->file_extension : ""); + afl->saved_hangs, afl->file_extension ? "." : "", + afl->file_extension ? (const char *)afl->file_extension : ""); #endif /* ^!SIMPLE_FILES */ @@ -800,18 +799,18 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { #ifndef SIMPLE_FILES - snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s%s", afl->out_dir, - afl->saved_crashes, afl->fsrv.last_kill_signal, + snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s%s", + afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal, describe_op(afl, 0, NAME_MAX - strlen("id:000000,sig:00,")), afl->file_extension ? "." : "", - afl->file_extension ? (const char*)afl->file_extension : ""); + afl->file_extension ? (const char *)afl->file_extension : ""); #else snprintf(fn, PATH_MAX, "%s/crashes/id_%06llu_%02u%s%s", afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal, afl->file_extension ? "." : "", - afl->file_extension ? (const char*)afl->file_extension : ""); + afl->file_extension ? (const char *)afl->file_extension : ""); #endif /* ^!SIMPLE_FILES */ diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c index 5735db0c..c06896ef 100644 --- a/src/afl-fuzz-extras.c +++ b/src/afl-fuzz-extras.c @@ -742,10 +742,10 @@ void save_auto(afl_state_t *afl) { for (i = 0; i < MIN((u32)USE_AUTO_EXTRAS, afl->a_extras_cnt); ++i) { - u8 *fn = - alloc_printf("%s/queue/.state/auto_extras/auto_%06u%s%s", afl->out_dir, i, - afl->file_extension ? "." : "", - afl->file_extension ? (const char*)afl->file_extension : ""); + u8 *fn = alloc_printf( + "%s/queue/.state/auto_extras/auto_%06u%s%s", afl->out_dir, i, + afl->file_extension ? "." : "", + afl->file_extension ? (const char *)afl->file_extension : ""); s32 fd; diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 102c0f15..21a8ba7e 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1157,22 +1157,22 @@ void perform_dry_run(afl_state_t *afl) { #ifndef SIMPLE_FILES - snprintf(crash_fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s%s%s", - afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal, - describe_op(afl, 0, - NAME_MAX - strlen("id:000000,sig:00,") - - strlen(use_name)), - use_name, - afl->file_extension ? "." : "", - afl->file_extension ? (const char*)afl->file_extension : ""); + snprintf( + crash_fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s%s%s", + afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal, + describe_op( + afl, 0, + NAME_MAX - strlen("id:000000,sig:00,") - strlen(use_name)), + use_name, afl->file_extension ? "." : "", + afl->file_extension ? (const char *)afl->file_extension : ""); #else - snprintf(crash_fn, PATH_MAX, "%s/crashes/id_%06llu_%02u%s%s", - afl->out_dir, afl->saved_crashes, - afl->fsrv.last_kill_signal, - afl->file_extension ? "." : "", - afl->file_extension ? (const char*)afl->file_extension : ""); + snprintf( + crash_fn, PATH_MAX, "%s/crashes/id_%06llu_%02u%s%s", afl->out_dir, + afl->saved_crashes, afl->fsrv.last_kill_signal, + afl->file_extension ? "." : "", + afl->file_extension ? (const char *)afl->file_extension : ""); #endif @@ -1443,9 +1443,9 @@ void pivot_inputs(afl_state_t *afl) { u32 src_id; afl->resuming_fuzz = 1; - nfn = alloc_printf("%s/queue/%s%s%s", afl->out_dir, rsl, - afl->file_extension ? "." : "", - afl->file_extension ? (const char*)afl->file_extension : ""); + nfn = alloc_printf( + "%s/queue/%s%s%s", afl->out_dir, rsl, afl->file_extension ? "." : "", + afl->file_extension ? (const char *)afl->file_extension : ""); /* Since we're at it, let's also get the parent and figure out the appropriate depth for this entry. */ @@ -1485,16 +1485,17 @@ void pivot_inputs(afl_state_t *afl) { } - nfn = alloc_printf("%s/queue/id:%06u,time:0,execs:%llu,orig:%s%s%s", - afl->out_dir, id, afl->fsrv.total_execs, use_name, - afl->file_extension ? "." : "", - afl->file_extension ? (const char*)afl->file_extension : ""); + nfn = alloc_printf( + "%s/queue/id:%06u,time:0,execs:%llu,orig:%s%s%s", afl->out_dir, id, + afl->fsrv.total_execs, use_name, afl->file_extension ? "." : "", + afl->file_extension ? (const char *)afl->file_extension : ""); #else - nfn = alloc_printf("%s/queue/id_%06u%s%s", afl->out_dir, id, - afl->file_extension ? "." : "", - afl->file_extension ? (const char*)afl->file_extension : ""); + nfn = alloc_printf( + "%s/queue/id_%06u%s%s", afl->out_dir, id, + afl->file_extension ? "." : "", + afl->file_extension ? (const char *)afl->file_extension : ""); #endif /* ^!SIMPLE_FILES */ -- cgit v1.2.3 From 52e19d35fac636f9ea4679d402b5eaabaa74aa0a Mon Sep 17 00:00:00 2001 From: "Christian Holler (:decoder)" Date: Wed, 6 Mar 2024 10:55:53 +0100 Subject: Add optional handling of Nyx InvalidWriteToPayload event --- src/afl-forkserver.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 158651af..cf5c511e 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -1840,6 +1840,8 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, case Timeout: return FSRV_RUN_TMOUT; case InvalidWriteToPayload: + if (!!getenv("AFL_NYX_HANDLE_INVALID_WRITE")) { return FSRV_RUN_CRASH; } + /* ??? */ FATAL("FixMe: Nyx InvalidWriteToPayload handler is missing"); break; -- cgit v1.2.3 From 0ea53ea5b569a151902e4a8f79a6bc48a73f074b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 6 Mar 2024 12:41:00 +0100 Subject: likely --- src/afl-forkserver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 158651af..6071407a 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -1873,7 +1873,7 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, territory. */ #ifdef __linux__ - if (!fsrv->nyx_mode) { + if (likely(!fsrv->nyx_mode)) { memset(fsrv->trace_bits, 0, fsrv->map_size); MEM_BARRIER(); -- cgit v1.2.3 From 306a917956f91a34a6a9008952616fab07c8f21a Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 7 Mar 2024 12:09:22 +0100 Subject: UI fix --- src/afl-fuzz-stats.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index b6900506..4f398863 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -876,6 +876,10 @@ void show_stats_normal(afl_state_t *afl) { #endif + if (banner_pad) + for (u32 i = 0; i < banner_pad; ++i) + strcat(banner, " "); + } SAYF("\n%s\n", banner); -- cgit v1.2.3 From b85174fc8d599668dd17ccdd62971a09cb9497c8 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 12 Mar 2024 04:00:19 +0100 Subject: nit --- src/afl-fuzz.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 443d93b0..99491628 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2073,6 +2073,17 @@ int main(int argc, char **argv_orig, char **envp) { } + /* Simply code if AFL_TMPDIR is used or not */ + if (!afl->afl_env.afl_tmpdir) { + + afl->tmp_dir = afl->out_dir; + + } else { + + afl->tmp_dir = afl->afl_env.afl_tmpdir; + + } + write_setup_file(afl, argc, argv); setup_cmdline_file(afl, argv + optind); @@ -2085,8 +2096,7 @@ int main(int argc, char **argv_orig, char **envp) { if (!afl->timeout_given) { find_timeout(afl); } // only for resumes! - if ((afl->tmp_dir = afl->afl_env.afl_tmpdir) != NULL && - !afl->in_place_resume) { + if (afl->afl_env.afl_tmpdir && !afl->in_place_resume) { char tmpfile[PATH_MAX]; @@ -2111,10 +2121,6 @@ int main(int argc, char **argv_orig, char **envp) { } - } else { - - afl->tmp_dir = afl->out_dir; - } /* If we don't have a file name chosen yet, use a safe default. */ @@ -3068,7 +3074,7 @@ stop_fuzzing: afl_fsrv_deinit(&afl->fsrv); /* remove tmpfile */ - if (afl->tmp_dir != NULL && !afl->in_place_resume && afl->fsrv.out_file) { + if (!afl->in_place_resume && afl->fsrv.out_file) { (void)unlink(afl->fsrv.out_file); -- cgit v1.2.3 From c9ad3acc9b69daea5e99b6ef66ed1f593331d474 Mon Sep 17 00:00:00 2001 From: gnbon Date: Wed, 13 Mar 2024 12:10:38 +0900 Subject: Add -l option for adjustable block deletion - Introduce the -l option to set min block deletion length using powers of 2 (e.g., 1, 2, 4, 8, 16, ...). - This enables a trade-off between minimization thoroughness and speed. - Adjusting del_len_limit allows for faster processing, as doubling it roughly halves the minimization time. --- src/afl-tmin.c | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 4e5dab41..03e70a6f 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -82,6 +82,8 @@ static u8 crash_mode, /* Crash-centric mode? */ remove_shm = 1, /* remove shmem on exit? */ debug; /* debug mode */ +static u32 del_len_limit; /* Minimum block deletion length */ + static volatile u8 stop_soon; /* Ctrl-C pressed? */ static afl_forkserver_t *fsrv; @@ -421,6 +423,7 @@ next_pass: del_len = next_pow2(in_len / TRIM_START_STEPS); stage_o_len = in_len; + if (!del_len_limit) { del_len_limit = 1; } ACTF(cBRI "Stage #1: " cRST "Removing blocks of data..."); @@ -480,7 +483,7 @@ next_del_blksize: } - if (del_len > 1 && in_len >= 1) { + if (del_len > del_len_limit && in_len >= 1) { del_len /= 2; goto next_del_blksize; @@ -796,8 +799,9 @@ static void usage(u8 *argv0) { "Minimization settings:\n" " -e - solve for edge coverage only, ignore hit counts\n" - " -x - treat non-zero exit codes as crashes\n\n" - " -H - minimize a hang (hang mode)\n" + " -l bytes - set minimum block deletion length to speed up minimization\n" + " -x - treat non-zero exit codes as crashes\n" + " -H - minimize a hang (hang mode)\n\n" "For additional tips, please consult %s/README.md.\n\n" @@ -829,8 +833,9 @@ static void usage(u8 *argv0) { int main(int argc, char **argv_orig, char **envp) { - s32 opt; - u8 mem_limit_given = 0, timeout_given = 0, unicorn_mode = 0, use_wine = 0; + s32 opt; + u8 mem_limit_given = 0, timeout_given = 0, unicorn_mode = 0, use_wine = 0, + del_limit_given = 0; char **use_argv; char **argv = argv_cpy_dup(argc, argv_orig); @@ -846,7 +851,7 @@ int main(int argc, char **argv_orig, char **envp) { SAYF(cCYA "afl-tmin" VERSION cRST " by Michal Zalewski\n"); - while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeAOQUWXYHh")) > 0) { + while ((opt = getopt(argc, argv, "+i:o:f:m:t:l:B:xeAOQUWXYHh")) > 0) { switch (opt) { @@ -1055,6 +1060,24 @@ int main(int argc, char **argv_orig, char **envp) { read_bitmap(optarg, mask_bitmap, map_size); break; + case 'l': + if (del_limit_given) { FATAL("Multiple -l options not supported"); } + del_limit_given = 1; + + if (!optarg) { FATAL("Wrong usage of -l"); } + + if (optarg[0] == '-') { FATAL("Dangerously low value of -l"); } + + del_len_limit = atoi(optarg); + + if (del_len_limit < 1 || del_len_limit >= TMIN_MAX_FILE) { + + FATAL("Value of -l out of range between 1 and TMIN_MAX_FILE"); + + } + + break; + case 'h': usage(argv[0]); return -1; -- cgit v1.2.3 From 1860f6e594883965f7b630a65d5a77006f284aa1 Mon Sep 17 00:00:00 2001 From: gnbon Date: Thu, 14 Mar 2024 11:00:59 +0900 Subject: Fix invalid range for del_len_limit --- src/afl-tmin.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 03e70a6f..994174ed 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -82,7 +82,7 @@ static u8 crash_mode, /* Crash-centric mode? */ remove_shm = 1, /* remove shmem on exit? */ debug; /* debug mode */ -static u32 del_len_limit; /* Minimum block deletion length */ +static u32 del_len_limit = 1; /* Minimum block deletion length */ static volatile u8 stop_soon; /* Ctrl-C pressed? */ @@ -423,7 +423,6 @@ next_pass: del_len = next_pow2(in_len / TRIM_START_STEPS); stage_o_len = in_len; - if (!del_len_limit) { del_len_limit = 1; } ACTF(cBRI "Stage #1: " cRST "Removing blocks of data..."); @@ -1070,7 +1069,7 @@ int main(int argc, char **argv_orig, char **envp) { del_len_limit = atoi(optarg); - if (del_len_limit < 1 || del_len_limit >= TMIN_MAX_FILE) { + if (del_len_limit < 1 || del_len_limit > TMIN_MAX_FILE) { FATAL("Value of -l out of range between 1 and TMIN_MAX_FILE"); -- cgit v1.2.3 From 5ffc8c70761f97fbaffa3a98a6c472d35930c7b2 Mon Sep 17 00:00:00 2001 From: Sergey Bronnikov Date: Sat, 30 Mar 2024 11:26:38 +0300 Subject: src: fix calculation of fuzzing time in statistics When the computer is suspended during a fuzzing session, the time spent in suspended state is counted as a "run time" on a statistics screen. The time returned by `gettimeofday(2)` is affected by discontinuous jumps in the system time. It is better using `clock_gettime(2)`. The patch replace `gettimeofday` with `clock_gettime` [1]. `clock_gettime` uses a CLOCK_MONOTONIC_COARSE clock type, it is faster than CLOCK_MONOTONIC, but still has resolution (~1ms) that is adequate for our purposes. However, CLOCK_MONOTONIC_COARSE is a Linux-specific clock variant, so on macOS it is replaced with CLOCK_MONOTONIC, and with CLOCK_MONOTONIC_FAST on FreeBSD [2]. Closes #1241 1. https://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_gettime.html 2. https://man.freebsd.org/cgi/man.cgi?query=clock_gettime --- src/afl-common.c | 49 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/afl-common.c b/src/afl-common.c index 87003b03..53524e96 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -34,6 +34,7 @@ #endif #include #include +#include #include #include @@ -58,6 +59,26 @@ u8 last_intr = 0; #define AFL_PATH "/usr/local/lib/afl/" #endif +/* - Some BSD (i.e.: FreeBSD) offer the FAST clock source as + * equivalent to Linux COARSE clock source. Aliasing COARSE to + * FAST on such systems when COARSE is not already defined. + * - macOS has no support of CLOCK_MONOTONIC_COARSE clock type. + */ +#if defined (OS_DARWIN) || defined (OS_SUNOS) +# define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC +#elif defined (OS_FREEBSD) +# define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC_FAST +#endif + +/* Convert seconds to milliseconds. */ +#define SEC_TO_MS(sec) ((sec)*1000) +/* Convert seconds to microseconds. */ +#define SEC_TO_US(sec) ((sec)*1000000) +/* Convert nanoseconds to milliseconds. */ +#define NS_TO_MS(ns) ((ns)/1000000) +/* Convert nanoseconds to microseconds. */ +#define NS_TO_US(ns) ((ns)/1000) + void *afl_memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen) { @@ -973,27 +994,27 @@ void read_bitmap(u8 *fname, u8 *map, size_t len) { /* Get unix time in milliseconds */ inline u64 get_cur_time(void) { + struct timespec ts; + int rc = clock_gettime(CLOCK_MONOTONIC_COARSE, &ts); + if (rc == -1) { + PFATAL("Failed to obtain timestamp (errno = %i: %s)\n", + errno, strerror(errno)); + } - struct timeval tv; - struct timezone tz; - - gettimeofday(&tv, &tz); - - return (tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000); - + return SEC_TO_MS((uint64_t)ts.tv_sec) + NS_TO_MS((uint64_t)ts.tv_nsec); } /* Get unix time in microseconds */ u64 get_cur_time_us(void) { + struct timespec ts; + int rc = clock_gettime(CLOCK_MONOTONIC_COARSE, &ts); + if (rc == -1) { + PFATAL("Failed to obtain timestamp (errno = %i: %s)\n", + errno, strerror(errno)); + } - struct timeval tv; - struct timezone tz; - - gettimeofday(&tv, &tz); - - return (tv.tv_sec * 1000000ULL) + tv.tv_usec; - + return SEC_TO_US((uint64_t)ts.tv_sec) + NS_TO_US((uint64_t)ts.tv_nsec); } /* Describe integer. The buf should be -- cgit v1.2.3 From f7ea0f569fa57e22548c1dc8eaba2903213e496e Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 5 Apr 2024 14:52:53 +0200 Subject: fix aflpp custom mutator + standalone tool --- src/afl-fuzz-state.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index ae327117..c61f00bd 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -28,10 +28,6 @@ #include "afl-fuzz.h" #include "envs.h" -s8 interesting_8[] = {INTERESTING_8}; -s16 interesting_16[] = {INTERESTING_8, INTERESTING_16}; -s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32}; - char *power_names[POWER_SCHEDULES_NUM] = {"explore", "mmopt", "exploit", "fast", "coe", "lin", "quad", "rare", "seek"}; -- cgit v1.2.3 From 45603367bfb71948f56715ac88e34c05c0dc0486 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 7 Apr 2024 09:44:33 +0200 Subject: fix llvm modules --- src/afl-cc.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index faa46103..45fd398b 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1369,6 +1369,13 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) { } + if (getenv("AFL_LLVM_DICT2FILE") && + (getenv("AFL_LLVM_LAF_SPLIT_SWITCHES") || + getenv("AFL_LLVM_LAF_SPLIT_COMPARES") || + getenv("AFL_LLVM_LAF_SPLIT_FLOATS") || + getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES"))) + FATAL("AFL_LLVM_DICT2FILE is incompatible with AFL_LLVM_LAF_*"); + aflcc->cmplog_mode = getenv("AFL_CMPLOG") || getenv("AFL_LLVM_CMPLOG") || getenv("AFL_GCC_CMPLOG"); -- cgit v1.2.3 From 420a90ff75bc37a2b02055b2587a69741a8194eb Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 7 Apr 2024 12:53:41 +0200 Subject: code format --- src/afl-common.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/afl-common.c b/src/afl-common.c index 53524e96..a956fef9 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -64,20 +64,20 @@ u8 last_intr = 0; * FAST on such systems when COARSE is not already defined. * - macOS has no support of CLOCK_MONOTONIC_COARSE clock type. */ -#if defined (OS_DARWIN) || defined (OS_SUNOS) -# define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC -#elif defined (OS_FREEBSD) -# define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC_FAST +#if defined(OS_DARWIN) || defined(OS_SUNOS) + #define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC +#elif defined(OS_FREEBSD) + #define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC_FAST #endif /* Convert seconds to milliseconds. */ -#define SEC_TO_MS(sec) ((sec)*1000) +#define SEC_TO_MS(sec) ((sec) * 1000) /* Convert seconds to microseconds. */ -#define SEC_TO_US(sec) ((sec)*1000000) +#define SEC_TO_US(sec) ((sec) * 1000000) /* Convert nanoseconds to milliseconds. */ -#define NS_TO_MS(ns) ((ns)/1000000) +#define NS_TO_MS(ns) ((ns) / 1000000) /* Convert nanoseconds to microseconds. */ -#define NS_TO_US(ns) ((ns)/1000) +#define NS_TO_US(ns) ((ns) / 1000) void *afl_memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen) { @@ -994,27 +994,35 @@ void read_bitmap(u8 *fname, u8 *map, size_t len) { /* Get unix time in milliseconds */ inline u64 get_cur_time(void) { + struct timespec ts; - int rc = clock_gettime(CLOCK_MONOTONIC_COARSE, &ts); + int rc = clock_gettime(CLOCK_MONOTONIC_COARSE, &ts); if (rc == -1) { - PFATAL("Failed to obtain timestamp (errno = %i: %s)\n", - errno, strerror(errno)); + + PFATAL("Failed to obtain timestamp (errno = %i: %s)\n", errno, + strerror(errno)); + } return SEC_TO_MS((uint64_t)ts.tv_sec) + NS_TO_MS((uint64_t)ts.tv_nsec); + } /* Get unix time in microseconds */ u64 get_cur_time_us(void) { + struct timespec ts; - int rc = clock_gettime(CLOCK_MONOTONIC_COARSE, &ts); + int rc = clock_gettime(CLOCK_MONOTONIC_COARSE, &ts); if (rc == -1) { - PFATAL("Failed to obtain timestamp (errno = %i: %s)\n", - errno, strerror(errno)); + + PFATAL("Failed to obtain timestamp (errno = %i: %s)\n", errno, + strerror(errno)); + } return SEC_TO_US((uint64_t)ts.tv_sec) + NS_TO_US((uint64_t)ts.tv_nsec); + } /* Describe integer. The buf should be -- cgit v1.2.3 From 29544e4d2bf24859030823a4b6a13df00928f7e1 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 7 Apr 2024 18:44:21 +0200 Subject: fix time --- src/afl-common.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-common.c b/src/afl-common.c index a956fef9..6d915b00 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -64,7 +64,8 @@ u8 last_intr = 0; * FAST on such systems when COARSE is not already defined. * - macOS has no support of CLOCK_MONOTONIC_COARSE clock type. */ -#if defined(OS_DARWIN) || defined(OS_SUNOS) +#if defined(OS_DARWIN) || defined(OS_SUNOS) || defined(__APPLE__) || \ + defined(__sun) || defined(__NetBSD__) #define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC #elif defined(OS_FREEBSD) #define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC_FAST -- cgit v1.2.3 From 48a862c503483f64db713fd6a0392148b5584ca4 Mon Sep 17 00:00:00 2001 From: Cornelius Aschermann Date: Wed, 13 Mar 2024 11:43:58 -0700 Subject: :Adds stats tracking time spend in calibration/trim/sync This currently does not affect statsd nor the UI. Only the fuzzer_stats file is updated --- src/afl-fuzz-run.c | 26 ++++++++--- src/afl-fuzz-stats.c | 128 +++++++++++++++++++++++++++++---------------------- src/afl-fuzz.c | 1 - 3 files changed, 92 insertions(+), 63 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index d764952c..82cdeb81 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -409,6 +409,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, u32 use_tmout = afl->fsrv.exec_tmout; u8 *old_sn = afl->stage_name; + u64 calibration_start_us = get_cur_time_us(); if (unlikely(afl->shm.cmplog_mode)) { q->exec_cksum = 0; } /* Be a bit more generous about timeouts when resuming sessions, or when @@ -504,6 +505,9 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, fault = fuzz_run_target(afl, &afl->fsrv, use_tmout); + // update the time spend in calibration after each execution, as those may be slow + update_calibration_time(afl, &calibration_start_us); + /* afl->stop_soon is set by the handler for Ctrl+C. When it's pressed, we want to bail out quickly. */ @@ -650,6 +654,7 @@ abort_calibration: if (!first_run) { show_stats(afl); } + update_calibration_time(afl, &calibration_start_us); return fault; } @@ -669,11 +674,15 @@ void sync_fuzzers(afl_state_t *afl) { afl->stage_max = afl->stage_cur = 0; afl->cur_depth = 0; + u64 sync_start_us = get_cur_time_us(); /* Look at the entries created for every other fuzzer in the sync directory. */ while ((sd_ent = readdir(sd))) { + // since sync can take substantial amounts of time, update time spend every iteration + update_sync_time(afl, &sync_start_us); + u8 qd_synced_path[PATH_MAX], qd_path[PATH_MAX]; u32 min_accept = 0, next_min_accept = 0; @@ -861,6 +870,9 @@ void sync_fuzzers(afl_state_t *afl) { if (afl->foreign_sync_cnt) read_foreign_testcases(afl, 0); + //add time in sync one last time + update_sync_time(afl, &sync_start_us); + afl->last_sync_time = get_cur_time(); afl->last_sync_cycle = afl->queue_cycle; @@ -872,8 +884,9 @@ void sync_fuzzers(afl_state_t *afl) { u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { + u8 needs_write = 0, fault = 0; u32 orig_len = q->len; - + u64 trim_start_us = get_cur_time_us(); /* Custom mutator trimmer */ if (afl->custom_mutators_count) { @@ -897,11 +910,10 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { } - if (custom_trimmed) return trimmed_case; + if (custom_trimmed) { fault = trimmed_case; goto abort_trimming; } } - u8 needs_write = 0, fault = 0; u32 trim_exec = 0; u32 remove_len; u32 len_p2; @@ -912,7 +924,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { detected, it will still work to some extent, so we don't check for this. */ - if (unlikely(q->len < 5)) { return 0; } + if (unlikely(q->len < 5)) { fault = 0; goto abort_trimming; } afl->stage_name = afl->stage_name_buf; afl->bytes_trim_in += q->len; @@ -946,6 +958,8 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); + update_trim_time(afl, &trim_start_us); + if (afl->stop_soon || fault == FSRV_RUN_ERROR) { goto abort_trimming; } /* Note that we don't keep track of crashes or hangs here; maybe TODO? @@ -1039,8 +1053,9 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { } abort_trimming: - afl->bytes_trim_out += q->len; + update_trim_time(afl, &trim_start_us); + return fault; } @@ -1104,4 +1119,3 @@ common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { return 0; } - diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 4f398863..b39c8299 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -133,6 +133,10 @@ void write_setup_file(afl_state_t *afl, u32 argc, char **argv) { } +static bool starts_with(char* key, char* line) { + return strncmp(key, line, strlen(key)) == 0; +} + /* load some of the existing stats file when resuming.*/ void load_stats_file(afl_state_t *afl) { @@ -175,65 +179,54 @@ void load_stats_file(afl_state_t *afl) { strcpy(keystring, lstartptr); lptr++; char *nptr; - switch (lineno) { - - case 3: - if (!strcmp(keystring, "run_time ")) - afl->prev_run_time = 1000 * strtoull(lptr, &nptr, 10); - break; - case 5: - if (!strcmp(keystring, "cycles_done ")) - afl->queue_cycle = - strtoull(lptr, &nptr, 10) ? strtoull(lptr, &nptr, 10) + 1 : 0; - break; - case 7: - if (!strcmp(keystring, "execs_done ")) - afl->fsrv.total_execs = strtoull(lptr, &nptr, 10); - break; - case 10: - if (!strcmp(keystring, "corpus_count ")) { - - u32 corpus_count = strtoul(lptr, &nptr, 10); - if (corpus_count != afl->queued_items) { - - WARNF( - "queue/ has been modified -- things might not work, you're " - "on your own!"); - - } - - } - - break; - case 12: - if (!strcmp(keystring, "corpus_found ")) - afl->queued_discovered = strtoul(lptr, &nptr, 10); - break; - case 13: - if (!strcmp(keystring, "corpus_imported ")) - afl->queued_imported = strtoul(lptr, &nptr, 10); - break; - case 14: - if (!strcmp(keystring, "max_depth ")) - afl->max_depth = strtoul(lptr, &nptr, 10); - break; - case 21: - if (!strcmp(keystring, "saved_crashes ")) - afl->saved_crashes = strtoull(lptr, &nptr, 10); - break; - case 22: - if (!strcmp(keystring, "saved_hangs ")) - afl->saved_hangs = strtoull(lptr, &nptr, 10); - break; - default: - break; - + if (starts_with("run_time", keystring)){ + afl->prev_run_time = 1000 * strtoull(lptr, &nptr, 10); + } + if (starts_with("cycles_done", keystring)){ + afl->queue_cycle = + strtoull(lptr, &nptr, 10) ? strtoull(lptr, &nptr, 10) + 1 : 0; + } + if (starts_with("calibration_time", keystring)){ + afl->calibration_time_us = strtoull(lptr, &nptr, 10) * 1000000; + } + if (starts_with("sync_time", keystring)){ + afl->sync_time_us = strtoull(lptr, &nptr, 10) * 1000000; + } + if (starts_with("trim_time", keystring)){ + afl->trim_time_us = strtoull(lptr, &nptr, 10) * 1000000; } + if (starts_with("execs_done", keystring)){ + afl->fsrv.total_execs = strtoull(lptr, &nptr, 10); + } + if (starts_with("corpus_count", keystring)) { - } + u32 corpus_count = strtoul(lptr, &nptr, 10); + if (corpus_count != afl->queued_items) { - } + WARNF( + "queue/ has been modified -- things might not work, you're " + "on your own!"); + } + + } + if (starts_with("corpus_found", keystring)){ + afl->queued_discovered = strtoul(lptr, &nptr, 10); + } + if (starts_with("corpus_imported", keystring)){ + afl->queued_imported = strtoul(lptr, &nptr, 10); + } + if (starts_with("max_depth", keystring)) { + afl->max_depth = strtoul(lptr, &nptr, 10); + } + if (starts_with("saved_crashes", keystring)) { + afl->saved_crashes = strtoull(lptr, &nptr, 10); + } + if (starts_with("saved_hangs", keystring)) { + afl->saved_hangs = strtoull(lptr, &nptr, 10); + } + } + } if (afl->saved_crashes) { write_crash_readme(afl); } return; @@ -300,6 +293,10 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, "cycles_done : %llu\n" "cycles_wo_finds : %llu\n" "time_wo_finds : %llu\n" + "fuzz_time : %llu\n" + "calibration_time : %llu\n" + "sync_time : %llu\n" + "trim_time : %llu\n" "execs_done : %llu\n" "execs_per_sec : %0.02f\n" "execs_ps_last_min : %0.02f\n" @@ -345,6 +342,10 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, : ((afl->start_time == 0 || afl->last_find_time == 0) ? 0 : (cur_time - afl->last_find_time) / 1000), + (runtime - (afl->calibration_time_us + afl->sync_time_us + afl->trim_time_us) / 1000) / 1000, + afl->calibration_time_us / 1000000, + afl->sync_time_us / 1000000, + afl->trim_time_us / 1000000, afl->fsrv.total_execs, afl->fsrv.total_execs / ((double)(runtime) / 1000), afl->last_avg_execs_saved, afl->queued_items, afl->queued_favored, afl->queued_discovered, afl->queued_imported, afl->queued_variable, @@ -414,7 +415,6 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, fclose(f); rename(fn_tmp, fn_final); - } #ifdef INTROSPECTION @@ -2438,4 +2438,20 @@ void show_init_stats(afl_state_t *afl) { #undef IB } +void update_calibration_time(afl_state_t *afl, u64* time){ + u64 cur = get_cur_time_us(); + afl->calibration_time_us += cur-*time; + *time = cur; +} + +void update_trim_time(afl_state_t *afl, u64* time){ + u64 cur = get_cur_time_us(); + afl->trim_time_us += cur-*time; + *time = cur; +} +void update_sync_time(afl_state_t *afl, u64* time){ + u64 cur = get_cur_time_us(); + afl->sync_time_us += cur-*time; + *time = cur; +} diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 99491628..102809cd 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -3099,4 +3099,3 @@ stop_fuzzing: } #endif /* !AFL_LIB */ - -- cgit v1.2.3 From 40adc344136c954cdc58e62acb46708816f5870a Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 9 Apr 2024 09:24:19 +0200 Subject: fix -V, code format --- src/afl-fuzz-run.c | 25 ++++++++++---- src/afl-fuzz-stats.c | 98 +++++++++++++++++++++++++++++++++++++++------------- src/afl-fuzz.c | 21 ++++++++--- 3 files changed, 108 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 82cdeb81..1c6ce56a 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -505,7 +505,8 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, fault = fuzz_run_target(afl, &afl->fsrv, use_tmout); - // update the time spend in calibration after each execution, as those may be slow + // update the time spend in calibration after each execution, as those may + // be slow update_calibration_time(afl, &calibration_start_us); /* afl->stop_soon is set by the handler for Ctrl+C. When it's pressed, @@ -680,7 +681,8 @@ void sync_fuzzers(afl_state_t *afl) { while ((sd_ent = readdir(sd))) { - // since sync can take substantial amounts of time, update time spend every iteration + // since sync can take substantial amounts of time, update time spend every + // iteration update_sync_time(afl, &sync_start_us); u8 qd_synced_path[PATH_MAX], qd_path[PATH_MAX]; @@ -870,7 +872,7 @@ void sync_fuzzers(afl_state_t *afl) { if (afl->foreign_sync_cnt) read_foreign_testcases(afl, 0); - //add time in sync one last time + // add time in sync one last time update_sync_time(afl, &sync_start_us); afl->last_sync_time = get_cur_time(); @@ -910,7 +912,12 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { } - if (custom_trimmed) { fault = trimmed_case; goto abort_trimming; } + if (custom_trimmed) { + + fault = trimmed_case; + goto abort_trimming; + + } } @@ -924,7 +931,12 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { detected, it will still work to some extent, so we don't check for this. */ - if (unlikely(q->len < 5)) { fault = 0; goto abort_trimming; } + if (unlikely(q->len < 5)) { + + fault = 0; + goto abort_trimming; + + } afl->stage_name = afl->stage_name_buf; afl->bytes_trim_in += q->len; @@ -986,7 +998,6 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { /* Let's save a clean trace, which will be needed by update_bitmap_score once we're done with the trimming stuff. */ - if (!needs_write) { needs_write = 1; @@ -1001,7 +1012,6 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { } /* Since this can be slow, update the screen every now and then. */ - if (!(trim_exec++ % afl->stats_update_freq)) { show_stats(afl); } ++afl->stage_cur; @@ -1119,3 +1129,4 @@ common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { return 0; } + diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index b39c8299..7e1a3b92 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -133,8 +133,10 @@ void write_setup_file(afl_state_t *afl, u32 argc, char **argv) { } -static bool starts_with(char* key, char* line) { +static bool starts_with(char *key, char *line) { + return strncmp(key, line, strlen(key)) == 0; + } /* load some of the existing stats file when resuming.*/ @@ -179,25 +181,43 @@ void load_stats_file(afl_state_t *afl) { strcpy(keystring, lstartptr); lptr++; char *nptr; - if (starts_with("run_time", keystring)){ + if (starts_with("run_time", keystring)) { + afl->prev_run_time = 1000 * strtoull(lptr, &nptr, 10); + } - if (starts_with("cycles_done", keystring)){ + + if (starts_with("cycles_done", keystring)) { + afl->queue_cycle = strtoull(lptr, &nptr, 10) ? strtoull(lptr, &nptr, 10) + 1 : 0; + } - if (starts_with("calibration_time", keystring)){ + + if (starts_with("calibration_time", keystring)) { + afl->calibration_time_us = strtoull(lptr, &nptr, 10) * 1000000; + } - if (starts_with("sync_time", keystring)){ + + if (starts_with("sync_time", keystring)) { + afl->sync_time_us = strtoull(lptr, &nptr, 10) * 1000000; + } - if (starts_with("trim_time", keystring)){ + + if (starts_with("trim_time", keystring)) { + afl->trim_time_us = strtoull(lptr, &nptr, 10) * 1000000; + } - if (starts_with("execs_done", keystring)){ + + if (starts_with("execs_done", keystring)) { + afl->fsrv.total_execs = strtoull(lptr, &nptr, 10); + } + if (starts_with("corpus_count", keystring)) { u32 corpus_count = strtoul(lptr, &nptr, 10); @@ -206,27 +226,46 @@ void load_stats_file(afl_state_t *afl) { WARNF( "queue/ has been modified -- things might not work, you're " "on your own!"); + sleep(3); } } - if (starts_with("corpus_found", keystring)){ + + if (starts_with("corpus_found", keystring)) { + afl->queued_discovered = strtoul(lptr, &nptr, 10); + } - if (starts_with("corpus_imported", keystring)){ + + if (starts_with("corpus_imported", keystring)) { + afl->queued_imported = strtoul(lptr, &nptr, 10); + } + if (starts_with("max_depth", keystring)) { + afl->max_depth = strtoul(lptr, &nptr, 10); + } + if (starts_with("saved_crashes", keystring)) { + afl->saved_crashes = strtoull(lptr, &nptr, 10); + } + if (starts_with("saved_hangs", keystring)) { + afl->saved_hangs = strtoull(lptr, &nptr, 10); + } + } + } + if (afl->saved_crashes) { write_crash_readme(afl); } return; @@ -334,7 +373,7 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, "\n" "target_mode : %s%s%s%s%s%s%s%s%s%s\n" "command_line : %s\n", - (afl->start_time - afl->prev_run_time) / 1000, cur_time / 1000, + (afl->start_time /*- afl->prev_run_time*/) / 1000, cur_time / 1000, runtime / 1000, (u32)getpid(), afl->queue_cycle ? (afl->queue_cycle - 1) : 0, afl->cycles_wo_finds, afl->longest_find_time > cur_time - afl->last_find_time @@ -342,11 +381,13 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, : ((afl->start_time == 0 || afl->last_find_time == 0) ? 0 : (cur_time - afl->last_find_time) / 1000), - (runtime - (afl->calibration_time_us + afl->sync_time_us + afl->trim_time_us) / 1000) / 1000, - afl->calibration_time_us / 1000000, - afl->sync_time_us / 1000000, - afl->trim_time_us / 1000000, - afl->fsrv.total_execs, afl->fsrv.total_execs / ((double)(runtime) / 1000), + (runtime - + (afl->calibration_time_us + afl->sync_time_us + afl->trim_time_us) / + 1000) / + 1000, + afl->calibration_time_us / 1000000, afl->sync_time_us / 1000000, + afl->trim_time_us / 1000000, afl->fsrv.total_execs, + afl->fsrv.total_execs / ((double)(runtime) / 1000), afl->last_avg_execs_saved, afl->queued_items, afl->queued_favored, afl->queued_discovered, afl->queued_imported, afl->queued_variable, afl->max_depth, afl->current_entry, afl->pending_favored, @@ -415,6 +456,7 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, fclose(f); rename(fn_tmp, fn_final); + } #ifdef INTROSPECTION @@ -2438,20 +2480,28 @@ void show_init_stats(afl_state_t *afl) { #undef IB } -void update_calibration_time(afl_state_t *afl, u64* time){ - u64 cur = get_cur_time_us(); - afl->calibration_time_us += cur-*time; + +void update_calibration_time(afl_state_t *afl, u64 *time) { + + u64 cur = get_cur_time_us(); + afl->calibration_time_us += cur - *time; *time = cur; + } -void update_trim_time(afl_state_t *afl, u64* time){ - u64 cur = get_cur_time_us(); - afl->trim_time_us += cur-*time; +void update_trim_time(afl_state_t *afl, u64 *time) { + + u64 cur = get_cur_time_us(); + afl->trim_time_us += cur - *time; *time = cur; + } -void update_sync_time(afl_state_t *afl, u64* time){ - u64 cur = get_cur_time_us(); - afl->sync_time_us += cur-*time; +void update_sync_time(afl_state_t *afl, u64 *time) { + + u64 cur = get_cur_time_us(); + afl->sync_time_us += cur - *time; *time = cur; + } + diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 102809cd..00d24ab1 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -5,8 +5,9 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt and - Andrea Fioraldi + Dominik Meier , + Andrea Fioraldi , and + Heiko Eissfeldt Copyright 2016, 2017 Google Inc. All rights reserved. Copyright 2019-2024 AFLplusplus Project. All rights reserved. @@ -199,7 +200,8 @@ static void usage(u8 *argv0, int more_help) { "Test settings:\n" " -s seed - use a fixed seed for the RNG\n" - " -V seconds - fuzz for a specified time then terminate\n" + " -V seconds - fuzz for a specified time then terminate (fuzz time " + "only!)\n" " -E execs - fuzz for an approx. no. of total executions then " "terminate\n" " Note: not precise and can have several more " @@ -2543,8 +2545,6 @@ int main(int argc, char **argv_orig, char **envp) { } // (void)nice(-20); // does not improve the speed - // real start time, we reset, so this works correctly with -V - afl->start_time = get_cur_time(); #ifdef INTROSPECTION u32 prev_saved_crashes = 0, prev_saved_tmouts = 0; @@ -2565,6 +2565,9 @@ int main(int argc, char **argv_orig, char **envp) { OKF("Writing mutation introspection to '%s'", ifn); #endif + // real start time, we reset, so this works correctly with -V + afl->start_time = get_cur_time(); + while (likely(!afl->stop_soon)) { cull_queue(afl); @@ -2585,6 +2588,13 @@ int main(int argc, char **argv_orig, char **envp) { sync_fuzzers(afl); + if (!afl->queue_cycle && afl->afl_env.afl_import_first) { + + // real start time, we reset, so this works correctly with -V + afl->start_time = get_cur_time(); + + } + } ++afl->queue_cycle; @@ -3099,3 +3109,4 @@ stop_fuzzing: } #endif /* !AFL_LIB */ + -- cgit v1.2.3 From 72226d6f89ef47c1e81115eccff887cbf4ec585f Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 9 Apr 2024 16:20:42 +0200 Subject: fix shared memory test cases --- src/afl-forkserver.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 6071407a..d8efaa97 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -1111,8 +1111,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } - if ((status & FS_NEW_OPT_SHDMEM_FUZZ) && fsrv->add_extra_func && - !ignore_autodict) { + if (status & FS_NEW_OPT_SHDMEM_FUZZ) { if (fsrv->support_shmem_fuzz) { @@ -1129,7 +1128,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } - if ((status & FS_NEW_OPT_AUTODICT)) { + if (status & FS_NEW_OPT_AUTODICT) { // even if we do not need the dictionary we have to read it -- cgit v1.2.3 From b08df87f5ce2b5cc32d68d7785eab84795370ec2 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 11 Apr 2024 09:40:28 +0200 Subject: fix syncing with custom mutator --- src/afl-fuzz-run.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 1c6ce56a..edcddc8e 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -822,7 +822,7 @@ void sync_fuzzers(afl_state_t *afl) { /* See what happens. We rely on save_if_interesting() to catch major errors and save the test case. */ - (void)write_to_testcase(afl, (void **)&mem, st.st_size, 1); + u32 new_len = write_to_testcase(afl, (void **)&mem, st.st_size, 1); fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); @@ -830,7 +830,7 @@ void sync_fuzzers(afl_state_t *afl) { afl->syncing_party = sd_ent->d_name; afl->queued_imported += - save_if_interesting(afl, mem, st.st_size, fault); + save_if_interesting(afl, mem, new_len, fault); afl->syncing_party = 0; munmap(mem, st.st_size); -- cgit v1.2.3 From d84cc73d1350409b13c035da1179d7fd270041c8 Mon Sep 17 00:00:00 2001 From: Arnaud Rebillout Date: Tue, 16 Apr 2024 14:15:32 +0700 Subject: afl-cc: Add missing debug statement For each path that is tried, there's a debug log printed, _except_ for this one. Fix it. --- src/afl-cc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 45fd398b..5c059be2 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -464,6 +464,8 @@ u8 *find_object(aflcc_state_t *aflcc, u8 *obj) { *slash = 0; tmp = alloc_printf("%s/%s", exepath, obj); + if (aflcc->debug) DEBUGF("Trying %s\n", tmp); + if (!access(tmp, R_OK)) { return tmp; } ck_free(tmp); -- cgit v1.2.3 From 626a4434edc5c0cb381779f7e13d1b54c1ed1738 Mon Sep 17 00:00:00 2001 From: Arnaud Rebillout Date: Tue, 16 Apr 2024 15:10:51 +0700 Subject: afl-cc: Use afl-as (rather than as) to find obj path --- src/afl-cc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 5c059be2..15e0fcc7 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -2475,9 +2475,9 @@ void add_runtime(aflcc_state_t *aflcc) { */ void add_assembler(aflcc_state_t *aflcc) { - u8 *afl_as = find_object(aflcc, "as"); + u8 *afl_as = find_object(aflcc, "afl-as"); - if (!afl_as) FATAL("Cannot find 'as' (symlink to 'afl-as')."); + if (!afl_as) FATAL("Cannot find 'afl-as'."); u8 *slash = strrchr(afl_as, '/'); if (slash) *slash = 0; -- cgit v1.2.3 From 50839cf6e92c5f518ee2045452e7ff7a522c4d6f Mon Sep 17 00:00:00 2001 From: Sonic <50692172+SonicStark@users.noreply.github.com> Date: Wed, 17 Apr 2024 16:34:14 +0700 Subject: afl-cc: Complete fix for afl-as Look for afl-as, and then make sure that there's a 'as' binary in the same directory, that seems to be either a symlink to, or a copy of, afl-as. --- src/afl-cc.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 15e0fcc7..dd4fb4ea 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -17,6 +17,10 @@ #define AFL_MAIN +#ifndef _GNU_SOURCE + #define _GNU_SOURCE 1 +#endif + #include "common.h" #include "config.h" #include "types.h" @@ -32,7 +36,9 @@ #include #include #include +#include #include +#include #if (LLVM_MAJOR - 0 == 0) #undef LLVM_MAJOR @@ -520,7 +526,7 @@ void find_built_deps(aflcc_state_t *aflcc) { char *ptr = NULL; #if defined(__x86_64__) - if ((ptr = find_object(aflcc, "as")) != NULL) { + if ((ptr = find_object(aflcc, "afl-as")) != NULL) { #ifndef __APPLE__ // on OSX clang masquerades as GCC @@ -2482,6 +2488,53 @@ void add_assembler(aflcc_state_t *aflcc) { u8 *slash = strrchr(afl_as, '/'); if (slash) *slash = 0; + // Search for 'as' may be unreliable in some cases (see #2058) + // so use 'afl-as' instead, because 'as' is usually a symbolic link, + // or can be a renamed copy of 'afl-as' created in the same dir. + // Now we should verify if the compiler can find the 'as' we need. + +#define AFL_AS_ERR "(should be a symlink or copy of 'afl-as')" + + u8 *afl_as_dup = alloc_printf("%s/as", afl_as); + + int fd = open(afl_as_dup, O_RDONLY); + if (fd < 0) { PFATAL("Unable to open '%s' " AFL_AS_ERR, afl_as_dup); } + + struct stat st; + if (fstat(fd, &st) < 0) { + + PFATAL("Unable to fstat '%s' " AFL_AS_ERR, afl_as_dup); + + } + + u32 f_len = st.st_size; + + u8 *f_data = mmap(0, f_len, PROT_READ, MAP_PRIVATE, fd, 0); + if (f_data == MAP_FAILED) { + + PFATAL("Unable to mmap file '%s' " AFL_AS_ERR, afl_as_dup); + + } + + close(fd); + + // "AFL_AS" is a const str passed to getenv in afl-as.c + if (!memmem(f_data, f_len, "AFL_AS", strlen("AFL_AS") + 1)) { + + FATAL( + "Looks like '%s' is not a valid symlink or copy of '%s/afl-as'. " + "It is a prerequisite to override system-wide 'as' for " + "instrumentation.", + afl_as_dup, afl_as); + + } + + if (munmap(f_data, f_len)) { PFATAL("unmap() failed"); } + + ck_free(afl_as_dup); + +#undef AFL_AS_ERR + insert_param(aflcc, "-B"); insert_param(aflcc, afl_as); -- cgit v1.2.3 From 58206a3180479416e14ea324607be71ee69caa6f Mon Sep 17 00:00:00 2001 From: Jesse Schwartzentruber Date: Wed, 17 Apr 2024 14:40:41 -0400 Subject: Set explicit visibility on shared memory variables. --- src/afl-cc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index dd4fb4ea..57089ae0 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1591,8 +1591,10 @@ void add_defs_persistent_mode(aflcc_state_t *aflcc) { insert_param(aflcc, "-D__AFL_FUZZ_INIT()=" "int __afl_sharedmem_fuzzing = 1;" - "extern unsigned int *__afl_fuzz_len;" - "extern unsigned char *__afl_fuzz_ptr;" + "extern __attribute__((visibility(\"default\"))) " + "unsigned int *__afl_fuzz_len;" + "extern __attribute__((visibility(\"default\"))) " + "unsigned char *__afl_fuzz_ptr;" "unsigned char __afl_fuzz_alt[1048576];" "unsigned char *__afl_fuzz_alt_ptr = __afl_fuzz_alt;"); -- cgit v1.2.3 From 476aca5b67f2926f0cdc7c50e9669e68cad9a851 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 19 Apr 2024 15:45:00 +0200 Subject: nits --- src/afl-analyze.c | 2 +- src/afl-as.c | 2 +- src/afl-cc.c | 8 ++++---- src/afl-common.c | 2 +- src/afl-forkserver.c | 2 +- src/afl-fuzz-bitmap.c | 2 +- src/afl-fuzz-cmplog.c | 2 +- src/afl-fuzz-extras.c | 2 +- src/afl-fuzz-init.c | 2 +- src/afl-fuzz-mutators.c | 2 +- src/afl-fuzz-one.c | 2 +- src/afl-fuzz-python.c | 2 +- src/afl-fuzz-queue.c | 2 +- src/afl-fuzz-redqueen.c | 2 +- src/afl-fuzz-run.c | 5 ++--- src/afl-fuzz-state.c | 2 +- src/afl-fuzz-stats.c | 9 +++++---- src/afl-gotcpu.c | 2 +- src/afl-ld-lto.c | 2 +- src/afl-sharedmem.c | 2 +- src/afl-showmap.c | 2 +- src/afl-tmin.c | 2 +- 22 files changed, 30 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/afl-analyze.c b/src/afl-analyze.c index 95f32fee..d089cd08 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -5,7 +5,7 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. diff --git a/src/afl-as.c b/src/afl-as.c index 09ba75bf..d4ddb94d 100644 --- a/src/afl-as.c +++ b/src/afl-as.c @@ -5,7 +5,7 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. diff --git a/src/afl-cc.c b/src/afl-cc.c index 57089ae0..202e8145 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -2490,10 +2490,10 @@ void add_assembler(aflcc_state_t *aflcc) { u8 *slash = strrchr(afl_as, '/'); if (slash) *slash = 0; - // Search for 'as' may be unreliable in some cases (see #2058) - // so use 'afl-as' instead, because 'as' is usually a symbolic link, - // or can be a renamed copy of 'afl-as' created in the same dir. - // Now we should verify if the compiler can find the 'as' we need. + // Search for 'as' may be unreliable in some cases (see #2058) + // so use 'afl-as' instead, because 'as' is usually a symbolic link, + // or can be a renamed copy of 'afl-as' created in the same dir. + // Now we should verify if the compiler can find the 'as' we need. #define AFL_AS_ERR "(should be a symlink or copy of 'afl-as')" diff --git a/src/afl-common.c b/src/afl-common.c index 6d915b00..d86b431b 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -5,7 +5,7 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index f28a2a64..149a973e 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -7,7 +7,7 @@ Forkserver design by Jann Horn Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi and Dominik Maier diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index d8561dde..5d4d80af 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -5,7 +5,7 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c index 21f34e12..8c48eb49 100644 --- a/src/afl-fuzz-cmplog.c +++ b/src/afl-fuzz-cmplog.c @@ -7,7 +7,7 @@ Forkserver design by Jann Horn Now maintained by by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c index c06896ef..55b6be04 100644 --- a/src/afl-fuzz-extras.c +++ b/src/afl-fuzz-extras.c @@ -5,7 +5,7 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 21a8ba7e..2a8267cc 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -5,7 +5,7 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index ae4d6668..2f6af4bc 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -5,7 +5,7 @@ Originally written by Shengtuo Hu Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi Dominik Maier diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index d9c074ec..74bb8cbc 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -5,7 +5,7 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c index 16a398fd..873b25e2 100644 --- a/src/afl-fuzz-python.c +++ b/src/afl-fuzz-python.c @@ -5,7 +5,7 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 1ea50418..df4e7d79 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -5,7 +5,7 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index be41d6c4..100b0dd6 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -7,7 +7,7 @@ Forkserver design by Jann Horn Now maintained by by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index edcddc8e..ab96c778 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -5,7 +5,7 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi and Dominik Maier @@ -829,8 +829,7 @@ void sync_fuzzers(afl_state_t *afl) { if (afl->stop_soon) { goto close_sync; } afl->syncing_party = sd_ent->d_name; - afl->queued_imported += - save_if_interesting(afl, mem, new_len, fault); + afl->queued_imported += save_if_interesting(afl, mem, new_len, fault); afl->syncing_party = 0; munmap(mem, st.st_size); diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index c61f00bd..c21ae6be 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -5,7 +5,7 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 7e1a3b92..755e1c50 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -5,8 +5,9 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt and - Andrea Fioraldi + Dominik Meier , + Andrea Fioraldi , and + Heiko Eissfeldt Copyright 2016, 2017 Google Inc. All rights reserved. Copyright 2019-2024 AFLplusplus Project. All rights reserved. @@ -382,8 +383,8 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, ? 0 : (cur_time - afl->last_find_time) / 1000), (runtime - - (afl->calibration_time_us + afl->sync_time_us + afl->trim_time_us) / - 1000) / + ((afl->calibration_time_us + afl->sync_time_us + afl->trim_time_us) / + 1000)) / 1000, afl->calibration_time_us / 1000000, afl->sync_time_us / 1000000, afl->trim_time_us / 1000000, afl->fsrv.total_execs, diff --git a/src/afl-gotcpu.c b/src/afl-gotcpu.c index 7aee2985..6a3bd037 100644 --- a/src/afl-gotcpu.c +++ b/src/afl-gotcpu.c @@ -5,7 +5,7 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c index 513c1ae9..578552ba 100644 --- a/src/afl-ld-lto.c +++ b/src/afl-ld-lto.c @@ -5,7 +5,7 @@ Written by Marc Heuse for AFL++ Maintained by Marc Heuse , - Heiko Eißfeldt + Heiko Eissfeldt Andrea Fioraldi Dominik Maier diff --git a/src/afl-sharedmem.c b/src/afl-sharedmem.c index daea8f46..8f685633 100644 --- a/src/afl-sharedmem.c +++ b/src/afl-sharedmem.c @@ -7,7 +7,7 @@ Forkserver design by Jann Horn Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 20ba5a5e..07a4844a 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -7,7 +7,7 @@ Forkserver design by Jann Horn Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi and Dominik Maier diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 994174ed..23e0ff13 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -7,7 +7,7 @@ Forkserver design by Jann Horn Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi and Dominik Maier -- cgit v1.2.3 From 458b939bc4f0ed4016c2741529435a72283ffc74 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 19 Apr 2024 17:34:50 +0200 Subject: LTO fix --- src/afl-cc.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 202e8145..15a5bd8e 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1269,13 +1269,8 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) { aflcc->instrument_mode == INSTRUMENT_PCGUARD) { aflcc->lto_mode = 1; - // force CFG - // if (!aflcc->instrument_mode) { - aflcc->instrument_mode = INSTRUMENT_PCGUARD; - // } - } else if (aflcc->instrument_mode == INSTRUMENT_CLASSIC) { aflcc->lto_mode = 1; -- cgit v1.2.3 From 951a0e52254d873dd0f1a3a80d9acda44563edd5 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 25 Apr 2024 10:04:58 +0200 Subject: fix AFL_PERSISTENT_RECORD --- src/afl-forkserver.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 149a973e..e5f64c81 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -27,6 +27,9 @@ */ #include "config.h" +#ifdef AFL_PERSISTENT_RECORD + #include "afl-fuzz.h" +#endif #include "types.h" #include "debug.h" #include "common.h" @@ -2078,10 +2081,13 @@ store_persistent_record: { u32 len = fsrv->persistent_record_len[entry]; if (likely(len && data)) { - snprintf(fn, sizeof(fn), persistent_out_fmt, fsrv->persistent_record_dir, - fsrv->persistent_record_cnt, writecnt++, - afl->file_extension ? "." : "", - afl->file_extension ? (const char *)afl->file_extension : ""); + snprintf( + fn, sizeof(fn), persistent_out_fmt, fsrv->persistent_record_dir, + fsrv->persistent_record_cnt, writecnt++, + ((afl_state_t *)(fsrv->afl_ptr))->file_extension ? "." : "", + ((afl_state_t *)(fsrv->afl_ptr))->file_extension + ? (const char *)((afl_state_t *)(fsrv->afl_ptr))->file_extension + : ""); int fd = open(fn, O_CREAT | O_TRUNC | O_WRONLY, 0644); if (fd >= 0) { -- cgit v1.2.3 From 526dbe8f167f2ee9b11121c8b2b413b7b59fa1ff Mon Sep 17 00:00:00 2001 From: Yiyi Wang <91304853+ahuo1@users.noreply.github.com> Date: Thu, 25 Apr 2024 21:28:58 +0800 Subject: fix: initialize n_fuzz_entry in perform_dry_run. --- src/afl-fuzz-init.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 2a8267cc..503f1ca8 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -914,6 +914,11 @@ void perform_dry_run(afl_state_t *afl) { res = calibrate_case(afl, q, use_mem, 0, 1); + /* For AFLFast schedules we update the queue entry */ + if (likely(q->exec_cksum)) { + q->n_fuzz_entry = q->exec_cksum % N_FUZZ_SIZE; + } + if (afl->stop_soon) { return; } if (res == afl->crash_mode || res == FSRV_RUN_NOBITS) { -- cgit v1.2.3 From 43e9a139214d57888c8f234ee44044de5108f8ea Mon Sep 17 00:00:00 2001 From: Yiyi Wang <91304853+ahuo1@users.noreply.github.com> Date: Fri, 26 Apr 2024 07:45:58 +0800 Subject: add schedule check. --- src/afl-fuzz-init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 503f1ca8..b844123d 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -915,7 +915,7 @@ void perform_dry_run(afl_state_t *afl) { res = calibrate_case(afl, q, use_mem, 0, 1); /* For AFLFast schedules we update the queue entry */ - if (likely(q->exec_cksum)) { + if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE) && likely(q->exec_cksum)) { q->n_fuzz_entry = q->exec_cksum % N_FUZZ_SIZE; } -- cgit v1.2.3 From 70c60cfba798d4c7349280746e9f2488778be25e Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 26 Apr 2024 16:14:45 +0200 Subject: work with spaces in filenames --- src/afl-fuzz-init.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index b844123d..2d540eb1 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -459,6 +459,24 @@ void bind_to_free_cpu(afl_state_t *afl) { #endif /* HAVE_AFFINITY */ +/* transforms spaces in a string to underscores (inplace) */ + +static void no_spaces(u8 *string) { + + if (string) { + + u8 *ptr = string; + while (*ptr != 0) { + + if (*ptr == ' ') { *ptr = '_'; } + ++ptr; + + } + + } + +} + /* Shuffle an array of pointers. Might be slightly biased. */ static void shuffle_ptrs(afl_state_t *afl, void **ptrs, u32 cnt) { @@ -1381,11 +1399,11 @@ void perform_dry_run(afl_state_t *afl) { static void link_or_copy(u8 *old_path, u8 *new_path) { s32 i = link(old_path, new_path); + if (!i) { return; } + s32 sfd, dfd; u8 *tmp; - if (!i) { return; } - sfd = open(old_path, O_RDONLY); if (sfd < 0) { PFATAL("Unable to open '%s'", old_path); } @@ -1495,6 +1513,9 @@ void pivot_inputs(afl_state_t *afl) { afl->fsrv.total_execs, use_name, afl->file_extension ? "." : "", afl->file_extension ? (const char *)afl->file_extension : ""); + u8 *pos = strrchr(nfn, '/'); + no_spaces(pos + 30); + #else nfn = alloc_printf( -- cgit v1.2.3 From 58abcceff5af0ad414a10eee928f0f453aed3764 Mon Sep 17 00:00:00 2001 From: acture Date: Sun, 28 Apr 2024 16:24:52 +0800 Subject: Bug fix: Removed the redundant `id` field from the debug output in the afl-fuzz-redqueen.c file since cmp_header no longer have this field. --- src/afl-fuzz-redqueen.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 100b0dd6..cfa57c1d 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -2764,15 +2764,15 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, #ifdef _DEBUG u32 j; struct cmp_header *hh = &afl->orig_cmp_map->headers[key]; - fprintf(stderr, "RTN N hits=%u id=%u shape=%u attr=%u v0=", h->hits, h->id, + fprintf(stderr, "RTN N hits=%u shape=%u attr=%u v0=", h->hits, hshape, h->attribute); for (j = 0; j < 8; j++) fprintf(stderr, "%02x", o->v0[j]); fprintf(stderr, " v1="); for (j = 0; j < 8; j++) fprintf(stderr, "%02x", o->v1[j]); - fprintf(stderr, "\nRTN O hits=%u id=%u shape=%u attr=%u o0=", hh->hits, - hh->id, hshape, hh->attribute); + fprintf(stderr, "\nRTN O hits=%u shape=%u attr=%u o0=", hh->hits, + hshape, hh->attribute); for (j = 0; j < 8; j++) fprintf(stderr, "%02x", orig_o->v0[j]); fprintf(stderr, " o1="); @@ -3273,4 +3273,3 @@ exit_its: return r; } - -- cgit v1.2.3 From 5d623a27edcd4e6608178f80c7e29ede73138db6 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 30 Apr 2024 11:59:42 +0200 Subject: try enhanced asan support --- src/afl-cc.c | 8 +++++++- src/afl-common.c | 7 ++++--- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 15a5bd8e..fa3318de 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1911,7 +1911,13 @@ void add_sanitizers(aflcc_state_t *aflcc, char **envp) { } add_defs_fortify(aflcc, 0); - if (!aflcc->have_asan) { insert_param(aflcc, "-fsanitize=address"); } + if (!aflcc->have_asan) { + + insert_param(aflcc, "-fsanitize=address"); + insert_param(aflcc, "-fno-common"); + + } + aflcc->have_asan = 1; } else if (getenv("AFL_USE_MSAN") || aflcc->have_msan) { diff --git a/src/afl-common.c b/src/afl-common.c index d86b431b..9a27824d 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -108,9 +108,10 @@ void set_sanitizer_defaults() { u8 *have_lsan_options = getenv("LSAN_OPTIONS"); u8 have_san_options = 0; u8 default_options[1024] = - "detect_odr_violation=0:abort_on_error=1:symbolize=0:allocator_may_" - "return_null=1:handle_segv=0:handle_sigbus=0:handle_abort=0:handle_" - "sigfpe=0:handle_sigill=0:"; + "detect_odr_violation=0:abort_on_error=1:symbolize=0:" + "allocator_may_return_null=1:handle_segv=0:handle_sigbus=0:" + "handle_abort=0:handle_sigfpe=0:handle_sigill=0:" + "detect_stack_use_after_return=0:check_initialization_order=0:"; if (have_asan_options || have_ubsan_options || have_msan_options || have_lsan_options) { -- cgit v1.2.3 From 26eaf53a832be0b12dadbbd290b4a7e676818347 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 2 May 2024 08:35:24 +0200 Subject: AFL_DISABLE_REDUNDANT --- src/afl-fuzz-init.c | 7 +++++-- src/afl-fuzz-queue.c | 1 + src/afl-fuzz-redqueen.c | 9 +++++---- src/afl-fuzz-state.c | 7 +++++++ src/afl-fuzz.c | 1 + 5 files changed, 19 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 2d540eb1..b3fe9318 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -933,10 +933,13 @@ void perform_dry_run(afl_state_t *afl) { res = calibrate_case(afl, q, use_mem, 0, 1); /* For AFLFast schedules we update the queue entry */ - if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE) && likely(q->exec_cksum)) { + if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE) && + likely(q->exec_cksum)) { + q->n_fuzz_entry = q->exec_cksum % N_FUZZ_SIZE; + } - + if (afl->stop_soon) { return; } if (res == afl->crash_mode || res == FSRV_RUN_NOBITS) { diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index df4e7d79..5987ad0c 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -370,6 +370,7 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) { s32 fd; + if (unlikely(afl->afl_env.afl_disable_redundant)) { q->disabled = 1; } fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); if (fd < 0) { PFATAL("Unable to create '%s'", fn); } close(fd); diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index cfa57c1d..9316da71 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -2764,15 +2764,15 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, #ifdef _DEBUG u32 j; struct cmp_header *hh = &afl->orig_cmp_map->headers[key]; - fprintf(stderr, "RTN N hits=%u shape=%u attr=%u v0=", h->hits, - hshape, h->attribute); + fprintf(stderr, "RTN N hits=%u shape=%u attr=%u v0=", h->hits, hshape, + h->attribute); for (j = 0; j < 8; j++) fprintf(stderr, "%02x", o->v0[j]); fprintf(stderr, " v1="); for (j = 0; j < 8; j++) fprintf(stderr, "%02x", o->v1[j]); - fprintf(stderr, "\nRTN O hits=%u shape=%u attr=%u o0=", hh->hits, - hshape, hh->attribute); + fprintf(stderr, "\nRTN O hits=%u shape=%u attr=%u o0=", hh->hits, hshape, + hh->attribute); for (j = 0; j < 8; j++) fprintf(stderr, "%02x", orig_o->v0[j]); fprintf(stderr, " o1="); @@ -3273,3 +3273,4 @@ exit_its: return r; } + diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index c21ae6be..543fdc1c 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -293,6 +293,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_cmplog_only_new = get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_DISABLE_REDUNDANT", + + afl_environment_variable_len)) { + + afl->afl_env.afl_disable_redundant = + get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_NO_STARTUP_CALIBRATION", afl_environment_variable_len)) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 00d24ab1..329ce942 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -264,6 +264,7 @@ static void usage(u8 *argv0, int more_help) { "AFL_CYCLE_SCHEDULES: after completing a cycle, switch to a different -p schedule\n" "AFL_DEBUG: extra debugging output for Python mode trimming\n" "AFL_DEBUG_CHILD: do not suppress stdout/stderr from target\n" + "AFL_DISABLE_REDUNDANT: disable any queue item that is redundant\n" "AFL_DISABLE_TRIM: disable the trimming of test cases\n" "AFL_DUMB_FORKSRV: use fork server without feedback from target\n" "AFL_EXIT_WHEN_DONE: exit when all inputs are run and no new finds are found\n" -- cgit v1.2.3 From ac6ccd53dff5a43050ad8a0922c8fa47e69333a8 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 7 May 2024 16:46:15 +0200 Subject: stat update during syncing --- src/afl-fuzz-init.c | 9 ++++++++- src/afl-fuzz-run.c | 3 +++ 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index b3fe9318..01d0730d 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -577,6 +577,8 @@ void read_foreign_testcases(afl_state_t *afl, int first) { afl->stage_cur = 0; afl->stage_max = 0; + show_stats(afl); + for (i = 0; i < (u32)nl_cnt; ++i) { struct stat st; @@ -655,7 +657,12 @@ void read_foreign_testcases(afl_state_t *afl, int first) { munmap(mem, st.st_size); close(fd); - if (st.st_mtime > mtime_max) mtime_max = st.st_mtime; + if (st.st_mtime > mtime_max) { + + mtime_max = st.st_mtime; + show_stats(afl); + + } } diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index ab96c778..ed7cb4ce 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -771,6 +771,8 @@ void sync_fuzzers(afl_state_t *afl) { afl->stage_cur = 0; afl->stage_max = 0; + show_stats(afl); + /* For every file queued by this fuzzer, parse ID and see if we have looked at it before; exec a test case if not. */ @@ -830,6 +832,7 @@ void sync_fuzzers(afl_state_t *afl) { afl->syncing_party = sd_ent->d_name; afl->queued_imported += save_if_interesting(afl, mem, new_len, fault); + show_stats(afl); afl->syncing_party = 0; munmap(mem, st.st_size); -- cgit v1.2.3 From 4d4880b428c485a33eed924a488dc7c3542dbcf4 Mon Sep 17 00:00:00 2001 From: Arnaud Rebillout Date: Fri, 10 May 2024 23:45:46 +0700 Subject: afl-cc: Re-enable i386 Was disabled in 136febaf6855ac1e04c8ea4ecbcb84eb42de2143 Closes: #2081 --- src/afl-cc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index fa3318de..7acee8e4 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -525,7 +525,7 @@ void find_built_deps(aflcc_state_t *aflcc) { char *ptr = NULL; -#if defined(__x86_64__) +#if defined(__x86_64__) || defined(__i386__) if ((ptr = find_object(aflcc, "afl-as")) != NULL) { #ifndef __APPLE__ -- cgit v1.2.3 From c03f2897d081b2bf41e179a48d758f1f400b5929 Mon Sep 17 00:00:00 2001 From: Samuel Moelius Date: Fri, 10 May 2024 16:55:32 -0400 Subject: Add `AFL_SHA1_FILENAMES` option --- src/afl-fuzz-bitmap.c | 91 +++++++++++---- src/afl-fuzz-init.c | 78 +++++++++---- src/afl-fuzz-queue.c | 5 +- src/afl-fuzz-state.c | 7 ++ src/afl-performance.c | 310 ++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 439 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 5d4d80af..03bc5d6c 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -527,12 +527,24 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { #ifndef SIMPLE_FILES - queue_fn = alloc_printf( - "%s/queue/id:%06u,%s%s%s", afl->out_dir, afl->queued_items, - describe_op(afl, new_bits + is_timeout, - NAME_MAX - strlen("id:000000,")), - afl->file_extension ? "." : "", - afl->file_extension ? (const char *)afl->file_extension : ""); + if (!afl->afl_env.afl_sha1_filenames) { + + queue_fn = alloc_printf( + "%s/queue/id:%06u,%s%s%s", afl->out_dir, afl->queued_items, + describe_op(afl, new_bits + is_timeout, + NAME_MAX - strlen("id:000000,")), + afl->file_extension ? "." : "", + afl->file_extension ? (const char *)afl->file_extension : ""); + + } else { + + const char *hex = sha1_hex(mem, len); + queue_fn = alloc_printf( + "%s/queue/%s%s%s", afl->out_dir, hex, afl->file_extension ? "." : "", + afl->file_extension ? (const char *)afl->file_extension : ""); + ck_free((char *)hex); + + } #else @@ -542,10 +554,14 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { afl->file_extension ? (const char *)afl->file_extension : ""); #endif /* ^!SIMPLE_FILES */ - fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); - if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", queue_fn); } - ck_write(fd, mem, len, queue_fn); - close(fd); + fd = permissive_create(afl, queue_fn); + if (likely(fd >= 0)) { + + ck_write(fd, mem, len, queue_fn); + close(fd); + + } + add_to_queue(afl, queue_fn, len, 0); if (unlikely(afl->fuzz_mode) && @@ -743,11 +759,23 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { #ifndef SIMPLE_FILES - snprintf(fn, PATH_MAX, "%s/hangs/id:%06llu,%s%s%s", afl->out_dir, - afl->saved_hangs, - describe_op(afl, 0, NAME_MAX - strlen("id:000000,")), - afl->file_extension ? "." : "", - afl->file_extension ? (const char *)afl->file_extension : ""); + if (!afl->afl_env.afl_sha1_filenames) { + + snprintf(fn, PATH_MAX, "%s/hangs/id:%06llu,%s%s%s", afl->out_dir, + afl->saved_hangs, + describe_op(afl, 0, NAME_MAX - strlen("id:000000,")), + afl->file_extension ? "." : "", + afl->file_extension ? (const char *)afl->file_extension : ""); + + } else { + + const char *hex = sha1_hex(mem, len); + snprintf(fn, PATH_MAX, "%s/hangs/%s%s%s", afl->out_dir, hex, + afl->file_extension ? "." : "", + afl->file_extension ? (const char *)afl->file_extension : ""); + ck_free((char *)hex); + + } #else @@ -799,11 +827,23 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { #ifndef SIMPLE_FILES - snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s%s", - afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal, - describe_op(afl, 0, NAME_MAX - strlen("id:000000,sig:00,")), - afl->file_extension ? "." : "", - afl->file_extension ? (const char *)afl->file_extension : ""); + if (!afl->afl_env.afl_sha1_filenames) { + + snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s%s", + afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal, + describe_op(afl, 0, NAME_MAX - strlen("id:000000,sig:00,")), + afl->file_extension ? "." : "", + afl->file_extension ? (const char *)afl->file_extension : ""); + + } else { + + const char *hex = sha1_hex(mem, len); + snprintf(fn, PATH_MAX, "%s/crashes/%s%s%s", afl->out_dir, hex, + afl->file_extension ? "." : "", + afl->file_extension ? (const char *)afl->file_extension : ""); + ck_free((char *)hex); + + } #else @@ -873,10 +913,13 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { /* If we're here, we apparently want to save the crash or hang test case, too. */ - fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); - if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", fn); } - ck_write(fd, mem, len, fn); - close(fd); + fd = permissive_create(afl, fn); + if (fd >= 0) { + + ck_write(fd, mem, len, fn); + close(fd); + + } #ifdef __linux__ if (afl->fsrv.nyx_mode && fault == FSRV_RUN_CRASH) { diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 01d0730d..7310e49f 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1190,14 +1190,27 @@ void perform_dry_run(afl_state_t *afl) { #ifndef SIMPLE_FILES - snprintf( - crash_fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s%s%s", - afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal, - describe_op( - afl, 0, - NAME_MAX - strlen("id:000000,sig:00,") - strlen(use_name)), - use_name, afl->file_extension ? "." : "", - afl->file_extension ? (const char *)afl->file_extension : ""); + if (!afl->afl_env.afl_sha1_filenames) { + + snprintf( + crash_fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s%s%s", + afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal, + describe_op( + afl, 0, + NAME_MAX - strlen("id:000000,sig:00,") - strlen(use_name)), + use_name, afl->file_extension ? "." : "", + afl->file_extension ? (const char *)afl->file_extension : ""); + + } else { + + const char *hex = sha1_hex(use_mem, read_len); + snprintf( + crash_fn, PATH_MAX, "%s/crashes/%s%s%s", afl->out_dir, hex, + afl->file_extension ? "." : "", + afl->file_extension ? (const char *)afl->file_extension : ""); + ck_free((char *)hex); + + } #else @@ -1518,10 +1531,23 @@ void pivot_inputs(afl_state_t *afl) { } - nfn = alloc_printf( - "%s/queue/id:%06u,time:0,execs:%llu,orig:%s%s%s", afl->out_dir, id, - afl->fsrv.total_execs, use_name, afl->file_extension ? "." : "", - afl->file_extension ? (const char *)afl->file_extension : ""); + if (!afl->afl_env.afl_sha1_filenames) { + + nfn = alloc_printf( + "%s/queue/id:%06u,time:0,execs:%llu,orig:%s%s%s", afl->out_dir, id, + afl->fsrv.total_execs, use_name, afl->file_extension ? "." : "", + afl->file_extension ? (const char *)afl->file_extension : ""); + + } else { + + const char *hex = sha1_hex_for_file(q->fname, q->len); + nfn = alloc_printf( + "%s/queue/%s%s%s", afl->out_dir, hex, + afl->file_extension ? "." : "", + afl->file_extension ? (const char *)afl->file_extension : ""); + ck_free((char *)hex); + + } u8 *pos = strrchr(nfn, '/'); no_spaces(pos + 30); @@ -1738,10 +1764,11 @@ double get_runnable_processes(void) { void nuke_resume_dir(afl_state_t *afl) { - u8 *fn; + u8 *const case_prefix = afl->afl_env.afl_sha1_filenames ? "" : CASE_PREFIX; + u8 *fn; fn = alloc_printf("%s/_resume/.state/deterministic_done", afl->out_dir); - if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } + if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; } ck_free(fn); fn = alloc_printf("%s/_resume/.state/auto_extras", afl->out_dir); @@ -1749,11 +1776,11 @@ void nuke_resume_dir(afl_state_t *afl) { ck_free(fn); fn = alloc_printf("%s/_resume/.state/redundant_edges", afl->out_dir); - if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } + if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; } ck_free(fn); fn = alloc_printf("%s/_resume/.state/variable_behavior", afl->out_dir); - if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } + if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; } ck_free(fn); fn = alloc_printf("%s/_resume/.state", afl->out_dir); @@ -1761,7 +1788,7 @@ void nuke_resume_dir(afl_state_t *afl) { ck_free(fn); fn = alloc_printf("%s/_resume", afl->out_dir); - if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } + if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; } ck_free(fn); return; @@ -1778,8 +1805,9 @@ dir_cleanup_failed: static void handle_existing_out_dir(afl_state_t *afl) { - FILE *f; - u8 *fn = alloc_printf("%s/fuzzer_stats", afl->out_dir); + u8 *const case_prefix = afl->afl_env.afl_sha1_filenames ? "" : CASE_PREFIX; + FILE *f; + u8 *fn = alloc_printf("%s/fuzzer_stats", afl->out_dir); /* See if the output directory is locked. If yes, bail out. If not, create a lock that will persist for the lifetime of the process @@ -1901,7 +1929,7 @@ static void handle_existing_out_dir(afl_state_t *afl) { /* Next, we need to clean up out_dir>/queue/.state/ subdirectories: */ fn = alloc_printf("%s/queue/.state/deterministic_done", afl->out_dir); - if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } + if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; } ck_free(fn); fn = alloc_printf("%s/queue/.state/auto_extras", afl->out_dir); @@ -1909,11 +1937,11 @@ static void handle_existing_out_dir(afl_state_t *afl) { ck_free(fn); fn = alloc_printf("%s/queue/.state/redundant_edges", afl->out_dir); - if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } + if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; } ck_free(fn); fn = alloc_printf("%s/queue/.state/variable_behavior", afl->out_dir); - if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } + if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; } ck_free(fn); /* Then, get rid of the .state subdirectory itself (should be empty by now) @@ -1924,7 +1952,7 @@ static void handle_existing_out_dir(afl_state_t *afl) { ck_free(fn); fn = alloc_printf("%s/queue", afl->out_dir); - if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } + if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; } ck_free(fn); /* All right, let's do out_dir>/crashes/id:* and @@ -1971,7 +1999,7 @@ static void handle_existing_out_dir(afl_state_t *afl) { #ifdef AFL_PERSISTENT_RECORD delete_files(fn, RECORD_PREFIX); #endif - if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } + if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; } ck_free(fn); fn = alloc_printf("%s/hangs", afl->out_dir); @@ -2006,7 +2034,7 @@ static void handle_existing_out_dir(afl_state_t *afl) { #ifdef AFL_PERSISTENT_RECORD delete_files(fn, RECORD_PREFIX); #endif - if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } + if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; } ck_free(fn); /* And now, for some finishing touches. */ diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 5987ad0c..2318df60 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -371,9 +371,8 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) { s32 fd; if (unlikely(afl->afl_env.afl_disable_redundant)) { q->disabled = 1; } - fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); - if (fd < 0) { PFATAL("Unable to create '%s'", fn); } - close(fd); + fd = permissive_create(afl, fn); + if (fd >= 0) { close(fd); } } else { diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 543fdc1c..74edaddf 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -626,6 +626,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { } + } else if (!strncmp(env, "AFL_SHA1_FILENAMES", + + afl_environment_variable_len)) { + + afl->afl_env.afl_sha1_filenames = + get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } } else { diff --git a/src/afl-performance.c b/src/afl-performance.c index f730ca53..6c6e3c8b 100644 --- a/src/afl-performance.c +++ b/src/afl-performance.c @@ -95,3 +95,313 @@ inline u64 hash64(u8 *key, u32 len, u64 seed) { } +// Public domain SHA1 implementation copied from: +// https://github.com/x42/liboauth/blob/7001b8256cd654952ec2515b055d2c5b243be600/src/sha1.c + +/* This code is public-domain - it is based on libcrypt + * placed in the public domain by Wei Dai and other contributors. + */ +// gcc -Wall -DSHA1TEST -o sha1test sha1.c && ./sha1test + +#include +#include + +#ifdef __BIG_ENDIAN__ + #define SHA_BIG_ENDIAN +#elif defined __LITTLE_ENDIAN__ +/* override */ +#elif defined __BYTE_ORDER + #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + #define SHA_BIG_ENDIAN + #endif +#else // ! defined __LITTLE_ENDIAN__ + #include // machine/endian.h + #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + #define SHA_BIG_ENDIAN + #endif +#endif + +/* header */ + +#define HASH_LENGTH 20 +#define BLOCK_LENGTH 64 + +typedef struct sha1nfo { + + uint32_t buffer[BLOCK_LENGTH / 4]; + uint32_t state[HASH_LENGTH / 4]; + uint32_t byteCount; + uint8_t bufferOffset; + uint8_t keyBuffer[BLOCK_LENGTH]; + uint8_t innerHash[HASH_LENGTH]; + +} sha1nfo; + +/* public API - prototypes - TODO: doxygen*/ + +/** + */ +void sha1_init(sha1nfo *s); +/** + */ +void sha1_writebyte(sha1nfo *s, uint8_t data); +/** + */ +void sha1_write(sha1nfo *s, const char *data, size_t len); +/** + */ +uint8_t *sha1_result(sha1nfo *s); +/** + */ +void sha1_initHmac(sha1nfo *s, const uint8_t *key, int keyLength); +/** + */ +uint8_t *sha1_resultHmac(sha1nfo *s); + +/* code */ +#define SHA1_K0 0x5a827999 +#define SHA1_K20 0x6ed9eba1 +#define SHA1_K40 0x8f1bbcdc +#define SHA1_K60 0xca62c1d6 + +void sha1_init(sha1nfo *s) { + + s->state[0] = 0x67452301; + s->state[1] = 0xefcdab89; + s->state[2] = 0x98badcfe; + s->state[3] = 0x10325476; + s->state[4] = 0xc3d2e1f0; + s->byteCount = 0; + s->bufferOffset = 0; + +} + +uint32_t sha1_rol32(uint32_t number, uint8_t bits) { + + return ((number << bits) | (number >> (32 - bits))); + +} + +void sha1_hashBlock(sha1nfo *s) { + + uint8_t i; + uint32_t a, b, c, d, e, t; + + a = s->state[0]; + b = s->state[1]; + c = s->state[2]; + d = s->state[3]; + e = s->state[4]; + for (i = 0; i < 80; i++) { + + if (i >= 16) { + + t = s->buffer[(i + 13) & 15] ^ s->buffer[(i + 8) & 15] ^ + s->buffer[(i + 2) & 15] ^ s->buffer[i & 15]; + s->buffer[i & 15] = sha1_rol32(t, 1); + + } + + if (i < 20) { + + t = (d ^ (b & (c ^ d))) + SHA1_K0; + + } else if (i < 40) { + + t = (b ^ c ^ d) + SHA1_K20; + + } else if (i < 60) { + + t = ((b & c) | (d & (b | c))) + SHA1_K40; + + } else { + + t = (b ^ c ^ d) + SHA1_K60; + + } + + t += sha1_rol32(a, 5) + e + s->buffer[i & 15]; + e = d; + d = c; + c = sha1_rol32(b, 30); + b = a; + a = t; + + } + + s->state[0] += a; + s->state[1] += b; + s->state[2] += c; + s->state[3] += d; + s->state[4] += e; + +} + +void sha1_addUncounted(sha1nfo *s, uint8_t data) { + + uint8_t *const b = (uint8_t *)s->buffer; +#ifdef SHA_BIG_ENDIAN + b[s->bufferOffset] = data; +#else + b[s->bufferOffset ^ 3] = data; +#endif + s->bufferOffset++; + if (s->bufferOffset == BLOCK_LENGTH) { + + sha1_hashBlock(s); + s->bufferOffset = 0; + + } + +} + +void sha1_writebyte(sha1nfo *s, uint8_t data) { + + ++s->byteCount; + sha1_addUncounted(s, data); + +} + +void sha1_write(sha1nfo *s, const char *data, size_t len) { + + for (; len--;) + sha1_writebyte(s, (uint8_t)*data++); + +} + +void sha1_pad(sha1nfo *s) { + + // Implement SHA-1 padding (fips180-2 §5.1.1) + + // Pad with 0x80 followed by 0x00 until the end of the block + sha1_addUncounted(s, 0x80); + while (s->bufferOffset != 56) + sha1_addUncounted(s, 0x00); + + // Append length in the last 8 bytes + sha1_addUncounted(s, 0); // We're only using 32 bit lengths + sha1_addUncounted(s, 0); // But SHA-1 supports 64 bit lengths + sha1_addUncounted(s, 0); // So zero pad the top bits + sha1_addUncounted(s, s->byteCount >> 29); // Shifting to multiply by 8 + sha1_addUncounted( + s, s->byteCount >> 21); // as SHA-1 supports bitstreams as well as + sha1_addUncounted(s, s->byteCount >> 13); // byte. + sha1_addUncounted(s, s->byteCount >> 5); + sha1_addUncounted(s, s->byteCount << 3); + +} + +uint8_t *sha1_result(sha1nfo *s) { + + // Pad to complete the last block + sha1_pad(s); + +#ifndef SHA_BIG_ENDIAN + // Swap byte order back + int i; + for (i = 0; i < 5; i++) { + + s->state[i] = (((s->state[i]) << 24) & 0xff000000) | + (((s->state[i]) << 8) & 0x00ff0000) | + (((s->state[i]) >> 8) & 0x0000ff00) | + (((s->state[i]) >> 24) & 0x000000ff); + + } + +#endif + + // Return pointer to hash (20 characters) + return (uint8_t *)s->state; + +} + +#define HMAC_IPAD 0x36 +#define HMAC_OPAD 0x5c + +void sha1_initHmac(sha1nfo *s, const uint8_t *key, int keyLength) { + + uint8_t i; + memset(s->keyBuffer, 0, BLOCK_LENGTH); + if (keyLength > BLOCK_LENGTH) { + + // Hash long keys + sha1_init(s); + for (; keyLength--;) + sha1_writebyte(s, *key++); + memcpy(s->keyBuffer, sha1_result(s), HASH_LENGTH); + + } else { + + // Block length keys are used as is + memcpy(s->keyBuffer, key, keyLength); + + } + + // Start inner hash + sha1_init(s); + for (i = 0; i < BLOCK_LENGTH; i++) { + + sha1_writebyte(s, s->keyBuffer[i] ^ HMAC_IPAD); + + } + +} + +uint8_t *sha1_resultHmac(sha1nfo *s) { + + uint8_t i; + // Complete inner hash + memcpy(s->innerHash, sha1_result(s), HASH_LENGTH); + // Calculate outer hash + sha1_init(s); + for (i = 0; i < BLOCK_LENGTH; i++) + sha1_writebyte(s, s->keyBuffer[i] ^ HMAC_OPAD); + for (i = 0; i < HASH_LENGTH; i++) + sha1_writebyte(s, s->innerHash[i]); + return sha1_result(s); + +} + +// End public domain SHA1 implementation + +void sha1(const u8 *data, size_t len, u8 *out) { + + sha1nfo s; + sha1_init(&s); + sha1_write(&s, (const char *)data, len); + memcpy(out, sha1_result(&s), HASH_LENGTH); + +} + +char *sha1_hex(const u8 *data, size_t len) { + + u8 digest[HASH_LENGTH]; + sha1(data, len, digest); + u8 *hex = ck_alloc(HASH_LENGTH * 2 + 1); + for (size_t i = 0; i < HASH_LENGTH; ++i) { + + sprintf((char *)(hex + i * 2), "%02x", digest[i]); + + } + + return hex; + +} + +char *sha1_hex_for_file(const char *fname, u32 len) { + + int fd = open(fname, O_RDONLY); + if (fd < 0) { PFATAL("Unable to open '%s'", fname); } + + u32 read_len = MIN(len, (u32)MAX_FILE); + u8 *tmp = ck_alloc(read_len); + ck_read(fd, tmp, read_len, fname); + + close(fd); + + char *hex = sha1_hex(tmp, read_len); + ck_free(tmp); + return hex; + +} + -- cgit v1.2.3 From b282ce999d2ab9428210deb0e838f45a6a534084 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 13 May 2024 13:42:58 +0200 Subject: post_process after trim --- src/afl-fuzz-run.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) (limited to 'src') diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index ed7cb4ce..2a55da00 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -1028,6 +1028,68 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { if (needs_write) { + // run afl_custom_post_process + + if (unlikely(afl->custom_mutators_count) && + likely(!afl->afl_env.afl_post_process_keep_original)) { + + ssize_t new_size = q->len; + u8 *new_mem = in_buf; + u8 *new_buf = NULL; + + LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { + + if (el->afl_custom_post_process) { + + new_size = el->afl_custom_post_process(el->data, new_mem, new_size, + &new_buf); + + if (unlikely(!new_buf || new_size <= 0)) { + + new_size = 0; + new_buf = new_mem; + + } else { + + new_mem = new_buf; + + } + + } + + }); + + if (unlikely(!new_size)) { + + new_size = q->len; + new_mem = in_buf; + + } + + if (unlikely(new_size < afl->min_length)) { + + new_size = afl->min_length; + + } else if (unlikely(new_size > afl->max_length)) { + + new_size = afl->max_length; + + } + + q->len = new_size; + + if (new_mem != in_buf && new_mem != NULL) { + + new_buf = afl_realloc(AFL_BUF_PARAM(out_scratch), new_size); + if (unlikely(!new_buf)) { PFATAL("alloc"); } + memcpy(new_buf, new_mem, new_size); + + in_buf = new_buf; + + } + + } + s32 fd; if (unlikely(afl->no_unlink)) { -- cgit v1.2.3 From 622474e9e45056c21abf4f8f39f2a6f7cc01053f Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 13 May 2024 19:51:38 +0200 Subject: disable -> no variants --- src/afl-fuzz-state.c | 3 +++ src/afl-fuzz.c | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 74edaddf..333d57b2 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -295,6 +295,9 @@ void read_afl_environment(afl_state_t *afl, char **envp) { } else if (!strncmp(env, "AFL_DISABLE_REDUNDANT", + afl_environment_variable_len) || + !strncmp(env, "AFL_NO_REDUNDANT", + afl_environment_variable_len)) { afl->afl_env.afl_disable_redundant = diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 329ce942..bb9c270f 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1565,7 +1565,11 @@ int main(int argc, char **argv_orig, char **envp) { setenv("__AFL_OUT_DIR", afl->out_dir, 1); - if (get_afl_env("AFL_DISABLE_TRIM")) { afl->disable_trim = 1; } + if (get_afl_env("AFL_DISABLE_TRIM") || get_afl_env("AFL_NO_TRIM")) { + + afl->disable_trim = 1; + + } if (getenv("AFL_NO_UI") && getenv("AFL_FORCE_UI")) { -- cgit v1.2.3 From 0cf78b77483887004bdf376c92918cded913bb70 Mon Sep 17 00:00:00 2001 From: Bet4 <0xbet4@gmail.com> Date: Tue, 14 May 2024 17:17:58 +0800 Subject: Fix bug of afl-showmap in collect_coverage mode --- src/afl-showmap.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'src') diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 07a4844a..4ce01444 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -178,7 +178,7 @@ fsrv_run_result_t fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv, void classify_counts(afl_forkserver_t *fsrv) { u8 *mem = fsrv->trace_bits; - const u8 *map = binary_mode ? count_class_binary : count_class_human; + const u8 *map = (binary_mode || collect_coverage) ? count_class_binary : count_class_human; u32 i = map_size; @@ -242,9 +242,6 @@ static void analyze_results(afl_forkserver_t *fsrv) { if (fsrv->trace_bits[i]) { - total += fsrv->trace_bits[i]; - if (fsrv->trace_bits[i] > highest) highest = fsrv->trace_bits[i]; - // if (!coverage_map[i]) { coverage_map[i] = 1; } coverage_map[i] |= fsrv->trace_bits[i]; } @@ -1677,7 +1674,6 @@ int main(int argc, char **argv_orig, char **envp) { if ((coverage_map = (u8 *)malloc(map_size + 64)) == NULL) FATAL("coult not grab memory"); edges_only = false; - raw_instr_output = true; } -- cgit v1.2.3 From ab36756061b52c8f6bf5d4650ebf42d7c31d8cd9 Mon Sep 17 00:00:00 2001 From: nj00001 <42004790+nj00001@users.noreply.github.com> Date: Tue, 14 May 2024 18:27:12 +0800 Subject: change MAX_FILE to fsrv->max_length --- src/afl-forkserver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index e5f64c81..beb6bdeb 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -578,7 +578,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, void *nyx_config = fsrv->nyx_handlers->nyx_config_load(fsrv->target_path); fsrv->nyx_handlers->nyx_config_set_workdir_path(nyx_config, workdir_path); - fsrv->nyx_handlers->nyx_config_set_input_buffer_size(nyx_config, MAX_FILE); + fsrv->nyx_handlers->nyx_config_set_input_buffer_size(nyx_config, fsrv->max_length); fsrv->nyx_handlers->nyx_config_set_input_buffer_write_protection(nyx_config, true); -- cgit v1.2.3 From 5ee5564ae2981f83c76d42d2c6abd9ce88bc7a17 Mon Sep 17 00:00:00 2001 From: nj00001 <42004790+nj00001@users.noreply.github.com> Date: Tue, 14 May 2024 18:28:18 +0800 Subject: backup afl->max_length to afl->fsrv.max_length --- src/afl-fuzz.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index bb9c270f..1f0037ba 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1805,7 +1805,8 @@ int main(int argc, char **argv_orig, char **envp) { afl_realloc(AFL_BUF_PARAM(ex), min_alloc); afl->fsrv.use_fauxsrv = afl->non_instrumented_mode == 1 || afl->no_forkserver; - + afl->fsrv.max_length = afl->max_length; + #ifdef __linux__ if (!afl->fsrv.nyx_mode) { -- cgit v1.2.3 From 6ae95271becde1cd35a7792fd31ff84a548561ea Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 16 May 2024 09:17:59 +0200 Subject: nits --- src/afl-showmap.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 4ce01444..7e875040 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -178,7 +178,8 @@ fsrv_run_result_t fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv, void classify_counts(afl_forkserver_t *fsrv) { u8 *mem = fsrv->trace_bits; - const u8 *map = (binary_mode || collect_coverage) ? count_class_binary : count_class_human; + const u8 *map = (binary_mode || collect_coverage) ? count_class_binary + : count_class_human; u32 i = map_size; @@ -240,11 +241,7 @@ static void analyze_results(afl_forkserver_t *fsrv) { u32 i; for (i = 0; i < map_size; i++) { - if (fsrv->trace_bits[i]) { - - coverage_map[i] |= fsrv->trace_bits[i]; - - } + if (fsrv->trace_bits[i]) { coverage_map[i] |= fsrv->trace_bits[i]; } } @@ -1336,6 +1333,8 @@ int main(int argc, char **argv_orig, char **envp) { } + if (collect_coverage) { binary_mode = false; } // ensure this + if (optind == argc || !out_file) { usage(argv[0]); } if (in_dir && in_filelist) { FATAL("you can only specify either -i or -I"); } -- cgit v1.2.3 From ba7ae6c59d52d4a007fe53f415106277ae68b067 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 16 May 2024 14:21:00 +0200 Subject: nits --- src/afl-cc.c | 10 +++++----- src/afl-fuzz-run.c | 2 ++ 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/afl-cc.c b/src/afl-cc.c index 7acee8e4..c872b2eb 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -2794,11 +2794,11 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { "MODES: NCC PERSIST DICT LAF " "CMPLOG SELECT\n" " [LLVM] LLVM: %s%s\n" - " PCGUARD %s yes yes module yes yes " + " PCGUARD %s yes yes module yes yes " "yes\n" " NATIVE AVAILABLE no yes no no " "part. yes\n" - " CLASSIC %s no yes module yes yes " + " CLASSIC %s no yes module yes yes " "yes\n" " - NORMAL\n" " - CALLER\n" @@ -2815,10 +2815,10 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { " [GCC/CLANG] simple gcc/clang: %s%s\n" " CLASSIC DEFAULT no no no no no " "no\n\n", - aflcc->have_llvm ? "AVAILABLE" : "unavailable!", + aflcc->have_llvm ? "AVAILABLE " : "unavailable!", aflcc->compiler_mode == LLVM ? " [SELECTED]" : "", - aflcc->have_llvm ? "AVAILABLE" : "unavailable!", - aflcc->have_llvm ? "AVAILABLE" : "unavailable!", + aflcc->have_llvm ? "AVAILABLE " : "unavailable!", + aflcc->have_llvm ? "AVAILABLE " : "unavailable!", aflcc->have_lto ? "AVAILABLE" : "unavailable!", aflcc->compiler_mode == LTO ? " [SELECTED]" : "", aflcc->have_gcc_plugin ? "AVAILABLE" : "unavailable!", diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 2a55da00..4e2cceff 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -606,6 +606,8 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, } q->exec_us = diff_us / afl->stage_max; + if (unlikely(!q->exec_us)) { q->exec_us = 1; } + q->bitmap_size = count_bytes(afl, afl->fsrv.trace_bits); q->handicap = handicap; q->cal_failed = 0; -- cgit v1.2.3 From 6dd5e931fcd50908ff3c02f31e49f8cd751eaff3 Mon Sep 17 00:00:00 2001 From: Cornelius Aschermann Date: Wed, 15 May 2024 17:09:05 -0700 Subject: Fix runtime underflow & -V exiting before syncing print_stats sets exit_soon even while syncing, this leaves -V 0 still broken, as we don't finish syncing. Additionally, the change that introduced the previous -V fix also broke the runtime tracking, as runtime needs to include all time including sync, splice etc. This caused an underflow in the reported runtime. --- src/afl-fuzz-run.c | 1 - src/afl-fuzz-stats.c | 27 ++++++++++++--------------- src/afl-fuzz.c | 11 +---------- 3 files changed, 13 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 2a55da00..bfd35e5c 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -1193,4 +1193,3 @@ common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { return 0; } - diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 755e1c50..ffe56cde 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -321,8 +321,9 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, #ifndef __HAIKU__ if (getrusage(RUSAGE_CHILDREN, &rus)) { rus.ru_maxrss = 0; } #endif - u64 runtime = afl->prev_run_time + cur_time - afl->start_time; - if (!runtime) { runtime = 1; } + u64 runtime_ms = afl->prev_run_time + cur_time - afl->start_time; + u64 overhead_ms = (afl->calibration_time_us + afl->sync_time_us + afl->trim_time_us) / 1000; + if (!runtime_ms) { runtime_ms = 1; } fprintf( f, @@ -375,20 +376,17 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, "target_mode : %s%s%s%s%s%s%s%s%s%s\n" "command_line : %s\n", (afl->start_time /*- afl->prev_run_time*/) / 1000, cur_time / 1000, - runtime / 1000, (u32)getpid(), + runtime_ms / 1000, (u32)getpid(), afl->queue_cycle ? (afl->queue_cycle - 1) : 0, afl->cycles_wo_finds, afl->longest_find_time > cur_time - afl->last_find_time ? afl->longest_find_time / 1000 : ((afl->start_time == 0 || afl->last_find_time == 0) ? 0 : (cur_time - afl->last_find_time) / 1000), - (runtime - - ((afl->calibration_time_us + afl->sync_time_us + afl->trim_time_us) / - 1000)) / - 1000, + (runtime_ms - MIN(runtime_ms, overhead_ms)) / 1000, afl->calibration_time_us / 1000000, afl->sync_time_us / 1000000, afl->trim_time_us / 1000000, afl->fsrv.total_execs, - afl->fsrv.total_execs / ((double)(runtime) / 1000), + afl->fsrv.total_execs / ((double)(runtime_ms) / 1000), afl->last_avg_execs_saved, afl->queued_items, afl->queued_favored, afl->queued_discovered, afl->queued_imported, afl->queued_variable, afl->max_depth, afl->current_entry, afl->pending_favored, @@ -632,9 +630,9 @@ void show_stats_normal(afl_state_t *afl) { cur_ms = get_cur_time(); - if (afl->most_time_key) { + if (afl->most_time_key && afl->queue_cycle) { - if (afl->most_time * 1000 < cur_ms - afl->start_time) { + if (afl->most_time * 1000 + afl->sync_time_us / 1000 < cur_ms - afl->start_time) { afl->most_time_key = 2; afl->stop_soon = 2; @@ -643,7 +641,7 @@ void show_stats_normal(afl_state_t *afl) { } - if (afl->most_execs_key == 1) { + if (afl->most_execs_key == 1 && afl->queue_cycle) { if (afl->most_execs <= afl->fsrv.total_execs) { @@ -1462,9 +1460,9 @@ void show_stats_pizza(afl_state_t *afl) { cur_ms = get_cur_time(); - if (afl->most_time_key) { + if (afl->most_time_key && afl->queue_cycle) { - if (afl->most_time * 1000 < cur_ms - afl->start_time) { + if (afl->most_time * 1000 + afl->sync_time_us / 1000 < cur_ms - afl->start_time) { afl->most_time_key = 2; afl->stop_soon = 2; @@ -1473,7 +1471,7 @@ void show_stats_pizza(afl_state_t *afl) { } - if (afl->most_execs_key == 1) { + if (afl->most_execs_key == 1 && afl->queue_cycle) { if (afl->most_execs <= afl->fsrv.total_execs) { @@ -2505,4 +2503,3 @@ void update_sync_time(afl_state_t *afl, u64 *time) { *time = cur; } - diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 1f0037ba..cf3940f1 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1806,7 +1806,7 @@ int main(int argc, char **argv_orig, char **envp) { afl->fsrv.use_fauxsrv = afl->non_instrumented_mode == 1 || afl->no_forkserver; afl->fsrv.max_length = afl->max_length; - + #ifdef __linux__ if (!afl->fsrv.nyx_mode) { @@ -2593,14 +2593,6 @@ int main(int argc, char **argv_orig, char **envp) { } sync_fuzzers(afl); - - if (!afl->queue_cycle && afl->afl_env.afl_import_first) { - - // real start time, we reset, so this works correctly with -V - afl->start_time = get_cur_time(); - - } - } ++afl->queue_cycle; @@ -3115,4 +3107,3 @@ stop_fuzzing: } #endif /* !AFL_LIB */ - -- cgit v1.2.3 From 56d5aa3101945e81519a3fac8783d0d8fad82779 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 17 May 2024 23:55:43 +0200 Subject: log --- src/afl-fuzz.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index cf3940f1..70ab983c 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2593,6 +2593,7 @@ int main(int argc, char **argv_orig, char **envp) { } sync_fuzzers(afl); + } ++afl->queue_cycle; @@ -3107,3 +3108,4 @@ stop_fuzzing: } #endif /* !AFL_LIB */ + -- cgit v1.2.3