From c8ae8d7d07866cd06009bdb09e88c26f5adef394 Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Wed, 25 Sep 2024 13:33:58 +0200
Subject: [PATCH] Fix Fuzzing setup for Linux

---
 INSTALL.md                          |  2 +-
 test/fuzz/fuzz_compression.c        |  7 +++----
 test/fuzz/fuzz_data_producer.c      |  3 +--
 test/fuzz/fuzz_decompression.c      |  7 +++----
 test/fuzz/fuzz_helpers.c            | 28 ++++++++++++++++++++++++++++
 test/fuzz/fuzz_helpers.h            |  2 ++
 test/fuzz/fuzz_round_trip.c         |  5 ++---
 test/fuzz/meson.build               |  6 +++---
 test/test_common/chunk_round_trip.c | 20 ++++++++++++++++++++
 test/test_common/meson.build        |  3 ++-
 test/test_common/test_common.c      | 19 -------------------
 test/test_common/test_common.h      |  2 --
 12 files changed, 65 insertions(+), 39 deletions(-)
 create mode 100644 test/fuzz/fuzz_helpers.c

diff --git a/INSTALL.md b/INSTALL.md
index fc7e40d..414967d 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -152,7 +152,7 @@ meson setup builddir_fuzzing \
   --buildtype=plain \
   -Dfuzzer=enabled \
   -Dfuzzer_ldflags=-fsanitize=fuzzer \
-  -Dc_args="-O1 -gline-tables-only -fsanitize-address-use-after-scope -fsanitize=fuzzer-no-link" \
+  -Dc_args="-O1 -gline-tables-only -fsanitize=fuzzer-no-link" \
   -Db_sanitize=address,undefined \
   -Ddebug_level=0 \
   -Ddefault_library=static \
diff --git a/test/fuzz/fuzz_compression.c b/test/fuzz/fuzz_compression.c
index c047654..e894ebc 100644
--- a/test/fuzz/fuzz_compression.c
+++ b/test/fuzz/fuzz_compression.c
@@ -26,7 +26,6 @@
 
 #include "fuzz_helpers.h"
 #include "fuzz_data_producer.h"
-#include "../test_common/test_common.h"
 
 #include "../../lib/cmp_chunk.h"
 
@@ -62,7 +61,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
 	if (cmp_is_error(cmp_size_bound))
 		cmp_size_bound = 0;
 	cmp_data_capacity = FUZZ_dataProducer_uint32Range(producer, 0, cmp_size_bound+(uint32_t)size);
-	cmp_data = (uint32_t *)TEST_malloc(cmp_data_capacity);
+	cmp_data = (uint32_t *)FUZZ_malloc(cmp_data_capacity);
 
 	FUZZ_dataProducer_cmp_par(producer, &cmp_par);
 	if (FUZZ_dataProducer_uint32Range(producer, 0, 1))
@@ -74,10 +73,10 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
 		up_model = NULL;
 		break;
 	case 1:
-		up_model = TEST_malloc(size);
+		up_model = FUZZ_malloc(size);
 		break;
 	case 2:
