This is an automated email from the ASF dual-hosted git repository.

pnoltes pushed a commit to branch feature/add-fuzzing
in repository https://gitbox.apache.org/repos/asf/celix.git

commit 69ce5e1d39f9d8b7f564b9ff6dd6764d674633d6
Author: Pepijn Noltes <[email protected]>
AuthorDate: Thu Aug 14 15:38:22 2025 +0200

    Add fuzzing code
    
    Also improves benchmark setup
---
 libs/framework/benchmark/CMakeLists.txt            |  9 +---
 libs/utils/CMakeLists.txt                          | 19 +++++++++
 libs/utils/benchmark/CMakeLists.txt                |  9 +---
 libs/utils/benchmark/src/StringHashmapBenchmark.cc |  2 +-
 libs/utils/fuzzing/CMakeLists.txt                  | 49 ++++++++++++++++++++++
 libs/utils/fuzzing/filter_corpus/complex.txt       |  1 +
 libs/utils/fuzzing/filter_corpus/simple.txt        |  1 +
 libs/utils/fuzzing/properties_corpus/complex.json  |  2 +
 libs/utils/fuzzing/properties_corpus/simple.json   |  1 +
 libs/utils/fuzzing/src/FilterFuzz.cc               | 23 ++++++++++
 libs/utils/fuzzing/src/PropertiesFuzz.cc           | 32 ++++++++++++++
 libs/utils/fuzzing/src/VersionFuzz.cc              | 23 ++++++++++
 libs/utils/fuzzing/version_corpus/qualifier.txt    |  1 +
 libs/utils/fuzzing/version_corpus/simple.txt       |  1 +
 14 files changed, 156 insertions(+), 17 deletions(-)

diff --git a/libs/framework/benchmark/CMakeLists.txt 
b/libs/framework/benchmark/CMakeLists.txt
index ba39fcbb4..875d2f7f3 100644
--- a/libs/framework/benchmark/CMakeLists.txt
+++ b/libs/framework/benchmark/CMakeLists.txt
@@ -15,14 +15,7 @@
 # specific language governing permissions and limitations
 # under the License.
 
