about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorvanhauser-thc <vh@thc.org>2023-10-23 18:03:59 +0200
committervanhauser-thc <vh@thc.org>2023-10-23 18:03:59 +0200
commit4cdf7a1e3e351f10537683d49a08181b6c1576cc (patch)
tree7c30bc36c95bedabe409b94e061b3521d0853771 /src
parenteaa6a1754a2efa54903959a5b3ce3d433dcdea37 (diff)
downloadafl++-4cdf7a1e3e351f10537683d49a08181b6c1576cc.tar.gz
add scale encode mode for cmplog
Diffstat (limited to 'src')
-rw-r--r--src/afl-fuzz-redqueen.c263
-rw-r--r--src/afl-fuzz.c4
2 files changed, 243 insertions, 24 deletions
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;