about summary refs log tree commit diff
path: root/src/afl-fuzz-redqueen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/afl-fuzz-redqueen.c')
-rw-r--r--src/afl-fuzz-redqueen.c132
1 files changed, 118 insertions, 14 deletions
diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c
index 724da407..cb4c78df 100644
--- a/src/afl-fuzz-redqueen.c
+++ b/src/afl-fuzz-redqueen.c
@@ -24,6 +24,7 @@
 
  */
 
+#include <limits.h>
 #include "afl-fuzz.h"
 #include "cmplog.h"
 
@@ -177,6 +178,9 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u64 exec_cksum) {
   afl->stage_cycles[STAGE_COLORIZATION] += afl->stage_cur;
   ck_free(backup);
 
+  ck_free(rng);
+  rng = NULL;
+
   while (ranges) {
 
     rng = ranges;
@@ -186,9 +190,6 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u64 exec_cksum) {
 
   }
 
-  ck_free(rng);
-  rng = NULL;
-
   // save the input with the high entropy
 
   if (needs_write) {
@@ -262,11 +263,64 @@ static u8 its_fuzz(afl_state_t *afl, u8 *buf, u32 len, u8 *status) {
 
 }
 
+static long long strntoll(const char *str, size_t sz, char **end, int base) {
+
+  char        buf[64];
+  long long   ret;
+  const char *beg = str;
+
+  for (; beg && sz && *beg == ' '; beg++, sz--) {};
+
+  if (!sz || sz >= sizeof(buf)) {
+
+    if (end) *end = (char *)str;
+    return 0;
+
+  }
+
+  memcpy(buf, beg, sz);
+  buf[sz] = '\0';
+  ret = strtoll(buf, end, base);
+  if (ret == LLONG_MIN || ret == LLONG_MAX) return ret;
+  if (end) *end = (char *)beg + (*end - buf);
+  return ret;
+
+}
+
+static unsigned long long strntoull(const char *str, size_t sz, char **end,
+                                    int base) {
+
+  char               buf[64];
+  unsigned long long ret;
+  const char *       beg = str;
+
+  for (; beg && sz && *beg == ' '; beg++, sz--)
+    ;
+
+  if (!sz || sz >= sizeof(buf)) {
+
+    if (end) *end = (char *)str;
+    return 0;
+
+  }
+
+  memcpy(buf, beg, sz);
+  buf[sz] = '\0';
+  ret = strtoull(buf, end, base);
+  if (end) *end = (char *)beg + (*end - buf);
+  return ret;
+
+}
+
+#define BUF_PARAMS(name) (void **)&afl->name##_buf, &afl->name##_size
+
 static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
                               u64 pattern, u64 repl, u64 o_pattern, u32 idx,
                               u8 *orig_buf, u8 *buf, u32 len, u8 do_reverse,
                               u8 *status) {
 
+  if (!buf) { FATAL("BUG: buf was NULL. Please report this.\n"); }
+
   u64 *buf_64 = (u64 *)&buf[idx];
   u32 *buf_32 = (u32 *)&buf[idx];
   u16 *buf_16 = (u16 *)&buf[idx];
@@ -277,9 +331,56 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
   u8 * o_buf_8 = &orig_buf[idx];
 
   u32 its_len = len - idx;
-  *status = 0;
+  // *status = 0;
+
+  u8 *               endptr;
+  u8                 use_num = 0, use_unum = 0;
+  unsigned long long unum;
+  long long          num;
+  if (afl->queue_cur->is_ascii) {
+
+    endptr = buf_8;
+    num = strntoll(buf_8, len - idx, (char **)&endptr, 0);
+    if (endptr == buf_8) {
+
+      unum = strntoull(buf_8, len - idx, (char **)&endptr, 0);
+      if (endptr == buf_8) use_unum = 1;
+
+    } else
+
+      use_num = 1;
+
+  }
+
+  if (use_num && num == pattern) {
 
-  if (SHAPE_BYTES(h->shape) == 8) {
+    size_t old_len = endptr - buf_8;
+    size_t num_len = snprintf(NULL, 0, "%lld", num);
+
+    u8 *new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), len + num_len);
+    memcpy(new_buf, buf, idx);
+
+    snprintf(new_buf + idx, num_len, "%lld", num);
+    memcpy(new_buf + idx + num_len, buf_8 + old_len, len - idx - old_len);
+
+    if (unlikely(its_fuzz(afl, new_buf, len, status))) { return 1; }
+
+  } else if (use_unum && unum == pattern) {
+
+    size_t old_len = endptr - buf_8;
+    size_t num_len = snprintf(NULL, 0, "%llu", unum);
+
+    u8 *new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), len + num_len);
+    memcpy(new_buf, buf, idx);
+
+    snprintf(new_buf + idx, num_len, "%llu", unum);
+    memcpy(new_buf + idx + num_len, buf_8 + old_len, len - idx - old_len);
+
+    if (unlikely(its_fuzz(afl, new_buf, len, status))) { return 1; }
+
+  }
+
+  if (SHAPE_BYTES(h->shape) >= 8 && *status != 1) {
 
     if (its_len >= 8 && *buf_64 == pattern && *o_buf_64 == o_pattern) {
 
@@ -290,7 +391,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
     }
 
     // reverse encoding
-    if (do_reverse) {
+    if (do_reverse && *status != 1) {
 
       if (unlikely(cmp_extend_encoding(afl, h, SWAP64(pattern), SWAP64(repl),
                                        SWAP64(o_pattern), idx, orig_buf, buf,
@@ -304,7 +405,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
 
   }
 
-  if (SHAPE_BYTES(h->shape) == 4 || *status == 2) {
+  if (SHAPE_BYTES(h->shape) >= 4 && *status != 1) {
 
     if (its_len >= 4 && *buf_32 == (u32)pattern &&
         *o_buf_32 == (u32)o_pattern) {
@@ -316,7 +417,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
     }
 
     // reverse encoding
-    if (do_reverse) {
+    if (do_reverse && *status != 1) {
 
       if (unlikely(cmp_extend_encoding(afl, h, SWAP32(pattern), SWAP32(repl),
                                        SWAP32(o_pattern), idx, orig_buf, buf,
@@ -330,7 +431,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
 
   }
 
-  if (SHAPE_BYTES(h->shape) == 2 || *status == 2) {
+  if (SHAPE_BYTES(h->shape) >= 2 && *status != 1) {
 
     if (its_len >= 2 && *buf_16 == (u16)pattern &&
         *o_buf_16 == (u16)o_pattern) {
@@ -342,7 +443,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
     }
 
     // reverse encoding
-    if (do_reverse) {
+    if (do_reverse && *status != 1) {
 
       if (unlikely(cmp_extend_encoding(afl, h, SWAP16(pattern), SWAP16(repl),
                                        SWAP16(o_pattern), idx, orig_buf, buf,
@@ -356,7 +457,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
 
   }
 
-  if (SHAPE_BYTES(h->shape) == 1 || *status == 2) {
+  if (SHAPE_BYTES(h->shape) >= 1 && *status != 1) {
 
     if (its_len >= 1 && *buf_8 == (u8)pattern && *o_buf_8 == (u8)o_pattern) {
 
@@ -482,6 +583,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) {
 
     for (idx = 0; idx < len && fails < 8; ++idx) {
 
+      status = 0;
       if (unlikely(cmp_extend_encoding(afl, h, o->v0, o->v1, orig_o->v0, idx,
                                        orig_buf, buf, len, 1, &status))) {
 
@@ -499,6 +601,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) {
 
       }
 
+      status = 0;
       if (unlikely(cmp_extend_encoding(afl, h, o->v1, o->v0, orig_o->v1, idx,
                                        orig_buf, buf, len, 1, &status))) {
 
@@ -570,14 +673,15 @@ static u8 rtn_extend_encoding(afl_state_t *afl, struct cmp_header *h,
 
   for (i = 0; i < its_len; ++i) {
 
-    if (pattern[idx + i] != buf[idx + i] ||
-        o_pattern[idx + i] != orig_buf[idx + i] || *status == 1) {
+    if (pattern[i] != buf[idx + i] || o_pattern[i] != orig_buf[idx + i] ||
+        *status == 1) {
 
       break;
 
     }
 
-    buf[idx + i] = repl[idx + i];
+    buf[idx + i] = repl[i];
+
     if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
 
   }