about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDominik Maier <domenukk@gmail.com>2020-06-22 21:58:16 +0200
committerDominik Maier <domenukk@gmail.com>2020-06-22 21:58:23 +0200
commit7119bf5d860657dab7afb60fab8b7ad5dc0ef222 (patch)
tree8146668f22141e8f86627e451ad9d65cf99314d1
parentea1222b33fb5e97165f649168b812d83ed1ed8c4 (diff)
downloadafl++-7119bf5d860657dab7afb60fab8b7ad5dc0ef222.tar.gz
Added rand, hash unittests
-rw-r--r--.gitignore2
-rw-r--r--GNUmakefile23
-rw-r--r--include/afl-fuzz.h8
-rw-r--r--src/afl-fuzz-one.c2
-rw-r--r--src/afl-fuzz.c9
-rw-r--r--src/afl-performance.c10
-rw-r--r--test/unittests/unit_hash.c75
-rw-r--r--test/unittests/unit_rand.c84
8 files changed, 197 insertions, 16 deletions
diff --git a/.gitignore b/.gitignore
index 505a4ecb..8448c8f6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -49,5 +49,7 @@ core\.*
 test/unittests/unit_maybe_alloc
 test/unittests/unit_preallocable
 test/unittests/unit_list
+test/unittests/unit_rand
+test/unittests/unit_hash
 examples/afl_network_proxy/afl-network-server
 examples/afl_network_proxy/afl-network-client
diff --git a/GNUmakefile b/GNUmakefile
index a171e916..5a739ad8 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -403,13 +403,24 @@ document: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/
 test/unittests/unit_maybe_alloc.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_maybe_alloc.c $(AFL_FUZZ_FILES)
 	@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_maybe_alloc.c -o test/unittests/unit_maybe_alloc.o
 