-set(FRAMEWORK_BENCHMARK_DEFAULT "OFF")
-find_package(benchmark QUIET)
-if (benchmark_FOUND)
-    set(FRAMEWORK_BENCHMARK_DEFAULT "ON")
-endif ()
-
-celix_subproject(FRAMEWORK_BENCHMARK "Option to enable Celix framework 
benchmark" ${FRAMEWORK_BENCHMARK_DEFAULT})
-if (FRAMEWORK_BENCHMARK AND CELIX_CXX17)
+if (ENABLE_BENCHMARKING AND CELIX_CXX17)
     set(CMAKE_CXX_STANDARD 17)
     find_package(benchmark REQUIRED)
 
diff --git a/libs/utils/CMakeLists.txt b/libs/utils/CMakeLists.txt
index 4b8c08a35..cb29f8f60 100644
--- a/libs/utils/CMakeLists.txt
+++ b/libs/utils/CMakeLists.txt
@@ -126,5 +126,24 @@ if (UTILS)
         add_subdirectory(gtest)
     endif ()
 
+
+    if (ENABLE_FUZZING)
+        add_library(utils_cuf STATIC ${UTILS_SRC})
+        target_compile_definitions(utils_cuf PRIVATE CELIX_UTILS_STATIC_DEFINE)
+        target_include_directories(utils_cuf PUBLIC
+                        ${CMAKE_CURRENT_LIST_DIR}/include
+                        ${CMAKE_CURRENT_LIST_DIR}/include_internal
+                        ${CMAKE_BINARY_DIR}/celix/gen/includes/utils
+                        ${CMAKE_BINARY_DIR}/celix/gen/src/utils
+                        include_deprecated
+                        )
+        target_link_libraries(utils_cuf PUBLIC ${UTILS_PUBLIC_DEPS} 
${UTILS_PRIVATE_DEPS})
+        target_compile_options(utils_cuf PRIVATE 
-fsanitize=fuzzer-no-link,address) 
+        target_link_options(utils_cuf PRIVATE 
-fsanitize=fuzzer-no-link,address)
+        target_link_options(utils_cuf PRIVATE -Wl,--gc-sections)
+
+        add_subdirectory(fuzzing)
+    endif ()
+
     add_subdirectory(benchmark)
 endif ()
diff --git a/libs/utils/benchmark/CMakeLists.txt 
b/libs/utils/benchmark/CMakeLists.txt
index 2f891e6cb..4c22fc2df 100644
--- a/libs/utils/benchmark/CMakeLists.txt
+++ b/libs/utils/benchmark/CMakeLists.txt
@@ -15,14 +15,7 @@
 # specific language governing permissions and limitations
 # under the License.
 
-set(UTILS_BENCHMARK_DEFAULT "OFF")
-find_package(benchmark QUIET)
-if (benchmark_FOUND)
-    set(UTILS_BENCHMARK_DEFAULT "ON")
-endif ()
-
-celix_subproject(UTILS_BENCHMARK "Option to enable Celix framework benchmark" 
${UTILS_BENCHMARK_DEFAULT})
-if (UTILS_BENCHMARK)
+if (ENABLE_BENCHMARKING)
     find_package(benchmark REQUIRED)
 
     add_executable(celix_string_hashmap_benchmark
diff --git a/libs/utils/benchmark/src/StringHashmapBenchmark.cc 
b/libs/utils/benchmark/src/StringHashmapBenchmark.cc
index 4552dd044..7ecfb81e0 100644
--- a/libs/utils/benchmark/src/StringHashmapBenchmark.cc
+++ b/libs/utils/benchmark/src/StringHashmapBenchmark.cc
@@ -100,7 +100,7 @@ public:
         return valDistribution(generator);
     }
 
-    const int MAX_LEN = 100;
+    static constexpr int MAX_LEN = 100;
     std::default_random_engine generator{};
     std::uniform_int_distribution<int> lenDistribution{1,MAX_LEN};
     std::uniform_int_distribution<int> charDistribution{'a','z'};
diff --git a/libs/utils/fuzzing/CMakeLists.txt 
b/libs/utils/fuzzing/CMakeLists.txt
new file mode 100644
index 000000000..90b9eefaf
--- /dev/null
+++ b/libs/utils/fuzzing/CMakeLists.txt
@@ -0,0 +1,49 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+add_executable(celix_properties_fuzzer src/PropertiesFuzz.cc)
+target_link_libraries(celix_properties_fuzzer PRIVATE utils_cuf)
+target_compile_options(celix_properties_fuzzer PRIVATE 
-fsanitize=fuzzer,address)
+target_link_options(celix_properties_fuzzer PRIVATE -fsanitize=fuzzer,address)
+
+add_executable(celix_version_fuzzer src/VersionFuzz.cc)
+target_link_libraries(celix_version_fuzzer PRIVATE utils_cuf)
+target_compile_options(celix_version_fuzzer PRIVATE -fsanitize=fuzzer,address)
+target_link_options(celix_version_fuzzer PRIVATE -fsanitize=fuzzer,address)
+
+add_executable(celix_filter_fuzzer src/FilterFuzz.cc)
+target_link_libraries(celix_filter_fuzzer PRIVATE utils_cuf)
+target_compile_options(celix_filter_fuzzer PRIVATE -fsanitize=fuzzer,address)
+target_link_options(celix_filter_fuzzer PRIVATE -fsanitize=fuzzer,address)
+
+add_custom_command(TARGET celix_properties_fuzzer POST_BUILD
+    COMMAND ${CMAKE_COMMAND} -E copy_directory
+    ${CMAKE_CURRENT_SOURCE_DIR}/properties_corpus
+    $<TARGET_FILE_DIR:celix_properties_fuzzer>/properties_corpus
+)
+
+add_custom_command(TARGET celix_version_fuzzer POST_BUILD
+    COMMAND ${CMAKE_COMMAND} -E copy_directory
+    ${CMAKE_CURRENT_SOURCE_DIR}/version_corpus
+    $<TARGET_FILE_DIR:celix_version_fuzzer>/version_corpus
+)
+
+add_custom_command(TARGET celix_filter_fuzzer POST_BUILD
+    COMMAND ${CMAKE_COMMAND} -E copy_directory
+    ${CMAKE_CURRENT_SOURCE_DIR}/filter_corpus
+    $<TARGET_FILE_DIR:celix_filter_fuzzer>/filter_corpus
+)
+
diff --git a/libs/utils/fuzzing/filter_corpus/complex.txt 
b/libs/utils/fuzzing/filter_corpus/complex.txt
new file mode 100644
index 000000000..1ffe40511
--- /dev/null
+++ b/libs/utils/fuzzing/filter_corpus/complex.txt
@@ -0,0 +1 @@
+(&(test_attr1=attr1)(|(test_attr2=attr2)(test_attr3=attr3)))
diff --git a/libs/utils/fuzzing/filter_corpus/simple.txt 
b/libs/utils/fuzzing/filter_corpus/simple.txt
new file mode 100644
index 000000000..bfa80ac8d
--- /dev/null
+++ b/libs/utils/fuzzing/filter_corpus/simple.txt
@@ -0,0 +1 @@
+(key=value)
diff --git a/libs/utils/fuzzing/properties_corpus/complex.json 
b/libs/utils/fuzzing/properties_corpus/complex.json
new file mode 100644
index 000000000..070856559
--- /dev/null
+++ b/libs/utils/fuzzing/properties_corpus/complex.json
@@ -0,0 +1,2 @@
+{"key1":"value1","key2":"value2","object1":{"key3":"value3","key4":"value4"},"object2":{"key5":"value5"},"object3":{"object4":{"key6":"value6"}},"strArr":["value1","value2"],"intArr":[1,2],"realArr":[1.0,2.0],"boolArr":[true,false],"versionArr":["version<1.2.3.qualifier>","version<4.5.6.qualifier>"]}
+
diff --git a/libs/utils/fuzzing/properties_corpus/simple.json 
b/libs/utils/fuzzing/properties_corpus/simple.json
new file mode 100644
index 000000000..29f05f6bf
--- /dev/null
+++ b/libs/utils/fuzzing/properties_corpus/simple.json
@@ -0,0 +1 @@
+{"key":"value"}
diff --git a/libs/utils/fuzzing/src/FilterFuzz.cc 
b/libs/utils/fuzzing/src/FilterFuzz.cc
new file mode 100644
index 000000000..ddc5021c0
--- /dev/null
+++ b/libs/utils/fuzzing/src/FilterFuzz.cc
@@ -0,0 +1,23 @@
+#include <celix_filter.h>
+#include <celix_err.h>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+
+int filterParseFuzzOneInput(const uint8_t* data, size_t size) {
+    char* buffer = static_cast<char*>(malloc(size + 1));
+    if (buffer == nullptr) {
+        return 0;
+    }
+    memcpy(buffer, data, size);
+    buffer[size] = '\0';
+
+    celix_filter_t* filter = celix_filter_create(buffer);
+    celix_filter_destroy(filter);
+    celix_err_resetErrors();
+
+    free(buffer);
+    return 0;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { 
return filterParseFuzzOneInput(data, size); }
diff --git a/libs/utils/fuzzing/src/PropertiesFuzz.cc 
b/libs/utils/fuzzing/src/PropertiesFuzz.cc
new file mode 100644
index 000000000..627c2dd56
--- /dev/null
+++ b/libs/utils/fuzzing/src/PropertiesFuzz.cc
@@ -0,0 +1,32 @@
+#include <celix_properties.h>
+#include <celix_err.h>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+
+int propertiesParserFuzzOneInput(const uint8_t* data, size_t size) {
+    int flags = 0;
+    if (size > 0) {
+        flags = data[0] & 0x3F; // use 6 bits for decode flags
+        data += 1;
+        size -= 1;
+    }
+    char* buffer = static_cast<char*>(malloc(size + 1));
+    if (buffer == nullptr) {
+        return 0;
+    }
+    memcpy(buffer, data, size);
+    buffer[size] = '\0';
+
+    celix_properties_t* props = nullptr;
+    celix_properties_loadFromString(buffer, flags, &props);
+    celix_properties_destroy(props);
+    celix_err_resetErrors();
+
+    free(buffer);
+    return 0;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    return propertiesParserFuzzOneInput(data, size);
+}
diff --git a/libs/utils/fuzzing/src/VersionFuzz.cc 
b/libs/utils/fuzzing/src/VersionFuzz.cc
new file mode 100644
index 000000000..b1fc7e67f
--- /dev/null
+++ b/libs/utils/fuzzing/src/VersionFuzz.cc
@@ -0,0 +1,23 @@
+#include <celix_version.h>
+#include <celix_err.h>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+
+int versionParseFuzzOneInput(const uint8_t* data, size_t size) {
+    char* buffer = static_cast<char*>(malloc(size + 1));
+    if (buffer == nullptr) {
+        return 0;
+    }
+    memcpy(buffer, data, size);
+    buffer[size] = '\0';
+
+    celix_version_t* version = celix_version_createVersionFromString(buffer);
+    celix_version_destroy(version);
+    celix_err_resetErrors();
+
+    free(buffer);
+    return 0;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { 
return versionParseFuzzOneInput(data, size); }
diff --git a/libs/utils/fuzzing/version_corpus/qualifier.txt 
b/libs/utils/fuzzing/version_corpus/qualifier.txt
new file mode 100644
index 000000000..da3ad8b4e
--- /dev/null
+++ b/libs/utils/fuzzing/version_corpus/qualifier.txt
@@ -0,0 +1 @@
+2.0.0.qualifier
diff --git a/libs/utils/fuzzing/version_corpus/simple.txt 
b/libs/utils/fuzzing/version_corpus/simple.txt
new file mode 100644
index 000000000..0495c4a88
--- /dev/null
+++ b/libs/utils/fuzzing/version_corpus/simple.txt
@@ -0,0 +1 @@
+1.2.3

Reply via email to