1 /*
2 american fuzzy lop++ - redqueen implementation on top of cmplog
3 ---------------------------------------------------------------
4
5 Originally written by Michal Zalewski
6
7 Forkserver design by Jann Horn <[email protected]>
8
9 Now maintained by by Marc Heuse <[email protected]>,
10 Heiko Eißfeldt <[email protected]> and
11 Andrea Fioraldi <[email protected]>
12
13 Copyright 2016, 2017 Google Inc. All rights reserved.
14 Copyright 2019-2024 AFLplusplus Project. All rights reserved.
15
16 Licensed under the Apache License, Version 2.0 (the "License");
17 you may not use this file except in compliance with the License.
18 You may obtain a copy of the License at:
19
20 https://www.apache.org/licenses/LICENSE-2.0
21
22 Shared code to handle the shared memory. This is used by the fuzzer
23 as well the other components like afl-tmin, afl-showmap, etc...
24
25 */
26
27 #include <limits.h>
28 #include "afl-fuzz.h"
29 #include "cmplog.h"
30
31 // #define _DEBUG
32 // #define CMPLOG_INTROSPECTION
33
34 // CMP attribute enum
35 enum {
36
37 IS_EQUAL = 1, // arithemtic equal comparison
38 IS_GREATER = 2, // arithmetic greater comparison
39 IS_LESSER = 4, // arithmetic lesser comparison
40 IS_FP = 8, // is a floating point, not an integer
41 /* --- below are internal settings, not from target cmplog */
42 IS_FP_MOD = 16, // arithemtic changed floating point
43 IS_INT_MOD = 32, // arithmetic changed integer
44 IS_TRANSFORM = 64 // transformed integer
45
46 };
47
48 // add to dictionary enum
49 // DEFAULT = 1, notTXT = 2, FOUND = 4, notSAME = 8
50 enum {
51
52 DICT_ADD_NEVER = 0,
53 DICT_ADD_NOTFOUND_SAME_TXT = 1,
54 DICT_ADD_NOTFOUND_SAME = 3,
55 DICT_ADD_FOUND_SAME_TXT = 5,
56 DICT_ADD_FOUND_SAME = 7,
57 DICT_ADD_NOTFOUND_TXT = 9,
58 DICT_ADD_NOTFOUND = 11,
59 DICT_ADD_FOUND_TXT = 13,
60 DICT_ADD_FOUND = 15,
61 DICT_ADD_ANY = DICT_ADD_FOUND
62
63 };
64
65 // CMPLOG LVL
66 enum {
67
68 LVL1 = 1, // Integer solving
69 LVL2 = 2, // unused except for setting the queue entry
70 LVL3 = 4 // expensive tranformations
71
72 };
73
74 #define DICT_ADD_STRATEGY DICT_ADD_FOUND_SAME
75
76 struct range {
77
78 u32 start;
79 u32 end;
80 struct range *next;
81 struct range *prev;
82 u8 ok;
83
84 };
85
86 static u32 hshape;
87 static u64 screen_update;
88 static u64 last_update;
89
add_range(struct range * ranges,u32 start,u32 end)90 static struct range *add_range(struct range *ranges, u32 start, u32 end) {
91
92 struct range *r = ck_alloc_nozero(sizeof(struct range));
93 r->start = start;
94 r->end = end;
95 r->next = ranges;
96 r->ok = 0;
97 if (likely(ranges)) ranges->prev = r;
98 return r;
99
100 }
101
pop_biggest_range(struct range ** ranges)102 static struct range *pop_biggest_range(struct range **ranges) {
103
104 struct range *r = *ranges;
105 struct range *rmax = NULL;
106 u32 max_size = 0;
107
108 while (r) {
109
110 if (!r->ok) {
111
112 u32 s = 1 + r->end - r->start;
113
114 if (s >= max_size) {
115
116 max_size = s;
117 rmax = r;
118
119 }
120
121 }
122
123 r = r->next;
124
125 }
126
127 return rmax;
128
129 }
130
131 #ifdef _DEBUG
dump(char * txt,u8 * buf,u32 len)132 static void dump(char *txt, u8 *buf, u32 len) {
133
134 u32 i;
135 fprintf(stderr, "DUMP %s %016llx ", txt, hash64(buf, len, HASH_CONST));
136 for (i = 0; i < len; i++)
137 fprintf(stderr, "%02x", buf[i]);
138 fprintf(stderr, "\n");
139
140 }
141
142 /*
143 static void dump_file(char *path, char *name, u32 counter, u8 *buf, u32 len) {
144
145 char fn[4096];
146 if (!path) path = ".";
147 snprintf(fn, sizeof(fn), "%s/%s%d", path, name, counter);
148 int fd = open(fn, O_RDWR | O_CREAT | O_TRUNC, 0644);
149 if (fd >= 0) {
150
151 write(fd, buf, len);
152 close(fd);
153
154 }
155
156 }
157
158 */
159
160 #endif
161
get_exec_checksum(afl_state_t * afl,u8 * buf,u32 len,u64 * cksum)162 static u8 get_exec_checksum(afl_state_t *afl, u8 *buf, u32 len, u64 *cksum) {
163
164 if (unlikely(common_fuzz_stuff(afl, buf, len))) { return 1; }
165
166 *cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
167
168 return 0;
169
170 }
171
172 /* replace everything with different values */
random_replace(afl_state_t * afl,u8 * buf,u32 len)173 static void random_replace(afl_state_t *afl, u8 *buf, u32 len) {
174
175 for (u32 i = 0; i < len; i++) {
176
177 u8 c;
178
179 do {
180
181 c = rand_below(afl, 256);
182
183 } while (c == buf[i]);
184
185 buf[i] = c;
186
187 }
188
189 }
190
191 /* replace everything with different values but stay in the same type */
type_replace(afl_state_t * afl,u8 * buf,u32 len)192 static void type_replace(afl_state_t *afl, u8 *buf, u32 len) {
193
194 u32 i;
195 u8 c;
196 for (i = 0; i < len; ++i) {
197
198 // wont help for UTF or non-latin charsets
199 do {
200
201 switch (buf[i]) {
202
203 case 'A' ... 'F':
204 c = 'A' + rand_below(afl, 1 + 'F' - 'A');
205 break;
206 case 'a' ... 'f':
207 c = 'a' + rand_below(afl, 1 + 'f' - 'a');
208 break;
209 case '0':
210 c = '1';
211 break;
212 case '1':
213 c = '0';
214 break;
215 case '2' ... '9':
216 c = '2' + rand_below(afl, 1 + '9' - '2');
217 break;
218 case 'G' ... 'Z':
219 c = 'G' + rand_below(afl, 1 + 'Z' - 'G');
220 break;
221 case 'g' ... 'z':
222 c = 'g' + rand_below(afl, 1 + 'z' - 'g');
223 break;
224 case '!' ... '*':
225 c = '!' + rand_below(afl, 1 + '*' - '!');
226 break;
227 case ',' ... '.':
228 c = ',' + rand_below(afl, 1 + '.' - ',');
229 break;
230 case ':' ... '@':
231 c = ':' + rand_below(afl, 1 + '@' - ':');
232 break;
233 case '[' ... '`':
234 c = '[' + rand_below(afl, 1 + '`' - '[');
235 break;
236 case '{' ... '~':
237 c = '{' + rand_below(afl, 1 + '~' - '{');
238 break;
239 case '+':
240 c = '/';
241 break;
242 case '/':
243 c = '+';
244 break;
245 case ' ':
246 c = '\t';
247 break;
248 case '\t':
249 c = ' ';
250 break;
251 case '\r':
252 c = '\n';
253 break;
254 case '\n':
255 c = '\r';
256 break;
257 case 0:
258 c = 1;
259 break;
260 case 1:
261 c = 0;
262 break;
263 case 0xff:
264 c = 0;
265 break;
266 default:
267 if (buf[i] < 32) {
268
269 c = (buf[i] ^ 0x1f);
270
271 } else {
272
273 c = (buf[i] ^ 0x7f); // we keep the highest bit
274
275 }
276
277 }
278
279 } while (c == buf[i]);
280
281 buf[i] = c;
282
283 }
284
285 }
286
colorization(afl_state_t * afl,u8 * buf,u32 len,struct tainted ** taints)287 static u8 colorization(afl_state_t *afl, u8 *buf, u32 len,
288 struct tainted **taints) {
289
290 struct range *ranges = add_range(NULL, 0, len - 1), *rng;
291 struct tainted *taint = NULL;
292 u8 *backup = ck_alloc_nozero(len);
293 u8 *changed = ck_alloc_nozero(len);
294
295 #if defined(_DEBUG) || defined(CMPLOG_INTROSPECTION)
296 u64 start_time = get_cur_time();
297 #endif
298
299 u64 orig_hit_cnt, new_hit_cnt, exec_cksum;
300 orig_hit_cnt = afl->queued_items + afl->saved_crashes;
301
302 afl->stage_name = "colorization";
303 afl->stage_short = "colorization";
304 afl->stage_max = (len << 1);
305 afl->stage_cur = 0;
306
307 // in colorization we do not classify counts, hence we have to calculate
308 // the original checksum.
309 if (unlikely(get_exec_checksum(afl, buf, len, &exec_cksum))) {
310
311 goto checksum_fail;
312
313 }
314
315 memcpy(backup, buf, len);
316 memcpy(changed, buf, len);
317 if (afl->cmplog_random_colorization) {
318
319 random_replace(afl, changed, len);
320
321 } else {
322
323 type_replace(afl, changed, len);
324
325 }
326
327 while ((rng = pop_biggest_range(&ranges)) != NULL &&
328 afl->stage_cur < afl->stage_max) {
329
330 u32 s = 1 + rng->end - rng->start;
331
332 memcpy(buf + rng->start, changed + rng->start, s);
333
334 u64 cksum = 0;
335 u64 start_us = get_cur_time_us();
336 if (unlikely(get_exec_checksum(afl, buf, len, &cksum))) {
337
338 goto checksum_fail;
339
340 }
341
342 u64 stop_us = get_cur_time_us();
343
344 /* Discard if the mutations change the path or if it is too decremental
345 in speed - how could the same path have a much different speed
346 though ...*/
347 if (cksum != exec_cksum ||
348 (unlikely(stop_us - start_us > 3 * afl->queue_cur->exec_us) &&
349 likely(!afl->fixed_seed))) {
350
351 memcpy(buf + rng->start, backup + rng->start, s);
352
353 if (s > 1) { // to not add 0 size ranges
354
355 ranges = add_range(ranges, rng->start, rng->start - 1 + s / 2);
356 ranges = add_range(ranges, rng->start + s / 2, rng->end);
357
358 }
359
360 if (ranges == rng) {
361
362 ranges = rng->next;
363 if (ranges) { ranges->prev = NULL; }
364
365 } else if (rng->next) {
366
367 rng->prev->next = rng->next;
368 rng->next->prev = rng->prev;
369
370 } else {
371
372 if (rng->prev) { rng->prev->next = NULL; }
373
374 }
375
376 free(rng);
377
378 } else {
379
380 rng->ok = 1;
381
382 }
383
384 if (unlikely(++afl->stage_cur % screen_update == 0)) { show_stats(afl); };
385
386 }
387
388 rng = ranges;
389 while (rng) {
390
391 rng = rng->next;
392
393 }
394
395 u32 i = 1;
396 u32 positions = 0;
397 while (i) {
398
399 restart:
400 i = 0;
401 struct range *r = NULL;
402 u32 pos = (u32)-1;
403 rng = ranges;
404
405 while (rng) {
406
407 if (rng->ok == 1 && rng->start < pos) {
408
409 if (taint && taint->pos + taint->len == rng->start) {
410
411 taint->len += (1 + rng->end - rng->start);
412 positions += (1 + rng->end - rng->start);
413 rng->ok = 2;
414 goto restart;
415
416 } else {
417
418 r = rng;
419 pos = rng->start;
420
421 }
422
423 }
424
425 rng = rng->next;
426
427 }
428
429 if (r) {
430
431 struct tainted *t = ck_alloc_nozero(sizeof(struct tainted));
432 t->pos = r->start;
433 t->len = 1 + r->end - r->start;
434 positions += (1 + r->end - r->start);
435 if (likely(taint)) { taint->prev = t; }
436 t->next = taint;
437 t->prev = NULL;
438 taint = t;
439 r->ok = 2;
440 i = 1;
441
442 }
443
444 }
445
446 /* temporary: clean ranges */
447 while (ranges) {
448
449 rng = ranges;
450 ranges = rng->next;
451 ck_free(rng);
452 rng = NULL;
453
454 }
455
456 new_hit_cnt = afl->queued_items + afl->saved_crashes;
457
458 #if defined(_DEBUG) || defined(CMPLOG_INTROSPECTION)
459 FILE *f = stderr;
460 #ifndef _DEBUG
461 if (afl->not_on_tty) {
462
463 char fn[4096];
464 snprintf(fn, sizeof(fn), "%s/introspection_cmplog.txt", afl->out_dir);
465 f = fopen(fn, "a");
466
467 }
468
469 #endif
470
471 if (f) {
472
473 fprintf(
474 f,
475 "Colorization: fname=%s len=%u ms=%llu result=%u execs=%u found=%llu "
476 "taint=%u ascii=%u auto_extra_before=%u\n",
477 afl->queue_cur->fname, len, get_cur_time() - start_time,
478 afl->queue_cur->colorized, afl->stage_cur, new_hit_cnt - orig_hit_cnt,
479 positions, afl->queue_cur->is_ascii ? 1 : 0, afl->a_extras_cnt);
480
481 #ifndef _DEBUG
482 if (afl->not_on_tty) { fclose(f); }
483 #endif
484
485 }
486
487 #endif
488
489 if (taint) {
490
491 if (afl->colorize_success && afl->cmplog_lvl < 3 &&
492 (positions > CMPLOG_POSITIONS_MAX && len / positions == 1 &&
493 afl->active_items / afl->colorize_success > CMPLOG_CORPUS_PERCENT)) {
494
495 #ifdef _DEBUG
496 fprintf(stderr, "Colorization unsatisfactory\n");
497 #endif
498
499 *taints = NULL;
500
501 struct tainted *t;
502 while (taint) {
503
504 t = taint->next;
505 ck_free(taint);
506 taint = t;
507
508 }
509
510 } else {
511
512 *taints = taint;
513 ++afl->colorize_success;
514
515 }
516
517 }
518
519 afl->stage_finds[STAGE_COLORIZATION] += new_hit_cnt - orig_hit_cnt;
520 afl->stage_cycles[STAGE_COLORIZATION] += afl->stage_cur;
521 ck_free(backup);
522 ck_free(changed);
523
524 return 0;
525
526 checksum_fail:
527 while (ranges) {
528
529 rng = ranges;
530 ranges = rng->next;
531 ck_free(rng);
532 rng = NULL;
533
534 }
535
536 ck_free(backup);
537 ck_free(changed);
538
539 return 1;
540
541 }
542
543 ///// Input to State replacement
544
its_fuzz(afl_state_t * afl,u8 * buf,u32 len,u8 * status)545 static u8 its_fuzz(afl_state_t *afl, u8 *buf, u32 len, u8 *status) {
546
547 u64 orig_hit_cnt, new_hit_cnt;
548
549 orig_hit_cnt = afl->queued_items + afl->saved_crashes;
550
551 #ifdef _DEBUG
552 dump("DATA", buf, len);
553 #endif
554
555 if (unlikely(common_fuzz_stuff(afl, buf, len))) { return 1; }
556
557 new_hit_cnt = afl->queued_items + afl->saved_crashes;
558
559 if (unlikely(new_hit_cnt != orig_hit_cnt)) {
560
561 #ifdef _DEBUG
562 fprintf(stderr, "NEW FIND\n");
563 #endif
564 *status = 1;
565
566 } else {
567
568 *status = 2;
569
570 }
571
572 return 0;
573
574 }
575
strntoll(const char * str,size_t sz,char ** end,int base,long long * out)576 static int strntoll(const char *str, size_t sz, char **end, int base,
577 long long *out) {
578
579 char buf[64];
580 long long ret;
581 const char *beg = str;
582
583 if (!str || !sz) { return 1; }
584
585 for (; beg && sz && *beg == ' '; beg++, sz--) {};
586
587 if (!sz) return 1;
588 if (sz >= sizeof(buf)) sz = sizeof(buf) - 1;
589
590 memcpy(buf, beg, sz);
591 buf[sz] = '\0';
592 ret = strtoll(buf, end, base);
593 if ((ret == LLONG_MIN || ret == LLONG_MAX) && errno == ERANGE) return 1;
594 if (end) *end = (char *)beg + (*end - buf);
595 *out = ret;
596
597 return 0;
598
599 }
600
strntoull(const char * str,size_t sz,char ** end,int base,unsigned long long * out)601 static int strntoull(const char *str, size_t sz, char **end, int base,
602 unsigned long long *out) {
603
604 char buf[64];
605 unsigned long long ret;
606 const char *beg = str;
607
608 if (!str || !sz) { return 1; }
609
610 for (; beg && sz && *beg == ' '; beg++, sz--)
611 ;
612
613 if (!sz) return 1;
614 if (sz >= sizeof(buf)) sz = sizeof(buf) - 1;
615
616 memcpy(buf, beg, sz);
617 buf[sz] = '\0';
618 ret = strtoull(buf, end, base);
619 if (ret == ULLONG_MAX && errno == ERANGE) return 1;
620 if (end) *end = (char *)beg + (*end - buf);
621 *out = ret;
622
623 return 0;
624
625 }
626
627 static u8 hex_table_up[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
628 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
629 static u8 hex_table_low[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
630 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
631 static u8 hex_table[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0,
632 0, 0, 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0,
633 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
634 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15};
635
636 // tests 2 bytes at location
is_hex(const char * str)637 static int is_hex(const char *str) {
638
639 u32 i;
640
641 for (i = 0; i < 2; i++) {
642
643 switch (str[i]) {
644
645 case '0' ... '9':
646 case 'A' ... 'F':
647 case 'a' ... 'f':
648 break;
649 default:
650 return 0;
651
652 }
653
654 }
655
656 return 1;
657
658 }
659
660 // tests 4 bytes at location
is_base64(const char * str)661 static int is_base64(const char *str) {
662
663 u32 i;
664
665 for (i = 0; i < 4; i++) {
666
667 switch (str[i]) {
668
669 case '0' ... '9':
670 case 'A' ... 'Z':
671 case 'a' ... 'z':
672 case '+':
673 case '/':
674 case '=':
675 break;
676 default:
677 return 0;
678
679 }
680
681 }
682
683 return 1;
684
685 }
686
687 static u8 base64_encode_table[] =
688 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
689 static u8 base64_decode_table[] = {
690
691 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0,
692 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
693 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
694 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
695 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51};
696
from_base64(u8 * src,u8 * dst,u32 dst_len)697 static u32 from_base64(u8 *src, u8 *dst, u32 dst_len) {
698
699 u32 i, j, v;
700 u32 len = ((dst_len / 3) << 2);
701 u32 ret = 0;
702
703 for (i = 0, j = 0; i < len; i += 4, j += 3) {
704
705 v = base64_decode_table[src[i] - 43];
706 v = (v << 6) | base64_decode_table[src[i + 1] - 43];
707 v = src[i + 2] == '=' ? v << 6
708 : (v << 6) | base64_decode_table[src[i + 2] - 43];
709 v = src[i + 3] == '=' ? v << 6
710 : (v << 6) | base64_decode_table[src[i + 3] - 43];
711
712 dst[j] = (v >> 16) & 0xFF;
713 ++ret;
714
715 if (src[i + 2] != '=') {
716
717 dst[j + 1] = (v >> 8) & 0xFF;
718 ++ret;
719
720 }
721
722 if (src[i + 3] != '=') {
723
724 dst[j + 2] = v & 0xFF;
725 ++ret;
726
727 }
728
729 }
730
731 return ret;
732
733 }
734
to_base64(u8 * src,u8 * dst,u32 dst_len)735 static u32 to_base64(u8 *src, u8 *dst, u32 dst_len) {
736
737 u32 i, j, v;
738 // u32 len = (dst_len >> 2) * 3;
739 u32 len = (dst_len / 3) * 4;
740 if (dst_len % 3) len += 4;
741
742 for (i = 0, j = 0; j < len; i += 3, j += 4) {
743
744 v = src[i];
745 v = i + 1 < len ? v << 8 | src[i + 1] : v << 8;
746 v = i + 2 < len ? v << 8 | src[i + 2] : v << 8;
747
748 dst[j] = base64_encode_table[(v >> 18) & 0x3F];
749 dst[j + 1] = base64_encode_table[(v >> 12) & 0x3F];
750
751 if (i + 1 < dst_len) {
752
753 dst[j + 2] = base64_encode_table[(v >> 6) & 0x3F];
754
755 } else {
756
757 dst[j + 2] = '=';
758
759 }
760
761 if (i + 2 < dst_len) {
762
763 dst[j + 3] = base64_encode_table[v & 0x3F];
764
765 } else {
766
767 dst[j + 3] = '=';
768
769 }
770
771 }
772
773 dst[len] = 0;
774 return len;
775
776 }
777
778 #ifdef WORD_SIZE_64
779 static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h,
780 u128 pattern, u128 repl, u128 o_pattern,
781 u128 changed_val, u8 attr, u32 idx,
782 u32 taint_len, u8 *orig_buf, u8 *buf, u8 *cbuf,
783 u32 len, u8 do_reverse, u8 lvl, u8 *status);
784 #endif
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,u8 * orig_buf,u8 * buf,u8 * cbuf,u32 len,u8 do_reverse,u8 lvl,u8 * status)785 static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
786 u64 pattern, u64 repl, u64 o_pattern,
787 u64 changed_val, u8 attr, u32 idx, u32 taint_len,
788 u8 *orig_buf, u8 *buf, u8 *cbuf, u32 len,
789 u8 do_reverse, u8 lvl, u8 *status) {
790
791 u64 *buf_64 = (u64 *)&buf[idx];
792 u32 *buf_32 = (u32 *)&buf[idx];
793 u16 *buf_16 = (u16 *)&buf[idx];
794 u8 *buf_8 = &buf[idx];
795 u64 *o_buf_64 = (u64 *)&orig_buf[idx];
796 u32 *o_buf_32 = (u32 *)&orig_buf[idx];
797 u16 *o_buf_16 = (u16 *)&orig_buf[idx];
798 u8 *o_buf_8 = &orig_buf[idx];
799
800 u32 its_len = MIN(len - idx, taint_len);
801
802 if (unlikely(afl->fsrv.total_execs - last_update > screen_update)) {
803
804 show_stats(afl);
805 last_update = afl->fsrv.total_execs;
806
807 }
808
809 /*
810 fprintf(stderr,
811 "Encode: %llx->%llx into %llx(<-%llx) at idx=%u "
812 "taint_len=%u shape=%u attr=%u\n",
813 o_pattern, pattern, repl, changed_val, idx, taint_len,
814 hshape, attr);
815 */
816
817 u8 bytes;
818
819 switch (hshape) {
820
821 case 0:
822 case 1:
823 bytes = 1;
824 break;
825 case 2:
826 bytes = 2;
827 break;
828 case 3:
829 case 4:
830 bytes = 4;
831 break;
832 default:
833 bytes = 8;
834
835 }
836
837 // necessary for preventing heap access overflow
838 bytes = MIN(bytes, len - idx);
839
840 // reverse atoi()/strnu?toll() is expensive, so we only to it in lvl 3
841 if (afl->cmplog_enable_transform && (lvl & LVL3)) {
842
843 u8 *endptr;
844 u8 use_num = 0, use_unum = 0;
845 unsigned long long unum = 0;
846 long long num = 0;
847
848 // if (afl->queue_cur->is_ascii) {
849
850 // we first check if our input are ascii numbers that are transformed to
851 // an integer and used for comparison:
852
853 endptr = buf_8;
854 if (strntoll(buf_8, len - idx, (char **)&endptr, 0, &num)) {
855
856 if (!strntoull(buf_8, len - idx, (char **)&endptr, 0, &unum)) {
857
858 use_unum = 1;
859
860 }
861
862 } else {
863
864 use_num = 1;
865
866 }
867
868 //}
869
870 #ifdef _DEBUG
871 if (idx == 0)
872 fprintf(stderr,
873 "ASCII is=%u use_num=%u>%lld use_unum=%u>%llu idx=%u "
874 "pattern=0x%llx\n",
875 afl->queue_cur->is_ascii, use_num, num, use_unum, unum, idx,
876 pattern);
877 #endif
878
879 // atoi("AAA") == 0 so !num means we have to investigate
880 if (use_num && ((u64)num == pattern || !num)) {
881
882 u8 tmp_buf[32];
883 size_t num_len = snprintf(tmp_buf, sizeof(tmp_buf), "%lld", repl);
884 size_t old_len = endptr - buf_8;
885
886 u8 *new_buf = afl_realloc((void **)&afl->out_scratch_buf, len + num_len);
887 if (unlikely(!new_buf)) { PFATAL("alloc"); }
888
889 memcpy(new_buf, buf, idx);
890 memcpy(new_buf + idx, tmp_buf, num_len);
891 memcpy(new_buf + idx + num_len, buf_8 + old_len, len - idx - old_len);
892
893 if (new_buf[idx + num_len] >= '0' && new_buf[idx + num_len] <= '9') {
894
895 new_buf[idx + num_len] = ' ';
896
897 }
898
899 if (unlikely(its_fuzz(afl, new_buf, len, status))) { return 1; }
900
901 } else if (use_unum && (unum == pattern || !unum)) {
902
903 u8 tmp_buf[32];
904 size_t num_len = snprintf(tmp_buf, sizeof(tmp_buf), "%llu", repl);
905 size_t old_len = endptr - buf_8;
906
907 u8 *new_buf = afl_realloc((void **)&afl->out_scratch_buf, len + num_len);
908 if (unlikely(!new_buf)) { PFATAL("alloc"); }
909
910 memcpy(new_buf, buf, idx);
911 memcpy(new_buf + idx, tmp_buf, num_len);
912 memcpy(new_buf + idx + num_len, buf_8 + old_len, len - idx - old_len);
913
914 if (new_buf[idx + num_len] >= '0' && new_buf[idx + num_len] <= '9') {
915
916 new_buf[idx + num_len] = ' ';
917
918 }
919
920 if (unlikely(its_fuzz(afl, new_buf, len, status))) { return 1; }
921
922 }
923
924 // Try to identify transform magic
925 if (pattern != o_pattern && repl == changed_val && attr <= IS_EQUAL) {
926
927 u64 b_val, o_b_val, mask;
928 switch (bytes) {
929
930 case 0: // cannot happen
931 b_val = o_b_val = mask = 0; // keep the linters happy
932 break;
933 case 1: {
934
935 u8 *ptr = (u8 *)&buf[idx];
936 u8 *o_ptr = (u8 *)&orig_buf[idx];
937 b_val = (u64)(*ptr);
938 o_b_val = (u64)(*o_ptr % 0x100);
939 mask = 0xff;
940 break;
941
942 }
943
944 case 2:
945 case 3: {
946
947 u16 *ptr = (u16 *)&buf[idx];
948 u16 *o_ptr = (u16 *)&orig_buf[idx];
949 b_val = (u64)(*ptr);
950 o_b_val = (u64)(*o_ptr);
951 mask = 0xffff;
952 break;
953
954 }
955
956 case 4:
957 case 5:
958 case 6:
959 case 7: {
960
961 u32 *ptr = (u32 *)&buf[idx];
962 u32 *o_ptr = (u32 *)&orig_buf[idx];
963 b_val = (u64)(*ptr);
964 o_b_val = (u64)(*o_ptr);
965 mask = 0xffffffff;
966 break;
967
968 }
969
970 default: {
971
972 u64 *ptr = (u64 *)&buf[idx];
973 u64 *o_ptr = (u64 *)&orig_buf[idx];
974 b_val = (u64)(*ptr);
975 o_b_val = (u64)(*o_ptr);
976 mask = 0xffffffffffffffff;
977
978 }
979
980 }
981
982 // test for arithmetic, eg. "if ((user_val - 0x1111) == 0x1234) ..."
983 s64 diff = pattern - b_val;
984 s64 o_diff = o_pattern - o_b_val;
985 /*
986 fprintf(stderr, "DIFF1 idx=%03u shape=%02u %llx-%llx=%lx\n", idx,
987 hshape, o_pattern, o_b_val, o_diff);
988 fprintf(stderr, "DIFF1 %016llx %llx-%llx=%lx\n", repl, pattern,
989 b_val, diff);
990 */
991 if (diff == o_diff && diff) {
992
993 // this could be an arithmetic transformation
994
995 u64 new_repl = (u64)((s64)repl - diff);
996 // fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl);
997
998 if (unlikely(cmp_extend_encoding(
999 afl, h, pattern, new_repl, o_pattern, repl, IS_TRANSFORM, idx,
1000 taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) {
1001
1002 return 1;
1003
1004 }
1005
1006 // if (*status == 1) { fprintf(stderr, "FOUND!\n"); }
1007
1008 }
1009
1010 // test for XOR, eg. "if ((user_val ^ 0xabcd) == 0x1234) ..."
1011 if (*status != 1) {
1012
1013 diff = pattern ^ b_val;
1014 s64 o_diff = o_pattern ^ o_b_val;
1015
1016 /* fprintf(stderr, "DIFF2 idx=%03u shape=%02u %llx-%llx=%lx\n",
1017 idx, hshape, o_pattern, o_b_val, o_diff);
1018 fprintf(stderr,
1019 "DIFF2 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);
1020 */
1021 if (diff == o_diff && diff) {
1022
1023 // this could be a XOR transformation
1024
1025 u64 new_repl = (u64)((s64)repl ^ diff);
1026 // fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl);
1027
1028 if (unlikely(cmp_extend_encoding(
1029 afl, h, pattern, new_repl, o_pattern, repl, IS_TRANSFORM, idx,
1030 taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) {
1031
1032 return 1;
1033
1034 }
1035
1036 // if (*status == 1) { fprintf(stderr, "FOUND!\n"); }
1037
1038 }
1039
1040 }
1041
1042 // test for to lowercase, eg. "new_val = (user_val | 0x2020) ..."
1043 if (*status != 1) {
1044
1045 if ((b_val | (0x2020202020202020 & mask)) == (pattern & mask)) {
1046
1047 diff = 1;
1048
1049 } else {
1050
1051 diff = 0;
1052
1053 }
1054
1055 if ((o_b_val | (0x2020202020202020 & mask)) == (o_pattern & mask)) {
1056
1057 o_diff = 1;
1058
1059 } else {
1060
1061 o_diff = 0;
1062
1063 }
1064
1065 /* fprintf(stderr, "DIFF3 idx=%03u shape=%02u %llx-%llx=%lx\n",
1066 idx, hshape, o_pattern, o_b_val, o_diff);
1067 fprintf(stderr,
1068 "DIFF3 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);
1069 */
1070 if (o_diff && diff) {
1071
1072 // this could be a lower to upper
1073
1074 u64 new_repl = (repl & (0x5f5f5f5f5f5f5f5f & mask));
1075 // fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl);
1076
1077 if (unlikely(cmp_extend_encoding(
1078 afl, h, pattern, new_repl, o_pattern, repl, IS_TRANSFORM, idx,
1079 taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) {
1080
1081 return 1;
1082
1083 }
1084
1085 // if (*status == 1) { fprintf(stderr, "FOUND!\n"); }
1086
1087 }
1088
1089 }
1090
1091 // test for to uppercase, eg. "new_val = (user_val | 0x5f5f) ..."
1092 if (*status != 1) {
1093
1094 if ((b_val & (0x5f5f5f5f5f5f5f5f & mask)) == (pattern & mask)) {
1095
1096 diff = 1;
1097
1098 } else {
1099
1100 diff = 0;
1101
1102 }
1103
1104 if ((o_b_val & (0x5f5f5f5f5f5f5f5f & mask)) == (o_pattern & mask)) {
1105
1106 o_diff = 1;
1107
1108 } else {
1109
1110 o_diff = 0;
1111
1112 }
1113
1114 /* fprintf(stderr, "DIFF4 idx=%03u shape=%02u %llx-%llx=%lx\n",
1115 idx, hshape, o_pattern, o_b_val, o_diff);
1116 fprintf(stderr,
1117 "DIFF4 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);
1118 */
1119 if (o_diff && diff) {
1120
1121 // this could be a lower to upper
1122
1123 u64 new_repl = (repl | (0x2020202020202020 & mask));
1124 // fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl);
1125
1126 if (unlikely(cmp_extend_encoding(
1127 afl, h, pattern, new_repl, o_pattern, repl, IS_TRANSFORM, idx,
1128 taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) {
1129
1130 return 1;
1131
1132 }
1133
1134 // if (*status == 1) { fprintf(stderr, "FOUND!\n"); }
1135
1136 }
1137
1138 }
1139
1140 *status = 0;
1141
1142 }
1143
1144 }
1145
1146 // #endif
1147
1148 // we only allow this for ascii2integer (above) so leave if this is the case
1149 if (unlikely(pattern == o_pattern)) { return 0; }
1150
1151 if ((lvl & LVL1) || attr >= IS_FP_MOD) {
1152
1153 if (hshape >= 8 && *status != 1) {
1154
1155 // if (its_len >= 8)
1156 // fprintf(stderr,
1157 // "TestU64: %u>=8 (idx=%u attr=%u) %llx==%llx"
1158 // " %llx==%llx <= %llx<-%llx\n",
1159 // its_len, idx, attr, *buf_64, pattern, *o_buf_64, o_pattern,
1160 // repl, changed_val);
1161
1162 // if this is an fcmp (attr & 8 == 8) then do not compare the patterns -
1163 // due to a bug in llvm dynamic float bitcasts do not work :(
1164 // the value 16 means this is a +- 1.0 test case
1165 if (its_len >= 8 && ((*buf_64 == pattern && *o_buf_64 == o_pattern) ||
1166 attr >= IS_FP_MOD)) {
1167
1168 u64 tmp_64 = *buf_64;
1169 *buf_64 = repl;
1170 if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
1171 #ifdef CMPLOG_COMBINE
1172 if (*status == 1) { memcpy(cbuf + idx, buf_64, 8); }
1173 #endif
1174 *buf_64 = tmp_64;
1175
1176 // fprintf(stderr, "Status=%u\n", *status);
1177
1178 }
1179
1180 // reverse encoding
1181 if (do_reverse && *status != 1) {
1182
1183 if (unlikely(cmp_extend_encoding(afl, h, SWAP64(pattern), SWAP64(repl),
1184 SWAP64(o_pattern), SWAP64(changed_val),
1185 attr, idx, taint_len, orig_buf, buf,
1186 cbuf, len, 0, lvl, status))) {
1187
1188 return 1;
1189
1190 }
1191
1192 }
1193
1194 }
1195
1196 if (hshape >= 4 && *status != 1) {
1197
1198 // if (its_len >= 4 && (attr <= 1 || attr >= 8))
1199 // fprintf(stderr,
1200 // "TestU32: %u>=4 (idx=%u attr=%u) %x==%x"
1201 // " %x==%x <= %x<-%x\n",
1202 // its_len, idx, attr, *buf_32, (u32)pattern, *o_buf_32,
1203 // (u32)o_pattern, (u32)repl, (u32)changed_val);
1204
1205 if (its_len >= 4 &&
1206 ((*buf_32 == (u32)pattern && *o_buf_32 == (u32)o_pattern) ||
1207 attr >= IS_FP_MOD)) {
1208
1209 u32 tmp_32 = *buf_32;
1210 *buf_32 = (u32)repl;
1211 if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
1212 #ifdef CMPLOG_COMBINE
1213 if (*status == 1) { memcpy(cbuf + idx, buf_32, 4); }
1214 #endif
1215 *buf_32 = tmp_32;
1216
1217 // fprintf(stderr, "Status=%u\n", *status);
1218
1219 }
1220
1221 // reverse encoding
1222 if (do_reverse && *status != 1) {
1223
1224 if (unlikely(cmp_extend_encoding(afl, h, SWAP32(pattern), SWAP32(repl),
1225 SWAP32(o_pattern), SWAP32(changed_val),
1226 attr, idx, taint_len, orig_buf, buf,
1227 cbuf, len, 0, lvl, status))) {
1228
1229 return 1;
1230
1231 }
1232
1233 }
1234
1235 }
1236
1237 if (hshape >= 2 && *status != 1) {
1238
1239 if (its_len >= 2 &&
1240 ((*buf_16 == (u16)pattern && *o_buf_16 == (u16)o_pattern) ||
1241 attr >= IS_FP_MOD)) {
1242
1243 u16 tmp_16 = *buf_16;
1244 *buf_16 = (u16)repl;
1245 if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
1246 #ifdef CMPLOG_COMBINE
1247 if (*status == 1) { memcpy(cbuf + idx, buf_16, 2); }
1248 #endif
1249 *buf_16 = tmp_16;
1250
1251 }
1252
1253 // reverse encoding
1254 if (do_reverse && *status != 1) {
1255
1256 if (unlikely(cmp_extend_encoding(afl, h, SWAP16(pattern), SWAP16(repl),
1257 SWAP16(o_pattern), SWAP16(changed_val),
1258 attr, idx, taint_len, orig_buf, buf,
1259 cbuf, len, 0, lvl, status))) {
1260
1261 return 1;
1262
1263 }
1264
1265 }
1266
1267 }
1268
1269 if (*status != 1) { // u8
1270
1271 // if (its_len >= 1)
1272 // fprintf(stderr,
1273 // "TestU8: %u>=1 (idx=%u attr=%u) %x==%x %x==%x <= %x<-%x\n",
1274 // its_len, idx, attr, *buf_8, (u8)pattern, *o_buf_8,
1275 // (u8)o_pattern, (u8)repl, (u8)changed_val);
1276
1277 if (its_len >= 1 &&
1278 ((*buf_8 == (u8)pattern && *o_buf_8 == (u8)o_pattern) ||
1279 attr >= IS_FP_MOD)) {
1280
1281 u8 tmp_8 = *buf_8;
1282 *buf_8 = (u8)repl;
1283 if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
1284 #ifdef CMPLOG_COMBINE
1285 if (*status == 1) { cbuf[idx] = *buf_8; }
1286 #endif
1287 *buf_8 = tmp_8;
1288
1289 }
1290
1291 }
1292
1293 }
1294
1295 // If 'S' is set for cmplog mode then we try a scale encoding of the value.
1296 // Currently we can only handle bytes up to 1 << 55 on 32 bit and 1 << 119
1297 // on 64 bit systems.
1298 // Caveat: This implementation here works only on little endian systems.
1299
1300 if (attr < IS_FP && (afl->cmplog_enable_scale || lvl >= LVL3) &&
1301 repl == changed_val) {
1302
1303 u8 do_call = 1;
1304 u64 new_val = repl << 2;
1305 u32 ilen = 0;
1306
1307 if (changed_val <= 255) {
1308
1309 ilen = 1;
1310
1311 } else if (new_val <= 65535) {
1312
1313 new_val += 1; // two byte mode
1314 ilen = 2;
1315
1316 } else if (new_val <= 4294967295) {
1317
1318 new_val += 2; // four byte mode
1319 ilen = 4;
1320
1321 } else {
1322
1323 #ifndef WORD_SIZE_64
1324 if (repl <= 0x00ffffffffffffff) {
1325
1326 new_val = repl << 8;
1327 u8 scale_len = 0;
1328 u64 tmp_val = repl;
1329 while (tmp_val) {
1330
1331 tmp_val >>= 8;
1332 ++scale_len;
1333
1334 } // scale_len will be >= 4;
1335
1336 if (scale_len >= 4) {
1337
1338 scale_len -= 4;
1339
1340 } else {
1341
1342 scale_len = 0;
1343
1344 };
1345
1346 new_val += (scale_len << 2) + 3;
1347 ilen = scale_len + 5;
1348
1349 } else {
1350
1351 do_call = 0;
1352
1353 }
1354
1355 #else
1356 {
1357
1358 u128 new_vall = ((u128)repl) << 8;
1359 u8 scale_len = 0;
1360 u128 tmp_val = (u128)repl;
1361
1362 while (tmp_val) {
1363
1364 tmp_val >>= 8;
1365 ++scale_len;
1366
1367 } // scale_len will be >= 4;
1368
1369 if (scale_len >= 4) {
1370
1371 scale_len -= 4;
1372
1373 } else {
1374
1375 scale_len = 0;
1376
1377 };
1378
1379 new_vall += (scale_len << 2) + 3;
1380 ilen = scale_len + 5;
1381
1382 if (ilen <= its_len && ilen > 1) {
1383
1384 u8 tmpbuf[32];
1385 memcpy(tmpbuf, buf + idx, ilen);
1386 memcpy(buf + idx, (char *)&new_vall, ilen);
1387
1388 if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
1389 #ifdef CMPLOG_COMBINE
1390 if (*status == 1) { memcpy(cbuf + idx, (char *)&new_vall, ilen); }
1391 #endif
1392 memcpy(buf + idx, tmpbuf, ilen);
1393
1394 };
1395
1396 do_call = 0;
1397
1398 }
1399
1400 #endif
1401
1402 }
1403
1404 if (do_call) {
1405
1406 if (ilen <= its_len && ilen > 1) {
1407
1408 u8 tmpbuf[32];
1409 memcpy(tmpbuf, buf + idx, ilen);
1410 memcpy(buf + idx, (char *)&new_val, ilen);
1411
1412 if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
1413 #ifdef CMPLOG_COMBINE
1414 if (*status == 1) { memcpy(cbuf + idx, (char *)&new_val, ilen); }
1415 #endif
1416 memcpy(buf + idx, tmpbuf, ilen);
1417
1418 };
1419
1420 }
1421
1422 }
1423
1424 // here we add and subtract 1 from the value, but only if it is not an
1425 // == or != comparison
1426 // Bits: 1 = Equal, 2 = Greater, 4 = Lesser, 8 = Float
1427 // 16 = modified float, 32 = modified integer (modified = wont match
1428 // in original buffer)
1429
1430 if (!afl->cmplog_enable_arith || lvl < LVL3 || attr == IS_TRANSFORM) {
1431
1432 return 0;
1433
1434 }
1435
1436 if (!(attr & (IS_GREATER | IS_LESSER)) || hshape < 4) { return 0; }
1437
1438 // transform >= to < and <= to >
1439 if ((attr & IS_EQUAL) && (attr & (IS_GREATER | IS_LESSER))) {
1440
1441 if (attr & 2) {
1442
1443 attr += 2;
1444
1445 } else {
1446
1447 attr -= 2;
1448
1449 }
1450
1451 }
1452
1453 // lesser/greater FP comparison
1454 if (attr >= IS_FP && attr < IS_FP_MOD) {
1455
1456 u64 repl_new;
1457
1458 if (attr & IS_GREATER) {
1459
1460 if (hshape == 4 && its_len >= 4) {
1461
1462 float *f = (float *)&repl;
1463 float g = *f;
1464 g += 1.0;
1465 u32 *r = (u32 *)&g;
1466 repl_new = (u32)*r;
1467
1468 } else if (hshape == 8 && its_len >= 8) {
1469
1470 double *f = (double *)&repl;
1471 double g = *f;
1472 g += 1.0;
1473
1474 u64 *r = (u64 *)&g;
1475 repl_new = *r;
1476
1477 } else {
1478
1479 return 0;
1480
1481 }
1482
1483 changed_val = repl_new;
1484
1485 if (unlikely(cmp_extend_encoding(
1486 afl, h, pattern, repl_new, o_pattern, changed_val, 16, idx,
1487 taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) {
1488
1489 return 1;
1490
1491 }
1492
1493 } else {
1494
1495 if (hshape == 4) {
1496
1497 float *f = (float *)&repl;
1498 float g = *f;
1499 g -= 1.0;
1500 u32 *r = (u32 *)&g;
1501 repl_new = (u32)*r;
1502
1503 } else if (hshape == 8) {
1504
1505 double *f = (double *)&repl;
1506 double g = *f;
1507 g -= 1.0;
1508 u64 *r = (u64 *)&g;
1509 repl_new = *r;
1510
1511 } else {
1512
1513 return 0;
1514
1515 }
1516
1517 changed_val = repl_new;
1518
1519 if (unlikely(cmp_extend_encoding(
1520 afl, h, pattern, repl_new, o_pattern, changed_val, 16, idx,
1521 taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) {
1522
1523 return 1;
1524
1525 }
1526
1527 }
1528
1529 // transform double to float, llvm likes to do that internally ...
1530 if (hshape == 8 && its_len >= 4) {
1531
1532 double *f = (double *)&repl;
1533 float g = (float)*f;
1534 repl_new = 0;
1535 #if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
1536 memcpy((char *)&repl_new, (char *)&g, 4);
1537 #else
1538 memcpy(((char *)&repl_new) + 4, (char *)&g, 4);
1539 #endif
1540 changed_val = repl_new;
1541 hshape = 4; // modify shape
1542
1543 // fprintf(stderr, "DOUBLE2FLOAT %llx\n", repl_new);
1544
1545 if (unlikely(cmp_extend_encoding(
1546 afl, h, pattern, repl_new, o_pattern, changed_val, 16, idx,
1547 taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) {
1548
1549 hshape = 8; // recover shape
1550 return 1;
1551
1552 }
1553
1554 hshape = 8; // recover shape
1555
1556 }
1557
1558 }
1559
1560 else if (attr < IS_FP) {
1561
1562 // lesser/greater integer comparison
1563
1564 u64 repl_new;
1565
1566 if (attr & IS_GREATER) {
1567
1568 repl_new = repl + 1;
1569 changed_val = repl_new;
1570 if (unlikely(cmp_extend_encoding(
1571 afl, h, pattern, repl_new, o_pattern, changed_val, 32, idx,
1572 taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) {
1573
1574 return 1;
1575
1576 }
1577
1578 } else {
1579
1580 repl_new = repl - 1;
1581 changed_val = repl_new;
1582 if (unlikely(cmp_extend_encoding(
1583 afl, h, pattern, repl_new, o_pattern, changed_val, 32, idx,
1584 taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) {
1585
1586 return 1;
1587
1588 }
1589
1590 }
1591
1592 }
1593
1594 // #endif /*
1595 // CMPLOG_SOLVE_ARITHMETIC
1596
1597 return 0;
1598
1599 }
1600
1601 #ifdef WORD_SIZE_64
1602
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)1603 static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h,
1604 u128 pattern, u128 repl, u128 o_pattern,
1605 u128 changed_val, u8 attr, u32 idx,
1606 u32 taint_len, u8 *orig_buf, u8 *buf, u8 *cbuf,
1607 u32 len, u8 do_reverse, u8 lvl, u8 *status) {
1608
1609 if (unlikely(afl->fsrv.total_execs - last_update > screen_update)) {
1610
1611 show_stats(afl);
1612 last_update = afl->fsrv.total_execs;
1613
1614 }
1615
1616 u8 *ptr = (u8 *)&buf[idx];
1617 u8 *o_ptr = (u8 *)&orig_buf[idx];
1618 u8 *p = (u8 *)&pattern;
1619 u8 *o_p = (u8 *)&o_pattern;
1620 u8 *r = (u8 *)&repl;
1621 u8 backup[16];
1622 u32 its_len = MIN(len - idx, taint_len);
1623 #if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
1624 size_t off = 0;
1625 #else
1626 size_t off = 16 - hshape;
1627 #endif
1628
1629 if (its_len >= hshape) {
1630
1631 #ifdef _DEBUG
1632 fprintf(stderr, "TestUN: %u>=%u (len=%u idx=%u attr=%u off=%lu) (%u) ",
1633 its_len, hshape, len, idx, attr, off, do_reverse);
1634 u32 i;
1635 u8 *o_r = (u8 *)&changed_val;
1636 for (i = 0; i < hshape; i++)
1637 fprintf(stderr, "%02x", ptr[i]);
1638 fprintf(stderr, "==");
1639 for (i = 0; i < hshape; i++)
1640 fprintf(stderr, "%02x", p[off + i]);
1641 fprintf(stderr, " ");
1642 for (i = 0; i < hshape; i++)
1643 fprintf(stderr, "%02x", o_ptr[i]);
1644 fprintf(stderr, "==");
1645 for (i = 0; i < hshape; i++)
1646 fprintf(stderr, "%02x", o_p[off + i]);
1647 fprintf(stderr, " <= ");
1648 for (i = 0; i < hshape; i++)
1649 fprintf(stderr, "%02x", r[off + i]);
1650 fprintf(stderr, "<-");
1651 for (i = 0; i < hshape; i++)
1652 fprintf(stderr, "%02x", o_r[off + i]);
1653 fprintf(stderr, "\n");
1654 #endif
1655
1656 if (!memcmp(ptr, p + off, hshape) && !memcmp(o_ptr, o_p + off, hshape)) {
1657
1658 memcpy(backup, ptr, hshape);
1659 memcpy(ptr, r + off, hshape);
1660
1661 if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
1662
1663 #ifdef CMPLOG_COMBINE
1664 if (*status == 1) { memcpy(cbuf + idx, r, hshape); }
1665 #endif
1666
1667 memcpy(ptr, backup, hshape);
1668
1669 #ifdef _DEBUG
1670 fprintf(stderr, "Status=%u\n", *status);
1671 #endif
1672
1673 }
1674
1675 // reverse encoding
1676 if (do_reverse && *status != 1) {
1677
1678 if (unlikely(cmp_extend_encodingN(
1679 afl, h, SWAPN(pattern, (hshape << 3)), SWAPN(repl, (hshape << 3)),
1680 SWAPN(o_pattern, (hshape << 3)),
1681 SWAPN(changed_val, (hshape << 3)), attr, idx, taint_len, orig_buf,
1682 buf, cbuf, len, 0, lvl, status))) {
1683
1684 return 1;
1685
1686 }
1687
1688 }
1689
1690 // Scale encoding only works on little endian systems
1691
1692 if (attr < IS_FP && attr < 32 &&
1693 (afl->cmplog_enable_scale || lvl >= LVL3)) {
1694
1695 u128 new_val = repl << 2;
1696 u128 max_scale = (u128)1 << 120;
1697 u32 ilen = 0;
1698 u8 do_call = 1;
1699
1700 if (new_val <= 255) {
1701
1702 ilen = 1;
1703
1704 } else if (new_val <= 65535) {
1705
1706 new_val += 1; // two byte mode
1707 ilen = 2;
1708
1709 } else if (new_val <= 4294967295) {
1710
1711 new_val += 2; // four byte mode
1712 ilen = 4;
1713
1714 } else if (repl < max_scale) {
1715
1716 new_val = (u128)repl << 8;
1717 u8 scale_len = 0;
1718 u128 tmp_val = (u128)repl;
1719 while (tmp_val) {
1720
1721 tmp_val >>= 8;
1722 ++scale_len;
1723
1724 } // scale_len will be >= 4;
1725
1726 if (scale_len >= 4) {
1727
1728 scale_len -= 4;
1729
1730 } else {
1731
1732 scale_len = 0;
1733
1734 };
1735
1736 new_val += (scale_len << 2) + 3;
1737 ilen = scale_len + 5;
1738
1739 } else {
1740
1741 do_call = 0;
1742
1743 }
1744
1745 if (do_call && ilen <= its_len) {
1746
1747 u8 tmpbuf[32];
1748 memcpy(tmpbuf, buf + idx, ilen);
1749 memcpy(buf + idx, (char *)&new_val, ilen);
1750
1751 if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
1752 #ifdef CMPLOG_COMBINE
1753 if (*status == 1) { memcpy(cbuf + idx, (char *)&new_val, ilen); }
1754 #endif
1755 memcpy(buf + idx, tmpbuf, ilen);
1756
1757 };
1758
1759 }
1760
1761 }
1762
1763 return 0;
1764
1765 }
1766
1767 #endif
1768
try_to_add_to_dict(afl_state_t * afl,u64 v,u8 shape)1769 static void try_to_add_to_dict(afl_state_t *afl, u64 v, u8 shape) {
1770
1771 u8 *b = (u8 *)&v;
1772
1773 u32 k;
1774 u8 cons_ff = 0, cons_0 = 0;
1775 for (k = 0; k < shape; ++k) {
1776
1777 if (b[k] == 0) {
1778
1779 ++cons_0;
1780
1781 } else if (b[k] == 0xff) {
1782
1783 ++cons_ff;
1784
1785 } else {
1786
1787 cons_0 = cons_ff = 0;
1788
1789 }
1790
1791 if (cons_0 > 1 || cons_ff > 1) { return; }
1792
1793 }
1794
1795 maybe_add_auto(afl, (u8 *)&v, shape);
1796
1797 u64 rev;
1798 switch (shape) {
1799
1800 case 1:
1801 break;
1802 case 2:
1803 rev = SWAP16((u16)v);
1804 maybe_add_auto(afl, (u8 *)&rev, shape);
1805 break;
1806 case 4:
1807 rev = SWAP32((u32)v);
1808 maybe_add_auto(afl, (u8 *)&rev, shape);
1809 break;
1810 case 8:
1811 rev = SWAP64(v);
1812 maybe_add_auto(afl, (u8 *)&rev, shape);
1813 break;
1814
1815 }
1816
1817 }
1818
1819 #ifdef WORD_SIZE_64
try_to_add_to_dictN(afl_state_t * afl,u128 v,u8 size)1820 static void try_to_add_to_dictN(afl_state_t *afl, u128 v, u8 size) {
1821
1822 u8 *b = (u8 *)&v;
1823
1824 u32 k;
1825 u8 cons_ff = 0, cons_0 = 0;
1826 #if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
1827 u32 off = 0;
1828 for (k = 0; k < size; ++k) {
1829
1830 #else
1831 u32 off = 16 - size;
1832 for (k = 16 - size; k < 16; ++k) {
1833
1834 #endif
1835 if (b[k] == 0) {
1836
1837 ++cons_0;
1838
1839 } else if (b[k] == 0xff) {
1840
1841 ++cons_ff;
1842
1843 } else {
1844
1845 cons_0 = cons_ff = 0;
1846
1847 }
1848
1849 if (cons_0 > 1 || cons_ff > 1) { return; }
1850
1851 }
1852
1853 maybe_add_auto(afl, (u8 *)&v + off, size);
1854 u128 rev = SWAPN(v, size);
1855 maybe_add_auto(afl, (u8 *)&rev + off, size);
1856
1857 }
1858
1859 #endif
1860
1861 #define SWAPA(_x) ((_x & 0xf8) + ((_x & 7) ^ 0x07))
1862
1863 static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
1864 u32 len, u32 lvl, struct tainted *taint) {
1865
1866 struct cmp_header *h = &afl->shm.cmp_map->headers[key];
1867 struct tainted *t;
1868 u32 i, j, idx, taint_len, loggeds;
1869 u32 have_taint = 1;
1870 u8 status = 0, found_one = 0;
1871
1872 /* loop cmps are useless, detect and ignore them */
1873 #ifdef WORD_SIZE_64
1874 u32 is_n = 0;
1875 u128 s128_v0 = 0, s128_v1 = 0, orig_s128_v0 = 0, orig_s128_v1 = 0;
1876 #endif
1877 u64 s_v0, s_v1;
1878 u8 s_v0_fixed = 1, s_v1_fixed = 1;
1879 u8 s_v0_inc = 1, s_v1_inc = 1;
1880 u8 s_v0_dec = 1, s_v1_dec = 1;
1881
1882 hshape = SHAPE_BYTES(h->shape);
1883
1884 if (h->hits > CMP_MAP_H) {
1885
1886 loggeds = CMP_MAP_H;
1887
1888 } else {
1889
1890 loggeds = h->hits;
1891
1892 }
1893
1894 #ifdef WORD_SIZE_64
1895 switch (hshape) {
1896
1897 case 1:
1898 case 2:
1899 case 4:
1900 case 8:
1901 break;
1902 default:
1903 is_n = 1;
1904
1905 }
1906
1907 #endif
1908
1909 if (hshape < 2) { return 0; }
1910
1911 for (i = 0; i < loggeds; ++i) {
1912
1913 struct cmp_operands *o = &afl->shm.cmp_map->log[key][i];
1914
1915 // loop detection code
1916 if (i == 0) {
1917
1918 s_v0 = o->v0;
1919 s_v1 = o->v1;
1920
1921 } else {
1922
1923 if (s_v0 != o->v0) { s_v0_fixed = 0; }
1924 if (s_v1 != o->v1) { s_v1_fixed = 0; }
1925 if (s_v0 + 1 != o->v0) { s_v0_inc = 0; }
1926 if (s_v1 + 1 != o->v1) { s_v1_inc = 0; }
1927 if (s_v0 - 1 != o->v0) { s_v0_dec = 0; }
1928 if (s_v1 - 1 != o->v1) { s_v1_dec = 0; }
1929 s_v0 = o->v0;
1930 s_v1 = o->v1;
1931
1932 }
1933
1934 struct cmp_operands *orig_o = &afl->orig_cmp_map->log[key][i];
1935
1936 // opt not in the paper
1937 for (j = 0; j < i; ++j) {
1938
1939 if (afl->shm.cmp_map->log[key][j].v0 == o->v0 &&
1940 afl->shm.cmp_map->log[key][j].v1 == o->v1) {
1941
1942 goto cmp_fuzz_next_iter;
1943
1944 }
1945
1946 }
1947
1948 #ifdef _DEBUG
1949 fprintf(stderr, "Handling: %llx->%llx vs %llx->%llx attr=%u shape=%u\n",
1950 orig_o->v0, o->v0, orig_o->v1, o->v1, h->attribute, hshape);
1951 #endif
1952
1953 t = taint;
1954 while (t->next) {
1955
1956 t = t->next;
1957
1958 }
1959
1960 #ifdef WORD_SIZE_64
1961 if (unlikely(is_n)) {
1962
1963 s128_v0 = ((u128)o->v0) + (((u128)o->v0_128) << 64);
1964 s128_v1 = ((u128)o->v1) + (((u128)o->v1_128) << 64);
1965 orig_s128_v0 = ((u128)orig_o->v0) + (((u128)orig_o->v0_128) << 64);
1966 orig_s128_v1 = ((u128)orig_o->v1) + (((u128)orig_o->v1_128) << 64);
1967
1968 }
1969
1970 #endif
1971
1972 for (idx = 0; idx < len; ++idx) {
1973
1974 if (have_taint) {
1975
1976 if (!t || idx < t->pos) {
1977
1978 continue;
1979
1980 } else {
1981
1982 taint_len = t->pos + t->len - idx;
1983
1984 if (idx == t->pos + t->len - 1) { t = t->prev; }
1985
1986 }
1987
1988 } else {
1989
1990 taint_len = len - idx;
1991
1992 }
1993
1994 status = 0;
1995
1996 #ifdef WORD_SIZE_64
1997 if (is_n) { // _ExtInt special case including u128
1998
1999 if (s128_v0 != orig_s128_v0 && orig_s128_v0 != orig_s128_v1) {
2000
2001 if (unlikely(cmp_extend_encodingN(
2002 afl, h, s128_v0, s128_v1, orig_s128_v0, orig_s128_v1,
2003 h->attribute, idx, taint_len, orig_buf, buf, cbuf, len, 1,
2004 lvl, &status))) {
2005
2006 return 1;
2007
2008 }
2009
2010 }
2011
2012 if (status == 1) {
2013
2014 found_one = 1;
2015 break;
2016
2017 }
2018
2019 if (s128_v1 != orig_s128_v1 && orig_s128_v1 != orig_s128_v0) {
2020
2021 if (unlikely(cmp_extend_encodingN(
2022 afl, h, s128_v1, s128_v0, orig_s128_v1, orig_s128_v0,
2023 SWAPA(h->attribute), idx, taint_len, orig_buf, buf, cbuf, len,
2024 1, lvl, &status))) {
2025
2026 return 1;
2027
2028 }
2029
2030 }
2031
2032 if (status == 1) {
2033
2034 found_one = 1;
2035 break;
2036
2037 }
2038
2039 }
2040
2041 #endif
2042
2043 #ifdef _DEBUG
2044 if (o->v0 != orig_o->v0 || o->v1 != orig_o->v1)
2045 fprintf(stderr, "key=%u idx=%u o0=%llu v0=%llu o1=%llu v1=%llu\n", key,
2046 idx, orig_o->v0, o->v0, orig_o->v1, o->v1);
2047 #endif
2048
2049 // even for u128 and _ExtInt we do cmp_extend_encoding() because
2050 // if we got here their own special trials failed and it might just be
2051 // a cast from e.g. u64 to u128 from the input data.
2052
2053 if ((o->v0 != orig_o->v0 || lvl >= LVL3) && orig_o->v0 != orig_o->v1) {
2054
2055 if (unlikely(cmp_extend_encoding(
2056 afl, h, o->v0, o->v1, orig_o->v0, orig_o->v1, h->attribute, idx,
2057 taint_len, orig_buf, buf, cbuf, len, 1, lvl, &status))) {
2058
2059 return 1;
2060
2061 }
2062
2063 }
2064
2065 if (status == 1) {
2066
2067 found_one = 1;
2068 break;
2069
2070 }
2071
2072 status = 0;
2073 if ((o->v1 != orig_o->v1 || lvl >= LVL3) && orig_o->v0 != orig_o->v1) {
2074
2075 if (unlikely(cmp_extend_encoding(afl, h, o->v1, o->v0, orig_o->v1,
2076 orig_o->v0, SWAPA(h->attribute), idx,
2077 taint_len, orig_buf, buf, cbuf, len, 1,
2078 lvl, &status))) {
2079
2080 return 1;
2081
2082 }
2083
2084 }
2085
2086 if (status == 1) {
2087
2088 found_one = 1;
2089 break;
2090
2091 }
2092
2093 }
2094
2095 #ifdef _DEBUG
2096 fprintf(stderr,
2097 "END: %llx->%llx vs %llx->%llx attr=%u i=%u found=%u "
2098 "isN=%u size=%u\n",
2099 orig_o->v0, o->v0, orig_o->v1, o->v1, h->attribute, i, found_one,
2100 is_n, hshape);
2101 #endif
2102
2103 // we only learn 16 bit +
2104 if (hshape > 1) {
2105
2106 if (!found_one || afl->queue_cur->is_ascii) {
2107
2108 #ifdef WORD_SIZE_64
2109 if (unlikely(is_n)) {
2110
2111 if (!found_one ||
2112 check_if_text_buf((u8 *)&s128_v0, SHAPE_BYTES(h->shape)) ==
2113 SHAPE_BYTES(h->shape))
2114 try_to_add_to_dictN(afl, s128_v0, SHAPE_BYTES(h->shape));
2115 if (!found_one ||
2116 check_if_text_buf((u8 *)&s128_v1, SHAPE_BYTES(h->shape)) ==
2117 SHAPE_BYTES(h->shape))
2118 try_to_add_to_dictN(afl, s128_v1, SHAPE_BYTES(h->shape));
2119
2120 } else
2121
2122 #endif
2123 {
2124
2125 if (!memcmp((u8 *)&o->v0, (u8 *)&orig_o->v0, SHAPE_BYTES(h->shape)) &&
2126 (!found_one ||
2127 check_if_text_buf((u8 *)&o->v0, SHAPE_BYTES(h->shape)) ==
2128 SHAPE_BYTES(h->shape)))
2129 try_to_add_to_dict(afl, o->v0, SHAPE_BYTES(h->shape));
2130 if (!memcmp((u8 *)&o->v1, (u8 *)&orig_o->v1, SHAPE_BYTES(h->shape)) &&
2131 (!found_one ||
2132 check_if_text_buf((u8 *)&o->v1, SHAPE_BYTES(h->shape)) ==
2133 SHAPE_BYTES(h->shape)))
2134 try_to_add_to_dict(afl, o->v1, SHAPE_BYTES(h->shape));
2135
2136 }
2137
2138 }
2139
2140 }
2141
2142 cmp_fuzz_next_iter:
2143 afl->stage_cur++;
2144
2145 }
2146
2147 if (loggeds > 3 && ((s_v0_fixed && s_v1_inc) || (s_v1_fixed && s_v0_inc) ||
2148 (s_v0_fixed && s_v1_dec) || (s_v1_fixed && s_v0_dec))) {
2149
2150 afl->pass_stats[key].total = afl->pass_stats[key].faileds = 0xff;
2151
2152 }
2153
2154 if (!found_one && afl->pass_stats[key].faileds < 0xff) {
2155
2156 afl->pass_stats[key].faileds++;
2157
2158 }
2159
2160 if (afl->pass_stats[key].total < 0xff) { afl->pass_stats[key].total++; }
2161
2162 return 0;
2163
2164 }
2165
2166 static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
2167 struct cmpfn_operands *o,
2168 struct cmpfn_operands *orig_o, u32 idx,
2169 u32 taint_len, u8 *orig_buf, u8 *buf, u8 *cbuf,
2170 u32 len, u8 lvl, u8 *status) {
2171
2172 #ifndef CMPLOG_COMBINE
2173 (void)(cbuf);
2174 #endif
2175 // #ifndef CMPLOG_SOLVE_TRANSFORM
2176 // (void)(changed_val);
2177 // #endif
2178
2179 if (unlikely(afl->fsrv.total_execs - last_update > screen_update)) {
2180
2181 show_stats(afl);
2182 last_update = afl->fsrv.total_execs;
2183
2184 }
2185
2186 u8 *pattern, *repl, *o_pattern, *changed_val;
2187 u8 l0, l1, ol0, ol1;
2188
2189 if (entry == 0) {
2190
2191 pattern = o->v0;
2192 repl = o->v1;
2193 o_pattern = orig_o->v0;
2194 changed_val = orig_o->v1;
2195 l0 = o->v0_len;
2196 ol0 = orig_o->v0_len;
2197 l1 = o->v1_len;
2198 ol1 = orig_o->v1_len;
2199
2200 } else {
2201
2202 pattern = o->v1;
2203 repl = o->v0;
2204 o_pattern = orig_o->v1;
2205 changed_val = orig_o->v0;
2206 l0 = o->v1_len;
2207 ol0 = orig_o->v1_len;
2208 l1 = o->v0_len;
2209 ol1 = orig_o->v0_len;
2210
2211 }
2212
2213 if (l0 >= 0x80 || ol0 >= 0x80) {
2214
2215 if (l0 >= 0x80) { l0 -= 0x80; }
2216 if (l1 >= 0x80) { l1 -= 0x80; }
2217 if (ol0 >= 0x80) { ol0 -= 0x80; }
2218 if (ol1 >= 0x80) { ol1 -= 0x80; }
2219
2220 }
2221
2222 if (l0 == 0 || l1 == 0 || ol0 == 0 || ol1 == 0 || l0 > 31 || l1 > 31 ||
2223 ol0 > 31 || ol1 > 31) {
2224
2225 l0 = ol0 = hshape;
2226
2227 }
2228
2229 u8 lmax = MAX(l0, ol0);
2230 u8 save[40];
2231 u32 saved_idx = idx, pre, from = 0, to = 0, i, j;
2232 u32 its_len = MIN(MIN(lmax, hshape), len - idx);
2233 its_len = MIN(its_len, taint_len);
2234 u32 saved_its_len = its_len;
2235
2236 // fprintf(stderr, "its_len=%u repl=%s\n", its_len, repl);
2237
2238 if (its_len <= 1) { return 0; }
2239
2240 if (lvl & LVL3) {
2241
2242 if (memcmp(changed_val, repl, its_len) != 0) { return 0; }
2243
2244 u32 max_to = MIN(4U, idx);
2245 if (!(lvl & LVL1) && max_to) { from = 1; }
2246 to = max_to;
2247
2248 }
2249
2250 memcpy(save, &buf[saved_idx - to], its_len + to);
2251 (void)(j);
2252
2253 #ifdef _DEBUG
2254 if (idx == 0) {
2255
2256 fprintf(stderr, "RTN T idx=%u lvl=%02x is_txt=%u shape=%u/%u ", idx, lvl,
2257 o->v0_len >= 0x80 ? 1 : 0, hshape, l0);
2258 for (j = 0; j < 8; j++)
2259 fprintf(stderr, "%02x", orig_buf[idx + j]);
2260 fprintf(stderr, " -> ");
2261 for (j = 0; j < 8; j++)
2262 fprintf(stderr, "%02x", o_pattern[j]);
2263 fprintf(stderr, " <= ");
2264 for (j = 0; j < 8; j++)
2265 fprintf(stderr, "%02x", repl[j]);
2266 fprintf(stderr, "\n");
2267 fprintf(stderr, " ");
2268 for (j = 0; j < 8; j++)
2269 fprintf(stderr, "%02x", buf[idx + j]);
2270 fprintf(stderr, " -> ");
2271 for (j = 0; j < 8; j++)
2272 fprintf(stderr, "%02x", pattern[j]);
2273 fprintf(stderr, " <= ");
2274 for (j = 0; j < 8; j++)
2275 fprintf(stderr, "%02x", changed_val[j]);
2276 fprintf(stderr, "\n");
2277
2278 }
2279
2280 #endif
2281
2282 // Try to match the replace value up to 4 bytes before the current idx.
2283 // This allows matching of eg.:
2284 // if (memcmp(user_val, "TEST") == 0)
2285 // if (memcmp(user_val, "TEST-VALUE") == 0) ...
2286 // We only do this in lvl 3, otherwise we only do direct matching
2287
2288 // fprintf(stderr, "XXXX FROMB64 saved_idx=%u its_len=%u from=%u to=%u FROMHEX
2289 // repl=%s\n", saved_idx, saved_its_len, from, to, repl);
2290
2291 for (pre = from; pre <= to; pre++) {
2292
2293 if (*status != 1 && (!pre || !memcmp(buf + saved_idx - pre, repl, pre))) {
2294
2295 idx = saved_idx - pre;
2296 its_len = saved_its_len + pre;
2297
2298 for (i = 0; i < its_len; ++i) {
2299
2300 if ((pattern[i] != buf[idx + i] || o_pattern[i] != orig_buf[idx + i]) ||
2301 *status == 1) {
2302
2303 break;
2304
2305 }
2306
2307 buf[idx + i] = repl[i];
2308
2309 if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
2310
2311 #ifdef CMPLOG_COMBINE
2312 if (*status == 1) { memcpy(cbuf + idx, &buf[idx], i); }
2313 #endif
2314
2315 }
2316
2317 memcpy(&buf[idx], save + to - pre, i);
2318
2319 }
2320
2321 }
2322
2323 if (*status == 1) return 0;
2324
2325 // transform solving
2326
2327 if (afl->cmplog_enable_transform && (lvl & LVL3)) {
2328
2329 u32 toupper = 0, tolower = 0, xor = 0, arith = 0, tohex = 0, fromhex = 0;
2330 u32 tob64 = 0, fromb64 = 0;
2331 u32 from_0 = 0, from_x = 0, from_X = 0, from_slash = 0, from_up = 0;
2332 u32 to_0 = 0, to_x = 0, to_slash = 0, to_up = 0;
2333 u8 xor_val[32], arith_val[32], tmp[48];
2334
2335 idx = saved_idx;
2336 its_len = saved_its_len;
2337
2338 memcpy(save, &buf[idx], its_len);
2339
2340 for (i = 0; i < its_len; ++i) {
2341
2342 xor_val[i] = pattern[i] ^ buf[idx + i];
2343 arith_val[i] = pattern[i] - buf[idx + i];
2344
2345 if (i == 0) {
2346
2347 if (orig_buf[idx] == '0') {
2348
2349 from_0 = 1;
2350
2351 } else if (orig_buf[idx] == '\\') {
2352
2353 from_slash = 1;
2354
2355 }
2356
2357 if (repl[0] == '0') {
2358
2359 to_0 = 1;
2360
2361 } else if (repl[0] == '\\') {
2362
2363 to_slash = 1;
2364
2365 }
2366
2367 } else if (i == 1) {
2368
2369 if (orig_buf[idx + 1] == 'x') {
2370
2371 from_x = 1;
2372
2373 } else if (orig_buf[idx + 1] == 'X') {
2374
2375 from_X = from_x = 1;
2376
2377 }
2378
2379 if (repl[1] == 'x' || repl[1] == 'X') { to_x = 1; }
2380
2381 }
2382
2383 if (afl->cmplog_enable_xtreme_transform && i < 16 &&
2384 is_hex(repl + (i << 1))) {
2385
2386 ++tohex;
2387
2388 if (!to_up) {
2389
2390 if (repl[i << 1] >= 'A' && repl[i << 1] <= 'F')
2391 to_up = 1;
2392 else if (repl[i << 1] >= 'a' && repl[i << 1] <= 'f')
2393 to_up = 2;
2394 if (repl[(i << 1) + 1] >= 'A' && repl[(i << 1) + 1] <= 'F')
2395 to_up = 1;
2396 else if (repl[(i << 1) + 1] >= 'a' && repl[(i << 1) + 1] <= 'f')
2397 to_up = 2;
2398
2399 }
2400
2401 }
2402
2403 if (afl->cmplog_enable_xtreme_transform && (i % 2) == 1) {
2404
2405 if (len > idx + i + 1 && is_hex(orig_buf + idx + i - 1)) {
2406
2407 fromhex += 2;
2408
2409 if (!from_up) {
2410
2411 if (orig_buf[idx + i] >= 'A' && orig_buf[idx + i] <= 'F')
2412 from_up = 1;
2413 else if (orig_buf[idx + i] >= 'a' && orig_buf[idx + i] <= 'f')
2414 from_up = 2;
2415 if (orig_buf[idx + i - 1] >= 'A' && orig_buf[idx + i - 1] <= 'F')
2416 from_up = 1;
2417 else if (orig_buf[idx + i - 1] >= 'a' &&
2418 orig_buf[idx + i - 1] <= 'f')
2419 from_up = 2;
2420
2421 }
2422
2423 }
2424
2425 }
2426
2427 if (afl->cmplog_enable_xtreme_transform) {
2428
2429 if (i % 3 == 2 && i < 24) {
2430
2431 if (is_base64(repl + ((i / 3) << 2))) tob64 += 3;
2432
2433 }
2434
2435 // fprintf(stderr, "X FROMB64 idx=%u i=%u repl=%s\n", saved_idx, i,
2436 // repl);
2437 if (i % 4 == 3 && i < 24) {
2438
2439 if (is_base64(orig_buf + idx + i - 3)) fromb64 += 4;
2440
2441 }
2442
2443 }
2444
2445 if ((o_pattern[i] ^ orig_buf[idx + i]) == xor_val[i] && xor_val[i]) {
2446
2447 ++xor;
2448
2449 }
2450
2451 if ((o_pattern[i] - orig_buf[idx + i]) == arith_val[i] && arith_val[i]) {
2452
2453 ++arith;
2454
2455 }
2456
2457 if ((buf[idx + i] | 0x20) == pattern[i] &&
2458 (orig_buf[idx + i] | 0x20) == o_pattern[i]) {
2459
2460 ++tolower;
2461
2462 }
2463
2464 if ((buf[idx + i] & 0x5a) == pattern[i] &&
2465 (orig_buf[idx + i] & 0x5a) == o_pattern[i]) {
2466
2467 ++toupper;
2468
2469 }
2470
2471 #ifdef _DEBUG
2472 if (idx == 0) {
2473
2474 fprintf(stderr, "RTN Z %s %s %s %s repl=%s\n", buf, pattern, orig_buf,
2475 o_pattern, repl);
2476 fprintf(
2477 stderr,
2478 "RTN Z idx=%u len=%u loop=%u xor=%u arith=%u tolower=%u toupper=%u "
2479 "tohex=%u fromhex=%u to_0=%u to_slash=%u to_x=%u "
2480 "from_0=%u from_slash=%u from_x=%u\n",
2481 idx, its_len, i, xor, arith, tolower, toupper, tohex, fromhex, to_0,
2482 to_slash, to_x, from_0, from_slash, from_x);
2483 if (afl->cmplog_enable_xtreme_transform) {
2484
2485 fprintf(stderr, "RTN Z idx=%u loop=%u tob64=%u from64=%u\n", idx, i,
2486 tob64, fromb64);
2487
2488 }
2489
2490 }
2491
2492 #endif
2493
2494 if (afl->cmplog_enable_xtreme_transform) {
2495
2496 // input is base64 and converted to binary? convert repl to base64!
2497 // fprintf(stderr, "FROMB64 idx=%u i=%u %% 4 == 3 && i < 24 &&
2498 // fromb64=%u > i, repl=%s\n", saved_idx, i, fromb64, repl);
2499 if ((i % 4) == 3 && i < 24 && fromb64 > i) {
2500
2501 for (u32 hlen = i; hlen + saved_idx < len && hlen <= its_len;
2502 ++hlen) {
2503
2504 u32 res = to_base64(repl, tmp, hlen);
2505 // fprintf(stderr, "FROMB64 GOGO! idx=%u repl=%s tmp[%u]=%s
2506 // hlen=%u\n", saved_idx, repl, res, tmp, hlen);
2507 if (res + saved_idx < len) {
2508
2509 memcpy(buf + idx, tmp, res);
2510 if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
2511 // fprintf(stderr, "RTN ATTEMPT FROMB64 idx=%u fromb64 %u %s %s
2512 // result %u\n", saved_idx, fromb64, tmp, repl,
2513 // *status);
2514
2515 }
2516
2517 }
2518
2519 }
2520
2521 // input is converted to base64? decode repl with base64!
2522 if ((i % 3) == 2 && i < 24 && tob64 > i) {
2523
2524 u32 olen = from_base64(repl, tmp, i + 1);
2525 memcpy(buf + idx, tmp, olen);
2526 if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
2527 // fprintf(stderr, "RTN ATTEMPT tob64 %u idx=%u result %u\n", tob64,
2528 // idx, *status);
2529
2530 }
2531
2532 }
2533
2534 // input is converted to hex? convert repl to binary!
2535 if (afl->cmplog_enable_xtreme_transform && i < 16 && tohex > i) {
2536
2537 u32 off;
2538 if (to_slash + to_x + to_0 == 2) {
2539
2540 off = 2;
2541
2542 } else {
2543
2544 off = 0;
2545
2546 }
2547
2548 for (j = 0; j <= i; j++)
2549 tmp[j] = (hex_table[repl[off + (j << 1)] - '0'] << 4) +
2550 hex_table[repl[off + (j << 1) + 1] - '0'];
2551
2552 memcpy(buf + idx, tmp, i + 1);
2553 if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
2554 // fprintf(stderr, "RTN ATTEMPT tohex %u result %u\n", tohex,
2555 // *status);
2556
2557 }
2558
2559 // input is hex and converted to binary? convert repl to hex!
2560 if (afl->cmplog_enable_xtreme_transform && (i % 2) == 1 && i < 16 &&
2561 fromhex && fromhex + from_slash + from_x + from_0 > i) {
2562
2563 u8 off = 0;
2564 if (from_slash && from_x) {
2565
2566 tmp[0] = '\\';
2567 if (from_X) {
2568
2569 tmp[1] = 'X';
2570
2571 } else {
2572
2573 tmp[1] = 'x';
2574
2575 }
2576
2577 off = 2;
2578
2579 } else if (from_0 && from_x) {
2580
2581 tmp[0] = '0';
2582 if (from_X) {
2583
2584 tmp[1] = 'X';
2585
2586 } else {
2587
2588 tmp[1] = 'x';
2589
2590 }
2591
2592 off = 2;
2593
2594 }
2595
2596 for (u32 hlen = i; hlen <= (i << 1) && hlen + idx < len; hlen += i) {
2597
2598 if (to_up == 1) {
2599
2600 for (j = 0; j <= (hlen >> 1); j++) {
2601
2602 tmp[off + (j << 1)] = hex_table_up[repl[j] >> 4];
2603 tmp[off + (j << 1) + 1] = hex_table_up[repl[j] % 16];
2604
2605 }
2606
2607 } else {
2608
2609 for (j = 0; j <= (hlen >> 1); j++) {
2610
2611 tmp[off + (j << 1)] = hex_table_low[repl[j] >> 4];
2612 tmp[off + (j << 1) + 1] = hex_table_low[repl[j] % 16];
2613
2614 }
2615
2616 }
2617
2618 memcpy(buf + idx, tmp, hlen + 1 + off);
2619 if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
2620 tmp[hlen + 1 + off] = 0;
2621 // fprintf(stderr, "RTN ATTEMPT idx=%u len=%u fromhex %u %s %s result
2622 // %u\n", idx, len, fromhex, tmp, repl, *status);
2623 memcpy(buf + idx, save, hlen + 1 + off);
2624
2625 }
2626
2627 }
2628
2629 if (xor > i) {
2630
2631 for (j = 0; j <= i; j++)
2632 buf[idx + j] = repl[j] ^ xor_val[j];
2633 if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
2634 // fprintf(stderr, "RTN ATTEMPT xor %u result %u\n", xor, *status);
2635
2636 }
2637
2638 if (arith > i && *status != 1) {
2639
2640 for (j = 0; j <= i; j++)
2641 buf[idx + j] = repl[j] - arith_val[j];
2642 if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
2643 // fprintf(stderr, "RTN ATTEMPT arith %u result %u\n", arith,
2644 // *status);
2645
2646 }
2647
2648 if (toupper > i && *status != 1) {
2649
2650 for (j = 0; j <= i; j++)
2651 buf[idx + j] = repl[j] | 0x20;
2652 if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
2653 // fprintf(stderr, "RTN ATTEMPT toupper %u result %u\n", toupper,
2654 // *status);
2655
2656 }
2657
2658 if (tolower > i && *status != 1) {
2659
2660 for (j = 0; j <= i; j++)
2661 buf[idx + j] = repl[j] & 0x5f;
2662 if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
2663 // fprintf(stderr, "RTN ATTEMPT tolower %u result %u\n", tolower,
2664 // *status);
2665
2666 }
2667
2668 #ifdef CMPLOG_COMBINE
2669 if (*status == 1) { memcpy(cbuf + idx, &buf[idx], i + 1); }
2670 #endif
2671
2672 if ((i >= 7 &&
2673 (i >= xor&&i >= arith &&i >= tolower &&i >= toupper &&i > tohex &&i >
2674 (fromhex + from_0 + from_x + from_slash + 1) &&
2675 (afl->cmplog_enable_xtreme_transform && i > tob64 + 3 &&
2676 i > fromb64 + 4))) ||
2677 repl[i] != changed_val[i] || *status == 1) {
2678
2679 break;
2680
2681 }
2682
2683 }
2684
2685 memcpy(&buf[idx], save, i);
2686
2687 }
2688
2689 return 0;
2690
2691 }
2692
2693 static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
2694 u32 len, u8 lvl, struct tainted *taint) {
2695
2696 struct tainted *t;
2697 struct cmp_header *h = &afl->shm.cmp_map->headers[key];
2698 u32 i, idx, have_taint = 1, taint_len, loggeds;
2699 u8 status = 0, found_one = 0;
2700
2701 hshape = SHAPE_BYTES(h->shape);
2702
2703 if (hshape < 2) { return 0; }
2704
2705 if (h->hits > CMP_MAP_RTN_H) {
2706
2707 loggeds = CMP_MAP_RTN_H;
2708
2709 } else {
2710
2711 loggeds = h->hits;
2712
2713 }
2714
2715 for (i = 0; i < loggeds; ++i) {
2716
2717 struct cmpfn_operands *o =
2718 &((struct cmpfn_operands *)afl->shm.cmp_map->log[key])[i];
2719
2720 struct cmpfn_operands *orig_o =
2721 &((struct cmpfn_operands *)afl->orig_cmp_map->log[key])[i];
2722
2723 /*
2724 // opt not in the paper
2725 for (j = 0; j < i; ++j) {
2726
2727 if (!memcmp(&((struct cmpfn_operands *)afl->shm.cmp_map->log[key])[j],
2728 o, sizeof(struct cmpfn_operands))) {
2729
2730 goto rtn_fuzz_next_iter;
2731
2732 }
2733
2734 }
2735
2736 */
2737
2738 #ifdef _DEBUG
2739 u32 j;
2740 struct cmp_header *hh = &afl->orig_cmp_map->headers[key];
2741 fprintf(stderr, "RTN N hits=%u id=%u shape=%u attr=%u v0=", h->hits, h->id,
2742 hshape, h->attribute);
2743 for (j = 0; j < 8; j++)
2744 fprintf(stderr, "%02x", o->v0[j]);
2745 fprintf(stderr, " v1=");
2746 for (j = 0; j < 8; j++)
2747 fprintf(stderr, "%02x", o->v1[j]);
2748 fprintf(stderr, "\nRTN O hits=%u id=%u shape=%u attr=%u o0=", hh->hits,
2749 hh->id, hshape, hh->attribute);
2750 for (j = 0; j < 8; j++)
2751 fprintf(stderr, "%02x", orig_o->v0[j]);
2752 fprintf(stderr, " o1=");
2753 for (j = 0; j < 8; j++)
2754 fprintf(stderr, "%02x", orig_o->v1[j]);
2755 fprintf(stderr, "\n");
2756 #endif
2757
2758 t = taint;
2759 while (t->next) {
2760
2761 t = t->next;
2762
2763 }
2764
2765 for (idx = 0; idx < len; ++idx) {
2766
2767 if (have_taint) {
2768
2769 if (!t || idx < t->pos) {
2770
2771 continue;
2772
2773 } else {
2774
2775 taint_len = t->pos + t->len - idx;
2776
2777 if (idx == t->pos + t->len - 1) { t = t->prev; }
2778
2779 }
2780
2781 } else {
2782
2783 taint_len = len - idx;
2784
2785 }
2786
2787 status = 0;
2788
2789 #ifdef _DEBUG
2790 u32 w;
2791 fprintf(stderr, "key=%u idx=%u len=%u o0=", key, idx, hshape);
2792 for (w = 0; w < hshape; ++w)
2793 fprintf(stderr, "%02x", orig_o->v0[w]);
2794 fprintf(stderr, " v0=");
2795 for (w = 0; w < hshape; ++w)
2796 fprintf(stderr, "%02x", o->v0[w]);
2797 fprintf(stderr, " o1=");
2798 for (w = 0; w < hshape; ++w)
2799 fprintf(stderr, "%02x", orig_o->v1[w]);
2800 fprintf(stderr, " v1=");
2801 for (w = 0; w < hshape; ++w)
2802 fprintf(stderr, "%02x", o->v1[w]);
2803 fprintf(stderr, "\n");
2804 #endif
2805
2806 if (unlikely(rtn_extend_encoding(afl, 0, o, orig_o, idx, taint_len,
2807 orig_buf, buf, cbuf, len, lvl,
2808 &status))) {
2809
2810 return 1;
2811
2812 }
2813
2814 if (status == 1) {
2815
2816 found_one = 1;
2817 break;
2818
2819 }
2820
2821 status = 0;
2822
2823 if (unlikely(rtn_extend_encoding(afl, 1, o, orig_o, idx, taint_len,
2824 orig_buf, buf, cbuf, len, lvl,
2825 &status))) {
2826
2827 return 1;
2828
2829 }
2830
2831 if (status == 1) {
2832
2833 found_one = 1;
2834 break;
2835
2836 }
2837
2838 }
2839
2840 // if (unlikely(!afl->pass_stats[key].total)) {
2841
2842 if ((!found_one && (lvl & LVL1)) || afl->queue_cur->is_ascii) {
2843
2844 // if (unlikely(!afl->pass_stats[key].total)) {
2845
2846 u32 shape_len = SHAPE_BYTES(h->shape);
2847 u32 v0_len = shape_len, v1_len = shape_len;
2848 if (afl->queue_cur->is_ascii ||
2849 check_if_text_buf((u8 *)&o->v0, shape_len) == shape_len) {
2850
2851 if (strlen(o->v0)) v0_len = strlen(o->v0);
2852
2853 }
2854
2855 if (afl->queue_cur->is_ascii ||
2856 check_if_text_buf((u8 *)&o->v1, shape_len) == shape_len) {
2857
2858 if (strlen(o->v1)) v1_len = strlen(o->v1);
2859
2860 }
2861
2862 // fprintf(stderr, "SHOULD: found:%u ascii:%u text?%u:%u %u:%s %u:%s \n",
2863 // found_one, afl->queue_cur->is_ascii, check_if_text_buf((u8 *)&o->v0,
2864 // shape_len), check_if_text_buf((u8 *)&o->v1, shape_len), v0_len,
2865 // o->v0, v1_len, o->v1);
2866
2867 // Note that this check differs from the line 1901, for RTN we are more
2868 // opportunistic for adding to the dictionary than cmps
2869 if (!memcmp(o->v0, orig_o->v0, v0_len) ||
2870 (!found_one || check_if_text_buf((u8 *)&o->v0, v0_len) == v0_len))
2871 maybe_add_auto(afl, o->v0, v0_len);
2872 if (!memcmp(o->v1, orig_o->v1, v1_len) ||
2873 (!found_one || check_if_text_buf((u8 *)&o->v1, v1_len) == v1_len))
2874 maybe_add_auto(afl, o->v1, v1_len);
2875
2876 //}
2877
2878 }
2879
2880 // rtn_fuzz_next_iter:
2881 afl->stage_cur++;
2882
2883 }
2884
2885 if (!found_one && afl->pass_stats[key].faileds < 0xff) {
2886
2887 afl->pass_stats[key].faileds++;
2888
2889 }
2890
2891 if (afl->pass_stats[key].total < 0xff) { afl->pass_stats[key].total++; }
2892
2893 return 0;
2894
2895 }
2896
2897 ///// Input to State stage
2898
2899 // afl->queue_cur->exec_cksum
2900 u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
2901
2902 u8 r = 1;
2903 if (unlikely(!afl->pass_stats)) {
2904
2905 afl->pass_stats = ck_alloc(sizeof(struct afl_pass_stat) * CMP_MAP_W);
2906
2907 }
2908
2909 struct tainted *taint = NULL;
2910 if (likely(afl->queue_cur->exec_us)) {
2911
2912 if (likely((100000 / 2) >= afl->queue_cur->exec_us)) {
2913
2914 screen_update = 100000 / afl->queue_cur->exec_us;
2915
2916 } else {
2917
2918 screen_update = 1;
2919
2920 }
2921
2922 } else {
2923
2924 screen_update = 100000;
2925
2926 }
2927
2928 if (!afl->queue_cur->taint || !afl->queue_cur->cmplog_colorinput) {
2929
2930 if (unlikely(colorization(afl, buf, len, &taint))) { return 1; }
2931
2932 // no taint? still try, create a dummy to prevent again colorization
2933 if (!taint) {
2934
2935 #ifdef _DEBUG
2936 fprintf(stderr, "TAINT FAILED\n");
2937 #endif
2938 afl->queue_cur->colorized = CMPLOG_LVL_MAX;
2939 return 0;
2940
2941 }
2942
2943 #ifdef _DEBUG
2944 else if (taint->pos == 0 && taint->len == len) {
2945
2946 fprintf(stderr, "TAINT FULL\n");
2947
2948 }
2949
2950 #endif
2951
2952 } else {
2953
2954 buf = afl->queue_cur->cmplog_colorinput;
2955 taint = afl->queue_cur->taint;
2956
2957 }
2958
2959 struct tainted *t = taint;
2960
2961 while (t) {
2962
2963 #ifdef _DEBUG
2964 fprintf(stderr, "T: idx=%u len=%u\n", t->pos, t->len);
2965 #endif
2966 t = t->next;
2967
2968 }
2969
2970 #if defined(_DEBUG) || defined(CMPLOG_INTROSPECTION)
2971 u64 start_time = get_cur_time();
2972 u32 cmp_locations = 0;
2973 #endif
2974
2975 // Generate the cmplog data
2976
2977 // manually clear the full cmp_map
2978 memset(afl->shm.cmp_map, 0, sizeof(struct cmp_map));
2979 if (unlikely(common_fuzz_cmplog_stuff(afl, orig_buf, len))) {
2980
2981 afl->queue_cur->colorized = CMPLOG_LVL_MAX;
2982 while (taint) {
2983
2984 t = taint->next;
2985 ck_free(taint);
2986 taint = t;
2987
2988 }
2989
2990 return 1;
2991
2992 }
2993
2994 if (unlikely(!afl->orig_cmp_map)) {
2995
2996 afl->orig_cmp_map = ck_alloc_nozero(sizeof(struct cmp_map));
2997
2998 }
2999
3000 memcpy(afl->orig_cmp_map, afl->shm.cmp_map, sizeof(struct cmp_map));
3001 memset(afl->shm.cmp_map->headers, 0, sizeof(struct cmp_header) * CMP_MAP_W);
3002 if (unlikely(common_fuzz_cmplog_stuff(afl, buf, len))) {
3003
3004 afl->queue_cur->colorized = CMPLOG_LVL_MAX;
3005 while (taint) {
3006
3007 t = taint->next;
3008 ck_free(taint);
3009 taint = t;
3010
3011 }
3012
3013 return 1;
3014
3015 }
3016
3017 #ifdef _DEBUG
3018 dump("ORIG", orig_buf, len);
3019 dump("NEW ", buf, len);
3020 #endif
3021
3022 // Start insertion loop
3023
3024 u64 orig_hit_cnt, new_hit_cnt;
3025 u64 orig_execs = afl->fsrv.total_execs;
3026 orig_hit_cnt = afl->queued_items + afl->saved_crashes;
3027
3028 afl->stage_name = "input-to-state";
3029 afl->stage_short = "its";
3030 afl->stage_max = 0;
3031 afl->stage_cur = 0;
3032
3033 u32 lvl = (afl->queue_cur->colorized ? 0 : LVL1) +
3034 (afl->cmplog_lvl == CMPLOG_LVL_MAX ? LVL3 : 0);
3035
3036 #ifdef CMPLOG_COMBINE
3037 u8 *cbuf = afl_realloc((void **)&afl->in_scratch_buf, len + 128);
3038 memcpy(cbuf, orig_buf, len);
3039 u8 *virgin_backup = afl_realloc((void **)&afl->ex_buf, afl->shm.map_size);
3040 memcpy(virgin_backup, afl->virgin_bits, afl->shm.map_size);
3041 #else
3042 u8 *cbuf = NULL;
3043 #endif
3044
3045 u32 k;
3046 for (k = 0; k < CMP_MAP_W; ++k) {
3047
3048 if (!afl->shm.cmp_map->headers[k].hits) { continue; }
3049
3050 if (afl->pass_stats[k].faileds >= CMPLOG_FAIL_MAX ||
3051 afl->pass_stats[k].total >= CMPLOG_FAIL_MAX) {
3052
3053 #ifdef _DEBUG
3054 fprintf(stderr, "DISABLED %u\n", k);
3055 #endif
3056
3057 afl->shm.cmp_map->headers[k].hits = 0; // ignore this cmp
3058
3059 }
3060
3061 if (afl->shm.cmp_map->headers[k].type == CMP_TYPE_INS) {
3062
3063 // fprintf(stderr, "INS %u\n", k);
3064 afl->stage_max +=
3065 MIN((u32)(afl->shm.cmp_map->headers[k].hits), (u32)CMP_MAP_H);
3066
3067 } else {
3068
3069 // fprintf(stderr, "RTN %u\n", k);
3070 afl->stage_max +=
3071 MIN((u32)(afl->shm.cmp_map->headers[k].hits), (u32)CMP_MAP_RTN_H);
3072
3073 }
3074
3075 }
3076
3077 for (k = 0; k < CMP_MAP_W; ++k) {
3078
3079 if (!afl->shm.cmp_map->headers[k].hits) { continue; }
3080
3081 #if defined(_DEBUG) || defined(CMPLOG_INTROSPECTION)
3082 ++cmp_locations;
3083 #endif
3084
3085 if (afl->shm.cmp_map->headers[k].type == CMP_TYPE_INS) {
3086
3087 if (unlikely(cmp_fuzz(afl, k, orig_buf, buf, cbuf, len, lvl, taint))) {
3088
3089 goto exit_its;
3090
3091 }
3092
3093 } else if ((lvl & LVL1) || ((lvl & LVL3) && afl->cmplog_enable_transform)) {
3094
3095 if (unlikely(rtn_fuzz(afl, k, orig_buf, buf, cbuf, len, lvl, taint))) {
3096
3097 goto exit_its;
3098
3099 }
3100
3101 }
3102
3103 }
3104
3105 r = 0;
3106
3107 exit_its:
3108
3109 if (afl->cmplog_lvl == CMPLOG_LVL_MAX) {
3110
3111 afl->queue_cur->colorized = CMPLOG_LVL_MAX;
3112
3113 if (afl->queue_cur->cmplog_colorinput) {
3114
3115 ck_free(afl->queue_cur->cmplog_colorinput);
3116
3117 }
3118
3119 while (taint) {
3120
3121 t = taint->next;
3122 ck_free(taint);
3123 taint = t;
3124
3125 }
3126
3127 afl->queue_cur->taint = NULL;
3128
3129 } else {
3130
3131 afl->queue_cur->colorized = LVL2;
3132
3133 if (!afl->queue_cur->taint) { afl->queue_cur->taint = taint; }
3134
3135 if (!afl->queue_cur->cmplog_colorinput) {
3136
3137 afl->queue_cur->cmplog_colorinput = ck_alloc_nozero(len);
3138 memcpy(afl->queue_cur->cmplog_colorinput, buf, len);
3139 memcpy(buf, orig_buf, len);
3140
3141 }
3142
3143 }
3144
3145 #ifdef CMPLOG_COMBINE
3146 if (afl->queued_items + afl->saved_crashes > orig_hit_cnt + 1) {
3147
3148 // copy the current virgin bits so we can recover the information
3149 u8 *virgin_save = afl_realloc((void **)&afl->eff_buf, afl->shm.map_size);
3150 memcpy(virgin_save, afl->virgin_bits, afl->shm.map_size);
3151 // reset virgin bits to the backup previous to redqueen
3152 memcpy(afl->virgin_bits, virgin_backup, afl->shm.map_size);
3153
3154 u8 status = 0;
3155 its_fuzz(afl, cbuf, len, &status);
3156
3157 // now combine with the saved virgin bits
3158 #ifdef WORD_SIZE_64
3159 u64 *v = (u64 *)afl->virgin_bits;
3160 u64 *s = (u64 *)virgin_save;
3161 u32 i;
3162 for (i = 0; i < (afl->shm.map_size >> 3); i++) {
3163
3164 v[i] &= s[i];
3165
3166 }
3167
3168 #else
3169 u32 *v = (u32 *)afl->virgin_bits;
3170 u32 *s = (u32 *)virgin_save;
3171 u32 i;
3172 for (i = 0; i < (afl->shm.map_size >> 2); i++) {
3173
3174 v[i] &= s[i];
3175
3176 }
3177
3178 #endif
3179
3180 #ifdef _DEBUG
3181 dump("COMB", cbuf, len);
3182 if (status == 1) {
3183
3184 fprintf(stderr, "NEW CMPLOG_COMBINED\n");
3185
3186 } else {
3187
3188 fprintf(stderr, "NO new combined\n");
3189
3190 }
3191
3192 #endif
3193
3194 }
3195
3196 #endif
3197
3198 new_hit_cnt = afl->queued_items + afl->saved_crashes;
3199 afl->stage_finds[STAGE_ITS] += new_hit_cnt - orig_hit_cnt;
3200 afl->stage_cycles[STAGE_ITS] += afl->fsrv.total_execs - orig_execs;
3201
3202 #if defined(_DEBUG) || defined(CMPLOG_INTROSPECTION)
3203 FILE *f = stderr;
3204 #ifndef _DEBUG
3205 if (afl->not_on_tty) {
3206
3207 char fn[4096];
3208 snprintf(fn, sizeof(fn), "%s/introspection_cmplog.txt", afl->out_dir);
3209 f = fopen(fn, "a");
3210
3211 }
3212
3213 #endif
3214
3215 if (f) {
3216
3217 fprintf(f,
3218 "Cmplog: fname=%s len=%u ms=%llu result=%u finds=%llu entries=%u "
3219 "auto_extra_after=%u\n",
3220 afl->queue_cur->fname, len, get_cur_time() - start_time, r,
3221 new_hit_cnt - orig_hit_cnt, cmp_locations, afl->a_extras_cnt);
3222
3223 #ifndef _DEBUG
3224 if (afl->not_on_tty) { fclose(f); }
3225 #endif
3226
3227 }
3228
3229 #endif
3230
3231 return r;
3232
3233 }
3234
3235