-		up_model = TEST_malloc(size);
+		up_model = FUZZ_malloc(size);
 		if (model && up_model) {
 			memcpy(up_model, model, size);
 			model = up_model; /* in-place update */
diff --git a/test/fuzz/fuzz_data_producer.c b/test/fuzz/fuzz_data_producer.c
index 9f03a94..1ee5994 100644
--- a/test/fuzz/fuzz_data_producer.c
+++ b/test/fuzz/fuzz_data_producer.c
@@ -23,7 +23,6 @@
 
 #include "fuzz_helpers.h"
 #include "fuzz_data_producer.h"
-#include "../test_common/test_common.h"
 #include <cmp_chunk.h>
 
 struct FUZZ_dataProducer_s{
@@ -32,7 +31,7 @@ struct FUZZ_dataProducer_s{
 };
 
 FUZZ_dataProducer_t *FUZZ_dataProducer_create(const uint8_t *data, size_t size) {
-    FUZZ_dataProducer_t *producer = TEST_malloc(sizeof(FUZZ_dataProducer_t));
+    FUZZ_dataProducer_t *producer = FUZZ_malloc(sizeof(FUZZ_dataProducer_t));
 
     producer->data = data;
     producer->size = size;
diff --git a/test/fuzz/fuzz_decompression.c b/test/fuzz/fuzz_decompression.c
index 01ade21..85ec62e 100644
--- a/test/fuzz/fuzz_decompression.c
+++ b/test/fuzz/fuzz_decompression.c
@@ -22,7 +22,6 @@
 
 #include "fuzz_helpers.h"
 #include "fuzz_data_producer.h"
-#include "../test_common/test_common.h"
 
 #include "../../lib/decmp.h"
 
@@ -77,10 +76,10 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
 		up_model_buf = NULL;
 		break;
 	case 1:
-		up_model_buf = TEST_malloc(model_of_data_size);
+		up_model_buf = FUZZ_malloc(model_of_data_size);
 		break;
 	case 2: /* in-place update */
-		up_model_buf = TEST_malloc(model_of_data_size);
+		up_model_buf = FUZZ_malloc(model_of_data_size);
 		if (model_of_data && up_model_buf) {
 			memcpy(up_model_buf, model_of_data, model_of_data_size);
 			model_of_data = up_model_buf;
@@ -90,7 +89,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
 		FUZZ_ASSERT(0);
 	}
 
-	decompressed_data = TEST_malloc((size_t)model_of_data_size);
+	decompressed_data = FUZZ_malloc((size_t)model_of_data_size);
 	decompress_cmp_entiy_save(ent, ent_size, model_of_data, up_model_buf, decompressed_data, model_of_data_size);
 
 	free(up_model_buf);
diff --git a/test/fuzz/fuzz_helpers.c b/test/fuzz/fuzz_helpers.c
new file mode 100644
index 0000000..fab2f0b
--- /dev/null
+++ b/test/fuzz/fuzz_helpers.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE.BSD-3.Zstandard file in the 3rdparty_licenses directory) and the GPLv2
+ * (found in the LICENSE.GPL-2 file in the 3rdparty_licenses directory).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+/**
+ * Helper functions for fuzzing.
+ */
+
+#include <stdlib.h>
+
+#include "fuzz_helpers.h"
+
+
+void* FUZZ_malloc(size_t size)
+{
+    if (size > 0) {
+        void* const mem = malloc(size);
+        FUZZ_ASSERT(mem);
+        return mem;
+    }
+    return NULL;
+}
diff --git a/test/fuzz/fuzz_helpers.h b/test/fuzz/fuzz_helpers.h
index 0f95b74..bdaa672 100644
--- a/test/fuzz/fuzz_helpers.h
+++ b/test/fuzz/fuzz_helpers.h
@@ -35,6 +35,8 @@ extern "C" {
              abort()))
 #define FUZZ_ASSERT(cond) FUZZ_ASSERT_MSG((cond), "");
 
+void* FUZZ_malloc(size_t size);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/test/fuzz/fuzz_round_trip.c b/test/fuzz/fuzz_round_trip.c
index c8a1ff1..88079bb 100644
--- a/test/fuzz/fuzz_round_trip.c
+++ b/test/fuzz/fuzz_round_trip.c
@@ -27,7 +27,6 @@
 #include "fuzz_helpers.h"
 #include "fuzz_data_producer.h"
 #include "../test_common/chunk_round_trip.h"
-#include "../test_common/test_common.h"
 
 
 int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
@@ -62,7 +61,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
 
 	/* 1/2 of the cases we use a updated model buffer */
 	if (FUZZ_dataProducer_uint32Range(producer, 0, 1)) {
-		up_model = TEST_malloc(size);
+		up_model = FUZZ_malloc(size);
 		if (!model_mode_is_used(cmp_par.cmp_mode))
 			memset(up_model, 0, size); /* up_model is not used */
 	}
@@ -71,7 +70,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
 	if (cmp_is_error(cmp_size_bound))
 		cmp_size_bound = 0;
 	cmp_data_capacity = FUZZ_dataProducer_uint32Range(producer, 0, cmp_size_bound+(uint32_t)size);
-	cmp_data = (uint32_t *)TEST_malloc(cmp_data_capacity);
+	cmp_data = (uint32_t *)FUZZ_malloc(cmp_data_capacity);
 
 	use_decmp_buf = FUZZ_dataProducer_int32Range(producer, 0, 1);
 	use_decmp_up_model = FUZZ_dataProducer_int32Range(producer, 0, 1);
diff --git a/test/fuzz/meson.build b/test/fuzz/meson.build
index 89d67ad..c9a73c9 100644
--- a/test/fuzz/meson.build
+++ b/test/fuzz/meson.build
@@ -2,7 +2,7 @@ if get_option('fuzzer').disabled()
   subdir_done()
 endif
 
-fuzz_common = files('fuzz_data_producer.c')
+fuzz_common = files('fuzz_data_producer.c', 'fuzz_helpers.c')
 fuzz_targets = ['fuzz_compression.c', 'fuzz_round_trip.c', 'fuzz_decompression.c']
 
 add_languages('cpp', native: false) # libFuzzingEngine needs c++
@@ -12,9 +12,9 @@ foreach target : fuzz_targets
   target_name = file_name.split('.').get(0)
 
   fuzz_exe = executable(target_name,
-    fuzz_common, file_name,
+    fuzz_common, chunk_round_trip, file_name,
     include_directories : incdir,
-    link_with : [cmp_lib, test_common_lib],
+    link_with : [cmp_lib],
     link_args : get_option('fuzzer_ldflags'),
     link_language : 'cpp' # libFuzzingEngine needs c++
   )
diff --git a/test/test_common/chunk_round_trip.c b/test/test_common/chunk_round_trip.c
index d0324d2..fa538f9 100644
--- a/test/test_common/chunk_round_trip.c
+++ b/test/test_common/chunk_round_trip.c
@@ -32,6 +32,26 @@
 #endif
 
 
+
+/**
+ * @brief allocates memory safely for tests
+ *
+ * @param size the size of memory to allocate
+ *
+ * @returns a pointer to the allocated memory, or NULL if allocation fails
+ */
+
+static void* TEST_malloc(size_t size)
+{
+    if (size > 0) {
+        void* const mem = malloc(size);
+        TEST_ASSERT(mem);
+        return mem;
+    }
+    return NULL;
+}
+
+
 /**
  * @brief performs chunk compression and checks if a decompression is possible
  *
diff --git a/test/test_common/meson.build b/test/test_common/meson.build
index ab030dc..ecc5614 100644
--- a/test/test_common/meson.build
+++ b/test/test_common/meson.build
@@ -1,9 +1,10 @@
 pcg_proj = subproject('pcg-c-basic')
 pcb_dep = pcg_proj.get_variable('libpcg_basic_dep')
 
+chunk_round_trip = files('chunk_round_trip.c')
 test_common_lib = static_library(
    'test_common',
    'test_common.c',
-   'chunk_round_trip.c',
+   chunk_round_trip,
    dependencies: [pcb_dep, unity_dep]
 )
diff --git a/test/test_common/test_common.c b/test/test_common/test_common.c
index 0cdd826..1a3e79d 100644
--- a/test/test_common/test_common.c
+++ b/test/test_common/test_common.c
@@ -50,22 +50,3 @@ uint32_t cmp_rand_nbits(unsigned int n_bits)
 
 	return cmp_rand32() >> (32 - n_bits);
 }
-
-
-/**
- * @brief allocates memory safely for tests
- *
- * @param size The size of memory to allocate.
- *
- * @returns a pointer to the allocated memory, or NULL if allocation fails
- */
-
-void* TEST_malloc(size_t size)
-{
-    if (size > 0) {
-        void* const mem = malloc(size);
-        TEST_ASSERT(mem);
-        return mem;
-    }
-    return NULL;
-}
diff --git a/test/test_common/test_common.h b/test/test_common/test_common.h
index a5e72f9..870b083 100644
--- a/test/test_common/test_common.h
+++ b/test/test_common/test_common.h
@@ -12,6 +12,4 @@ uint32_t cmp_rand_between(uint32_t min, uint32_t max);
 
 uint32_t cmp_rand_nbits(unsigned int n_bits);
 
-void* TEST_malloc(size_t size);
-
 #endif /* TEST_COMMON_H */
-- 
GitLab