summaryrefslogtreecommitdiff
path: root/archived/projt-launcher/fuzz
diff options
context:
space:
mode:
authorMehmet Samet Duman <yongdohyun@projecttick.org>2026-04-02 18:51:45 +0300
committerMehmet Samet Duman <yongdohyun@projecttick.org>2026-04-02 18:51:45 +0300
commitd3261e64152397db2dca4d691a990c6bc2a6f4dd (patch)
treefac2f7be638651181a72453d714f0f96675c2b8b /archived/projt-launcher/fuzz
parent31b9a8949ed0a288143e23bf739f2eb64fdc63be (diff)
downloadProject-Tick-d3261e64152397db2dca4d691a990c6bc2a6f4dd.tar.gz
Project-Tick-d3261e64152397db2dca4d691a990c6bc2a6f4dd.zip
NOISSUE add archived projects
Signed-off-by: Mehmet Samet Duman <yongdohyun@projecttick.org>
Diffstat (limited to 'archived/projt-launcher/fuzz')
-rw-r--r--archived/projt-launcher/fuzz/CMakeLists.txt39
-rw-r--r--archived/projt-launcher/fuzz/fuzz_gzip.cpp17
-rw-r--r--archived/projt-launcher/fuzz/fuzz_nbt_reader.cpp36
-rw-r--r--archived/projt-launcher/fuzz/fuzz_qjson_parse.cpp17
-rw-r--r--archived/projt-launcher/fuzz/fuzz_separator_prefix_tree.cpp123
5 files changed, 232 insertions, 0 deletions
diff --git a/archived/projt-launcher/fuzz/CMakeLists.txt b/archived/projt-launcher/fuzz/CMakeLists.txt
new file mode 100644
index 0000000000..8828726a7b
--- /dev/null
+++ b/archived/projt-launcher/fuzz/CMakeLists.txt
@@ -0,0 +1,39 @@
+set(FUZZ_ENGINE "")
+if(DEFINED ENV{LIB_FUZZING_ENGINE})
+ set(FUZZ_ENGINE $ENV{LIB_FUZZING_ENGINE})
+endif()
+
+function(add_fuzzer target)
+ add_executable(${target} ${ARGN})
+ target_compile_features(${target} PRIVATE cxx_std_20)
+ if(FUZZ_ENGINE)
+ target_link_libraries(${target} PRIVATE ${FUZZ_ENGINE})
+ else()
+ target_compile_options(${target} PRIVATE -fsanitize=fuzzer)
+ target_link_options(${target} PRIVATE -fsanitize=fuzzer)
+ endif()
+endfunction()
+
+add_fuzzer(fuzz_nbt_reader fuzz_nbt_reader.cpp)
+target_link_libraries(fuzz_nbt_reader PRIVATE nbt++)
+
+# Disabled: Qt6 adds unnecessary glib dependency in fuzzing environment
+# add_fuzzer(fuzz_qjson_parse fuzz_qjson_parse.cpp)
+# target_link_libraries(fuzz_qjson_parse PRIVATE Qt6::Core)
+
+# fuzz_gzip requires Qt6::Core for QByteArray/QFile usage in GZip.cpp
+# Only build if Qt6::Core is available
+if(TARGET Qt6::Core)
+ add_fuzzer(fuzz_gzip fuzz_gzip.cpp ${PROJECT_SOURCE_DIR}/launcher/GZip.cpp)
+ target_include_directories(fuzz_gzip PRIVATE ${PROJECT_SOURCE_DIR}/launcher)
+ # Use static ptlibzippy for fuzzer to avoid sanitizer symbol mismatch
+ if(TARGET ptlibzippystatic)
+ target_link_libraries(fuzz_gzip PRIVATE Qt6::Core ptlibzippystatic)
+ else()
+ target_link_libraries(fuzz_gzip PRIVATE Qt6::Core PTlibzippy::PTlibzippy)
+ endif()
+
+ add_fuzzer(fuzz_separator_prefix_tree fuzz_separator_prefix_tree.cpp)
+ target_include_directories(fuzz_separator_prefix_tree PRIVATE ${PROJECT_SOURCE_DIR}/launcher)
+ target_link_libraries(fuzz_separator_prefix_tree PRIVATE Qt6::Core)
+endif()
diff --git a/archived/projt-launcher/fuzz/fuzz_gzip.cpp b/archived/projt-launcher/fuzz/fuzz_gzip.cpp
new file mode 100644
index 0000000000..8db3c716f4
--- /dev/null
+++ b/archived/projt-launcher/fuzz/fuzz_gzip.cpp
@@ -0,0 +1,17 @@
+#include <cstdint>
+
+#include <QByteArray>
+
+#include "GZip.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
+{
+ QByteArray input(reinterpret_cast<const char*>(data), static_cast<int>(size));
+ QByteArray output;
+ QByteArray roundtrip;
+
+ GZip::unzip(input, output);
+ GZip::zip(output, roundtrip);
+
+ return 0;
+}
diff --git a/archived/projt-launcher/fuzz/fuzz_nbt_reader.cpp b/archived/projt-launcher/fuzz/fuzz_nbt_reader.cpp
new file mode 100644
index 0000000000..d6b1291c6f
--- /dev/null
+++ b/archived/projt-launcher/fuzz/fuzz_nbt_reader.cpp
@@ -0,0 +1,36 @@
+#include <cstdint>
+#include <exception>
+#include <sstream>
+#include <string>
+
+#include "io/stream_reader.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
+{
+ // Avoid excessive allocations on pathological inputs
+ // Very strict limit to prevent array allocation bombs
+ // E.g., NBT array with count 0x92929292 would allocate 3.2GB
+ constexpr size_t kMaxInputSize = 4 * 1024; // 4 KiB (was 64 KiB)
+ if (!data || size == 0 || size > kMaxInputSize)
+ {
+ return 0;
+ }
+
+ try
+ {
+ // Use custom string stream without extra copies
+ std::istringstream stream(std::string(reinterpret_cast<const char*>(data), size), std::ios::binary);
+ nbt::io::read_compound(stream);
+ }
+ catch (const std::exception&)
+ {
+ // Expected for malformed inputs or resource exhaustion
+ }
+ catch (const std::bad_alloc&)
+ {
+ // Handle out-of-memory gracefully
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/archived/projt-launcher/fuzz/fuzz_qjson_parse.cpp b/archived/projt-launcher/fuzz/fuzz_qjson_parse.cpp
new file mode 100644
index 0000000000..ee4db92ed6
--- /dev/null
+++ b/archived/projt-launcher/fuzz/fuzz_qjson_parse.cpp
@@ -0,0 +1,17 @@
+#include <cstdint>
+
+#include <QJsonDocument>
+#include <QJsonParseError>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
+{
+ if (!data || size == 0)
+ {
+ return 0;
+ }
+
+ QJsonParseError error{};
+ QJsonDocument::fromJson(QByteArray(reinterpret_cast<const char*>(data), static_cast<int>(size)), &error);
+
+ return 0;
+}
diff --git a/archived/projt-launcher/fuzz/fuzz_separator_prefix_tree.cpp b/archived/projt-launcher/fuzz/fuzz_separator_prefix_tree.cpp
new file mode 100644
index 0000000000..d50f616050
--- /dev/null
+++ b/archived/projt-launcher/fuzz/fuzz_separator_prefix_tree.cpp
@@ -0,0 +1,123 @@
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+
+#include <QByteArray>
+#include <QString>
+#include <QStringList>
+
+#include "SeparatorPrefixTree.h"
+
+namespace {
+class InputCursor
+{
+ public:
+ InputCursor(const uint8_t* data, size_t size) : m_data(data), m_size(size) {}
+
+ bool has(size_t count) const
+ {
+ return m_pos + count <= m_size;
+ }
+
+ uint8_t nextByte()
+ {
+ if (!has(1))
+ return 0;
+ return m_data[m_pos++];
+ }
+
+ QByteArray takeBytes(size_t count)
+ {
+ if (!has(count))
+ count = m_size - m_pos;
+ QByteArray out(reinterpret_cast<const char*>(m_data + m_pos), static_cast<int>(count));
+ m_pos += count;
+ return out;
+ }
+
+ QString nextPath()
+ {
+ static const char kAlphabet[] = "abcdefghijklmnopqrstuvwxyz0123456789-_.";
+ const int alphabet_len = static_cast<int>(sizeof(kAlphabet) - 1);
+
+ const int segments = 1 + (nextByte() % 4);
+ QStringList parts;
+ parts.reserve(segments);
+
+ for (int i = 0; i < segments; ++i) {
+ const int length = 1 + (nextByte() % 8);
+ QByteArray bytes;
+ bytes.reserve(length);
+ for (int j = 0; j < length; ++j) {
+ bytes.append(kAlphabet[nextByte() % alphabet_len]);
+ }
+ parts.append(QString::fromLatin1(bytes));
+ }
+
+ return parts.join('/');
+ }
+
+ private:
+ const uint8_t* m_data = nullptr;
+ size_t m_size = 0;
+ size_t m_pos = 0;
+};
+} // namespace
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
+{
+ InputCursor cursor(data, size);
+ SeparatorPrefixTree<'/'> tree;
+
+ const size_t max_ops = size < 256 ? size : 256;
+ for (size_t i = 0; i < max_ops && cursor.has(1); ++i) {
+ const uint8_t op = cursor.nextByte() % 8;
+ const QString path = cursor.nextPath();
+
+ switch (op) {
+ case 0:
+ tree.insert(path);
+ break;
+ case 1:
+ tree.remove(path);
+ break;
+ case 2: {
+ const bool contains = tree.contains(path);
+ if (contains && !tree.covers(path)) {
+ abort();
+ }
+ break;
+ }
+ case 3:
+ tree.covers(path);
+ break;
+ case 4: {
+ const bool covers = tree.covers(path);
+ const QString cover = tree.cover(path);
+ if (covers && cover.isNull()) {
+ abort();
+ }
+ break;
+ }
+ case 5:
+ tree.exists(path);
+ break;
+ case 6: {
+ const auto list = tree.toStringList();
+ for (const auto& entry : list) {
+ if (!tree.contains(entry)) {
+ abort();
+ }
+ }
+ break;
+ }
+ case 7:
+ tree.clear();
+ break;
+ default:
+ break;
+ }
+ }
+
+ return 0;
+}