-test/unittests/unit_preallocable.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_preallocable.c $(AFL_FUZZ_FILES)
-	@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_preallocable.c -o test/unittests/unit_preallocable.o
-
 unit_maybe_alloc: test/unittests/unit_maybe_alloc.o
 	@$(CC) $(CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_maybe_alloc.o -o test/unittests/unit_maybe_alloc $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
 	./test/unittests/unit_maybe_alloc
 
+test/unittests/unit_hash.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_hash.c $(AFL_FUZZ_FILES) src/afl-performance.o
+	@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_hash.c -o test/unittests/unit_hash.o
+
+unit_hash: test/unittests/unit_hash.o src/afl-performance.o
+	@$(CC) $(CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_hash $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
+	./test/unittests/unit_hash
+
+test/unittests/unit_rand.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_rand.c $(AFL_FUZZ_FILES) src/afl-performance.o
+	@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_rand.c -o test/unittests/unit_rand.o
+
+unit_rand: test/unittests/unit_rand.o src/afl-common.o src/afl-performance.o
+	@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_rand  $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
+	./test/unittests/unit_rand
+
 test/unittests/unit_list.o : $(COMM_HDR) include/list.h test/unittests/unit_list.c $(AFL_FUZZ_FILES)
 	@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_list.c -o test/unittests/unit_list.o
 
@@ -417,8 +428,8 @@ unit_list: test/unittests/unit_list.o
 	@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_list.o -o test/unittests/unit_list  $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
 	./test/unittests/unit_list
 
-test/unittests/preallocable.o : $(COMM_HDR) include/afl-prealloc.h test/unittests/preallocable.c $(AFL_FUZZ_FILES)
-	@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(CFLAGS_FLTO) -c test/unittests/preallocable.c -o test/unittests/preallocable.o
+test/unittests/unit_preallocable.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_preallocable.c $(AFL_FUZZ_FILES)
+	@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_preallocable.c -o test/unittests/unit_preallocable.o
 
 unit_preallocable: test/unittests/unit_preallocable.o
 	@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_preallocable.o -o test/unittests/unit_preallocable $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
@@ -429,7 +440,7 @@ unit_clean:
 
 ifneq "$(shell uname)" "Darwin"
 
-unit: unit_maybe_alloc unit_preallocable unit_list unit_clean
+unit: unit_maybe_alloc unit_preallocable unit_list unit_clean unit_rand unit_hash
 
 else
 
diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h
index e7b52d56..16f7d717 100644
--- a/include/afl-fuzz.h
+++ b/include/afl-fuzz.h
@@ -49,6 +49,7 @@
 #include "sharedmem.h"
 #include "forkserver.h"
 #include "common.h"
+#include "hash.h"
 
 #include <stdio.h>
 #include <unistd.h>
@@ -971,13 +972,16 @@ static inline u32 rand_below(afl_state_t *afl, u32 limit) {
 
 }
 
-static inline u32 get_rand_seed(afl_state_t *afl) {
+static inline s64 rand_get_seed(afl_state_t *afl) {
 
-  if (unlikely(afl->fixed_seed)) { return (u32)afl->init_seed; }
+  if (unlikely(afl->fixed_seed)) { return afl->init_seed; }
   return afl->rand_seed[0];
 
 }
 
+/* initialize randomness with a given seed. Can be called again at any time. */
+void rand_set_seed(afl_state_t *afl, s64 init_seed);
+
 /* Find first power of two greater or equal to val (assuming val under
    2^63). */
 
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index e42a323d..60db9777 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -2458,7 +2458,7 @@ radamsa_stage:
   for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
 
     u32 new_len = afl->radamsa_mutate_ptr(save_buf, len, new_buf, max_len,
-                                          get_rand_seed(afl));
+                                          rand_get_seed(afl));
 
     if (new_len) {
 
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index bfd7cb33..c8083f71 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -289,7 +289,7 @@ int main(int argc, char **argv_orig, char **envp) {
   doc_path = access(DOC_PATH, F_OK) != 0 ? (u8 *)"docs" : (u8 *)DOC_PATH;
 
   gettimeofday(&tv, &tz);
-  afl->init_seed = tv.tv_sec ^ tv.tv_usec ^ getpid();
+  rand_set_seed(afl, tv.tv_sec ^ tv.tv_usec ^ getpid());
 
   while ((opt = getopt(argc, argv,
                        "+c:i:I:o:f:m:t:T:dnCB:S:M:x:QNUWe:p:s:V:E:L:hRP:")) >
@@ -311,7 +311,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
       case 's': {
 
-        afl->init_seed = strtoul(optarg, 0L, 10);
+        rand_set_seed(afl, strtoul(optarg, 0L, 10));
         afl->fixed_seed = 1;
         break;
 
@@ -833,11 +833,6 @@ int main(int argc, char **argv_orig, char **envp) {
 
   }
 
-  afl->rand_seed[0] = hash64((void *)&afl->init_seed, sizeof(u32), HASH_CONST);
-  afl->rand_seed[1] = afl->rand_seed[0] ^ 0x1234567890abcdef;
-  afl->rand_seed[2] = afl->rand_seed[0] & 0x0123456789abcdef;
-  afl->rand_seed[3] = afl->rand_seed[0] | 0x01abcde43f567908;
-
   if (afl->use_radamsa) {
 
     if (afl->limit_time_sig > 0) {
diff --git a/src/afl-performance.c b/src/afl-performance.c
index 8efefcd8..757bbe1e 100644
--- a/src/afl-performance.c
+++ b/src/afl-performance.c
@@ -33,6 +33,16 @@ static inline uint64_t rotl(const uint64_t x, int k) {
 
 }
 
+void rand_set_seed(afl_state_t *afl, s64 init_seed) {
+
+  afl->init_seed = init_seed;
+  afl->rand_seed[0] = hash64((void *)&afl->init_seed, sizeof(afl->init_seed), HASH_CONST);
+  afl->rand_seed[1] = afl->rand_seed[0] ^ 0x1234567890abcdef;
+  afl->rand_seed[2] = afl->rand_seed[0] & 0x0123456789abcdef;
+  afl->rand_seed[3] = afl->rand_seed[0] | 0x01abcde43f567908;
+
+}
+
 uint64_t rand_next(afl_state_t *afl) {
 
   const uint64_t result =
diff --git a/test/unittests/unit_hash.c b/test/unittests/unit_hash.c
new file mode 100644
index 00000000..041d107a
--- /dev/null
+++ b/test/unittests/unit_hash.c
@@ -0,0 +1,75 @@
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <assert.h>
+#include <cmocka.h>
+/* cmocka < 1.0 didn't support these features we need */
+#ifndef assert_ptr_equal
+#define assert_ptr_equal(a, b) \
+    _assert_int_equal(cast_ptr_to_largest_integral_type(a), \
+                      cast_ptr_to_largest_integral_type(b), \
+                      __FILE__, __LINE__)
+#define CMUnitTest UnitTest
+#define cmocka_unit_test unit_test
+#define cmocka_run_group_tests(t, setup, teardown) run_tests(t)
+#endif
+
+
+extern void mock_assert(const int result, const char* const expression,
+                        const char * const file, const int line);
+#undef assert
+#define assert(expression) \
+    mock_assert((int)(expression), #expression, __FILE__, __LINE__);
+
+#include "afl-fuzz.h"
+#include "hash.h"
+
+/* remap exit -> assert, then use cmocka's mock_assert
+    (compile with `--wrap=exit`) */
+extern void exit(int status);
+extern void __real_exit(int status);
+void __wrap_exit(int status);
+void __wrap_exit(int status) {
+    assert(0);
+}
+
+/* ignore all printfs */
+#undef printf
+extern int printf(const char *format, ...);
+extern int __real_printf(const char *format, ...);
+int __wrap_printf(const char *format, ...);
+int __wrap_printf(const char *format, ...) {
+    return 1;
+}
+
+/* Rand with 0 seed would broke in the past */
+static void test_hash(void **state) {
+
+    char bitmap[64] = {0};
+    u64 hash0 = hash64(bitmap, sizeof(bitmap), 0xa5b35705);
+
+    bitmap[10] = 1;
+    u64 hash1 = hash64(bitmap, sizeof(bitmap), 0xa5b35705);
+
+    assert_int_not_equal(hash0, hash1);
+
+    bitmap[10] = 0;
+    assert_int_equal(hash0, hash64(bitmap, sizeof(bitmap), 0xa5b35705));
+
+    bitmap[10] = 1;
+    assert_int_equal(hash1, hash64(bitmap, sizeof(bitmap), 0xa5b35705));
+
+}
+
+int main(int argc, char **argv) {
+
+    const struct CMUnitTest tests[] = {
+        cmocka_unit_test(test_hash)
+    };
+
+    //return cmocka_run_group_tests (tests, setup, teardown);
+    __real_exit( cmocka_run_group_tests (tests, NULL, NULL) );
+
+    // fake return for dumb compilers
+    return 0;
+}
diff --git a/test/unittests/unit_rand.c b/test/unittests/unit_rand.c
new file mode 100644
index 00000000..0a90d8d1
--- /dev/null
+++ b/test/unittests/unit_rand.c
@@ -0,0 +1,84 @@
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <assert.h>
+#include <cmocka.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+/* cmocka < 1.0 didn't support these features we need */
+#ifndef assert_ptr_equal
+#define assert_ptr_equal(a, b) \
+    _assert_int_equal(cast_ptr_to_largest_integral_type(a), \
+                      cast_ptr_to_largest_integral_type(b), \
+                      __FILE__, __LINE__)
+#define CMUnitTest UnitTest
+#define cmocka_unit_test unit_test
+#define cmocka_run_group_tests(t, setup, teardown) run_tests(t)
+#endif
+
+
+extern void mock_assert(const int result, const char* const expression,
+                        const char * const file, const int line);
+#undef assert
+#define assert(expression) \
+    mock_assert((int)(expression), #expression, __FILE__, __LINE__);
+
+#include "afl-fuzz.h"
+
+/* remap exit -> assert, then use cmocka's mock_assert
+    (compile with `--wrap=exit`) */
+extern void exit(int status);
+extern void __real_exit(int status);
+void __wrap_exit(int status);
+void __wrap_exit(int status) {
+    assert(0);
+}
+
+/* ignore all printfs */
+#undef printf
+extern int printf(const char *format, ...);
+extern int __real_printf(const char *format, ...);
+int __wrap_printf(const char *format, ...);
+int __wrap_printf(const char *format, ...) {
+    return 1;
+}
+
+/* Rand with 0 seed would broke in the past */
+static void test_rand_0(void **state) {
+
+    afl_state_t afl = {0};
+    rand_set_seed(&afl, 0);
+
+    /* give this one chance to retry */
+    assert_int_not_equal(
+        (rand_next(&afl) != rand_next(&afl)
+            || rand_next(&afl) != rand_next(&afl))
+            , 0);
+
+}
+
+static void test_rand_below(void **state) {
+
+    afl_state_t afl = {0};
+    rand_set_seed(&afl, 1337);
+
+    afl.fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY);
+
+    assert(!(rand_below(&afl, 9000) > 9000));
+    assert_int_equal(rand_below(&afl, 1), 0);
+
+}
+
+int main(int argc, char **argv) {
+
+    const struct CMUnitTest tests[] = {
+        cmocka_unit_test(test_rand_0),
+        cmocka_unit_test(test_rand_below)
+    };
+
+    //return cmocka_run_group_tests (tests, setup, teardown);
+    __real_exit( cmocka_run_group_tests (tests, NULL, NULL) );
+
+    // fake return for dumb compilers
+    return 0;
+}