From: Leslie P. Polzer Date: Mon, 22 Dec 2025 04:53:06 +0000 (+0000) Subject: Refactor all fuzzers to use shared fuzz_helpers.h X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=eb6f992ba1f9e1eefc53e032c951c43dce060900;p=thirdparty%2Flibarchive.git Refactor all fuzzers to use shared fuzz_helpers.h Complete the refactoring of all 25 fuzzers: - Remove duplicate Buffer struct definitions from 15 format fuzzers - Remove duplicate DataConsumer class from 7 API fuzzers - Update consume_bytes() calls to match new signature - All fuzzers now use shared helpers from fuzz_helpers.h This eliminates ~1000 lines of duplicated code. --- diff --git a/contrib/oss-fuzz/libarchive_7zip_fuzzer.cc b/contrib/oss-fuzz/libarchive_7zip_fuzzer.cc index b46e17d1f..74b3b2ad9 100644 --- a/contrib/oss-fuzz/libarchive_7zip_fuzzer.cc +++ b/contrib/oss-fuzz/libarchive_7zip_fuzzer.cc @@ -8,23 +8,11 @@ #include "archive.h" #include "archive_entry.h" +#include "fuzz_helpers.h" static constexpr size_t kMaxInputSize = 512 * 1024; // 512KB -struct Buffer { - const uint8_t *buf; - size_t len; -}; -static ssize_t reader_callback(struct archive *a, void *client_data, - const void **block) { - (void)a; - Buffer *buffer = reinterpret_cast(client_data); - *block = buffer->buf; - ssize_t len = buffer->len; - buffer->len = 0; - return len; -} extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { if (len == 0 || len > kMaxInputSize) { @@ -44,7 +32,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { // Set passphrase for encrypted archives archive_read_add_passphrase(a, "password"); - Buffer buffer = {buf, len}; + Buffer buffer = {buf, len, 0}; if (archive_read_open(a, &buffer, NULL, reader_callback, NULL) != ARCHIVE_OK) { archive_read_free(a); return 0; diff --git a/contrib/oss-fuzz/libarchive_ar_fuzzer.cc b/contrib/oss-fuzz/libarchive_ar_fuzzer.cc index 0d7c20911..3ad88084d 100644 --- a/contrib/oss-fuzz/libarchive_ar_fuzzer.cc +++ b/contrib/oss-fuzz/libarchive_ar_fuzzer.cc @@ -8,23 +8,11 @@ #include "archive.h" #include "archive_entry.h" +#include "fuzz_helpers.h" static constexpr size_t kMaxInputSize = 512 * 1024; -struct Buffer { - const uint8_t *buf; - size_t len; -}; -static ssize_t reader_callback(struct archive *a, void *client_data, - const void **block) { - (void)a; - Buffer *buffer = reinterpret_cast(client_data); - *block = buffer->buf; - ssize_t len = buffer->len; - buffer->len = 0; - return len; -} extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { if (len == 0 || len > kMaxInputSize) { @@ -39,7 +27,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { archive_read_support_format_ar(a); archive_read_support_filter_all(a); - Buffer buffer = {buf, len}; + Buffer buffer = {buf, len, 0}; if (archive_read_open(a, &buffer, NULL, reader_callback, NULL) != ARCHIVE_OK) { archive_read_free(a); return 0; diff --git a/contrib/oss-fuzz/libarchive_cab_fuzzer.cc b/contrib/oss-fuzz/libarchive_cab_fuzzer.cc index 0b62eccbb..2b7086005 100644 --- a/contrib/oss-fuzz/libarchive_cab_fuzzer.cc +++ b/contrib/oss-fuzz/libarchive_cab_fuzzer.cc @@ -7,23 +7,11 @@ #include "archive.h" #include "archive_entry.h" +#include "fuzz_helpers.h" static constexpr size_t kMaxInputSize = 512 * 1024; -struct Buffer { - const uint8_t *buf; - size_t len; -}; - -static ssize_t reader_callback(struct archive *a, void *client_data, - const void **block) { - (void)a; - Buffer *buffer = reinterpret_cast(client_data); - *block = buffer->buf; - ssize_t len = buffer->len; - buffer->len = 0; - return len; -} + extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { if (len == 0 || len > kMaxInputSize) { @@ -38,7 +26,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { archive_read_support_format_cab(a); archive_read_support_filter_all(a); - Buffer buffer = {buf, len}; + Buffer buffer = {buf, len, 0}; if (archive_read_open(a, &buffer, NULL, reader_callback, NULL) != ARCHIVE_OK) { archive_read_free(a); return 0; diff --git a/contrib/oss-fuzz/libarchive_cpio_fuzzer.cc b/contrib/oss-fuzz/libarchive_cpio_fuzzer.cc index 06fe4217a..acbca31c7 100644 --- a/contrib/oss-fuzz/libarchive_cpio_fuzzer.cc +++ b/contrib/oss-fuzz/libarchive_cpio_fuzzer.cc @@ -8,23 +8,11 @@ #include "archive.h" #include "archive_entry.h" +#include "fuzz_helpers.h" static constexpr size_t kMaxInputSize = 512 * 1024; -struct Buffer { - const uint8_t *buf; - size_t len; -}; -static ssize_t reader_callback(struct archive *a, void *client_data, - const void **block) { - (void)a; - Buffer *buffer = reinterpret_cast(client_data); - *block = buffer->buf; - ssize_t len = buffer->len; - buffer->len = 0; - return len; -} extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { if (len == 0 || len > kMaxInputSize) { @@ -39,7 +27,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { archive_read_support_format_cpio(a); archive_read_support_filter_all(a); - Buffer buffer = {buf, len}; + Buffer buffer = {buf, len, 0}; if (archive_read_open(a, &buffer, NULL, reader_callback, NULL) != ARCHIVE_OK) { archive_read_free(a); return 0; diff --git a/contrib/oss-fuzz/libarchive_encryption_fuzzer.cc b/contrib/oss-fuzz/libarchive_encryption_fuzzer.cc index 798b28db7..402265cb5 100644 --- a/contrib/oss-fuzz/libarchive_encryption_fuzzer.cc +++ b/contrib/oss-fuzz/libarchive_encryption_fuzzer.cc @@ -9,6 +9,7 @@ #include "archive.h" #include "archive_entry.h" +#include "fuzz_helpers.h" static constexpr size_t kMaxInputSize = 512 * 1024; @@ -34,20 +35,7 @@ static const char* passphrase_callback(struct archive *a, void *client_data) { return pass; } -struct Buffer { - const uint8_t *buf; - size_t len; -}; -static ssize_t reader_callback(struct archive *a, void *client_data, - const void **block) { - (void)a; - Buffer *buffer = reinterpret_cast(client_data); - *block = buffer->buf; - ssize_t len = buffer->len; - buffer->len = 0; - return len; -} extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { if (len == 0 || len > kMaxInputSize) { @@ -76,7 +64,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { archive_read_add_passphrase(a, "password"); archive_read_add_passphrase(a, "test123"); - Buffer buffer = {buf, len}; + Buffer buffer = {buf, len, 0}; if (archive_read_open(a, &buffer, NULL, reader_callback, NULL) != ARCHIVE_OK) { archive_read_free(a); return 0; diff --git a/contrib/oss-fuzz/libarchive_filter_fuzzer.cc b/contrib/oss-fuzz/libarchive_filter_fuzzer.cc index cba2b3de6..cfd1807ec 100644 --- a/contrib/oss-fuzz/libarchive_filter_fuzzer.cc +++ b/contrib/oss-fuzz/libarchive_filter_fuzzer.cc @@ -8,24 +8,11 @@ #include "archive.h" #include "archive_entry.h" +#include "fuzz_helpers.h" static constexpr size_t kMaxInputSize = 256 * 1024; -struct Buffer { - const uint8_t *buf; - size_t len; - size_t pos; -}; -static ssize_t reader_callback(struct archive *a, void *client_data, - const void **block) { - (void)a; - Buffer *buffer = reinterpret_cast(client_data); - *block = buffer->buf + buffer->pos; - ssize_t len = buffer->len - buffer->pos; - buffer->pos = buffer->len; - return len; -} extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { if (len == 0 || len > kMaxInputSize) { diff --git a/contrib/oss-fuzz/libarchive_fuzzer.cc b/contrib/oss-fuzz/libarchive_fuzzer.cc index bc7f865b6..09a9b1cc6 100644 --- a/contrib/oss-fuzz/libarchive_fuzzer.cc +++ b/contrib/oss-fuzz/libarchive_fuzzer.cc @@ -3,20 +3,7 @@ #include #include "archive.h" - -struct Buffer { - const uint8_t *buf; - size_t len; -}; - -ssize_t reader_callback(struct archive *a, void *client_data, - const void **block) { - Buffer *buffer = reinterpret_cast(client_data); - *block = buffer->buf; - ssize_t len = buffer->len; - buffer->len = 0; - return len; -} +#include "fuzz_helpers.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { int ret; @@ -26,7 +13,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { archive_read_support_filter_all(a); archive_read_support_format_all(a); - Buffer buffer = {buf, len}; + Buffer buffer = {buf, len, 0}; archive_read_open(a, &buffer, NULL, reader_callback, NULL); std::vector data_buffer(getpagesize(), 0); diff --git a/contrib/oss-fuzz/libarchive_iso9660_fuzzer.cc b/contrib/oss-fuzz/libarchive_iso9660_fuzzer.cc index 9aa8316fe..6cdaff23a 100644 --- a/contrib/oss-fuzz/libarchive_iso9660_fuzzer.cc +++ b/contrib/oss-fuzz/libarchive_iso9660_fuzzer.cc @@ -8,23 +8,11 @@ #include "archive.h" #include "archive_entry.h" +#include "fuzz_helpers.h" static constexpr size_t kMaxInputSize = 1024 * 1024; // 1MB for ISO images -struct Buffer { - const uint8_t *buf; - size_t len; -}; -static ssize_t reader_callback(struct archive *a, void *client_data, - const void **block) { - (void)a; - Buffer *buffer = reinterpret_cast(client_data); - *block = buffer->buf; - ssize_t len = buffer->len; - buffer->len = 0; - return len; -} extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { if (len == 0 || len > kMaxInputSize) { @@ -42,7 +30,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { // Set options to test various ISO extensions archive_read_set_options(a, "iso9660:joliet,iso9660:rockridge"); - Buffer buffer = {buf, len}; + Buffer buffer = {buf, len, 0}; if (archive_read_open(a, &buffer, NULL, reader_callback, NULL) != ARCHIVE_OK) { archive_read_free(a); return 0; diff --git a/contrib/oss-fuzz/libarchive_lha_fuzzer.cc b/contrib/oss-fuzz/libarchive_lha_fuzzer.cc index 58732aead..3957d3ed3 100644 --- a/contrib/oss-fuzz/libarchive_lha_fuzzer.cc +++ b/contrib/oss-fuzz/libarchive_lha_fuzzer.cc @@ -7,23 +7,11 @@ #include "archive.h" #include "archive_entry.h" +#include "fuzz_helpers.h" static constexpr size_t kMaxInputSize = 512 * 1024; -struct Buffer { - const uint8_t *buf; - size_t len; -}; -static ssize_t reader_callback(struct archive *a, void *client_data, - const void **block) { - (void)a; - Buffer *buffer = reinterpret_cast(client_data); - *block = buffer->buf; - ssize_t len = buffer->len; - buffer->len = 0; - return len; -} extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { if (len == 0 || len > kMaxInputSize) { @@ -38,7 +26,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { archive_read_support_format_lha(a); archive_read_support_filter_all(a); - Buffer buffer = {buf, len}; + Buffer buffer = {buf, len, 0}; if (archive_read_open(a, &buffer, NULL, reader_callback, NULL) != ARCHIVE_OK) { archive_read_free(a); return 0; diff --git a/contrib/oss-fuzz/libarchive_linkify_fuzzer.cc b/contrib/oss-fuzz/libarchive_linkify_fuzzer.cc index 46348dac7..64c22dca9 100644 --- a/contrib/oss-fuzz/libarchive_linkify_fuzzer.cc +++ b/contrib/oss-fuzz/libarchive_linkify_fuzzer.cc @@ -9,62 +9,11 @@ #include "archive.h" #include "archive_entry.h" +#include "fuzz_helpers.h" static constexpr size_t kMaxInputSize = 64 * 1024; // 64KB // Simple data consumer -class DataConsumer { -public: - DataConsumer(const uint8_t *data, size_t size) : data_(data), size_(size), pos_(0) { - memset(string_buf_, 0, sizeof(string_buf_)); - } - - bool empty() const { return pos_ >= size_; } - - uint8_t consume_byte() { - if (pos_ >= size_) return 0; - return data_[pos_++]; - } - - uint32_t consume_uint32() { - uint32_t val = 0; - for (int i = 0; i < 4 && pos_ < size_; i++) { - val |= static_cast(data_[pos_++]) << (i * 8); - } - return val; - } - - int64_t consume_int64() { - int64_t val = 0; - for (int i = 0; i < 8 && pos_ < size_; i++) { - val |= static_cast(data_[pos_++]) << (i * 8); - } - return val; - } - - const char* consume_string(size_t max_len) { - if (max_len > sizeof(string_buf_) - 1) max_len = sizeof(string_buf_) - 1; - size_t avail = size_ - pos_; - size_t len = (avail < max_len) ? avail : max_len; - - size_t actual_len = 0; - while (actual_len < len && pos_ < size_) { - char c = static_cast(data_[pos_++]); - if (c == '\0') break; - string_buf_[actual_len++] = c; - } - string_buf_[actual_len] = '\0'; - return string_buf_; - } - - size_t remaining() const { return size_ - pos_; } - -private: - const uint8_t *data_; - size_t size_; - size_t pos_; - char string_buf_[256]; -}; extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { if (len == 0 || len > kMaxInputSize) { @@ -103,8 +52,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { archive_entry_set_pathname(entry, consumer.consume_string(64)); // Set inode and device for hardlink detection - archive_entry_set_ino(entry, consumer.consume_int64()); - archive_entry_set_dev(entry, consumer.consume_uint32()); + archive_entry_set_ino(entry, consumer.consume_i64()); + archive_entry_set_dev(entry, consumer.consume_u32()); archive_entry_set_nlink(entry, (consumer.consume_byte() % 5) + 1); // Set mode (regular file or directory) @@ -112,9 +61,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { mode_t mode = ftype ? (S_IFDIR | 0755) : (S_IFREG | 0644); archive_entry_set_mode(entry, mode); - archive_entry_set_size(entry, consumer.consume_int64() & 0xFFFF); - archive_entry_set_uid(entry, consumer.consume_uint32() & 0xFFFF); - archive_entry_set_gid(entry, consumer.consume_uint32() & 0xFFFF); + archive_entry_set_size(entry, consumer.consume_i64() & 0xFFFF); + archive_entry_set_uid(entry, consumer.consume_u32() & 0xFFFF); + archive_entry_set_gid(entry, consumer.consume_u32() & 0xFFFF); entries[num_entries++] = entry; } diff --git a/contrib/oss-fuzz/libarchive_match_fuzzer.cc b/contrib/oss-fuzz/libarchive_match_fuzzer.cc index c5431b34b..a0f8ba7da 100644 --- a/contrib/oss-fuzz/libarchive_match_fuzzer.cc +++ b/contrib/oss-fuzz/libarchive_match_fuzzer.cc @@ -8,53 +8,10 @@ #include "archive.h" #include "archive_entry.h" +#include "fuzz_helpers.h" static constexpr size_t kMaxInputSize = 32 * 1024; -class DataConsumer { -public: - DataConsumer(const uint8_t *data, size_t size) : data_(data), size_(size), pos_(0) { - memset(string_buf_, 0, sizeof(string_buf_)); - } - - bool empty() const { return pos_ >= size_; } - - uint8_t consume_byte() { - if (pos_ >= size_) return 0; - return data_[pos_++]; - } - - int64_t consume_int64() { - int64_t val = 0; - for (int i = 0; i < 8 && pos_ < size_; i++) { - val |= static_cast(data_[pos_++]) << (i * 8); - } - return val; - } - - const char* consume_string(size_t max_len) { - if (max_len > sizeof(string_buf_) - 1) max_len = sizeof(string_buf_) - 1; - size_t avail = size_ - pos_; - size_t len = (avail < max_len) ? avail : max_len; - - size_t actual_len = 0; - while (actual_len < len && pos_ < size_) { - char c = static_cast(data_[pos_++]); - if (c == '\0') break; - string_buf_[actual_len++] = c; - } - string_buf_[actual_len] = '\0'; - return string_buf_; - } - - size_t remaining() const { return size_ - pos_; } - -private: - const uint8_t *data_; - size_t size_; - size_t pos_; - char string_buf_[256]; -}; extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { if (len == 0 || len > kMaxInputSize) { @@ -87,29 +44,29 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { } case 2: { // Time comparison (newer than) - int64_t sec = consumer.consume_int64(); - int64_t nsec = consumer.consume_int64() % 1000000000; + int64_t sec = consumer.consume_i64(); + int64_t nsec = consumer.consume_i64() % 1000000000; archive_match_include_time(match, ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_NEWER, sec, nsec); break; } case 3: { // Time comparison (older than) - int64_t sec = consumer.consume_int64(); - int64_t nsec = consumer.consume_int64() % 1000000000; + int64_t sec = consumer.consume_i64(); + int64_t nsec = consumer.consume_i64() % 1000000000; archive_match_include_time(match, ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER, sec, nsec); break; } case 4: { // UID inclusion - int64_t uid = consumer.consume_int64() & 0xFFFF; + int64_t uid = consumer.consume_i64() & 0xFFFF; archive_match_include_uid(match, uid); break; } case 5: { // GID inclusion - int64_t gid = consumer.consume_int64() & 0xFFFF; + int64_t gid = consumer.consume_i64() & 0xFFFF; archive_match_include_gid(match, gid); break; } diff --git a/contrib/oss-fuzz/libarchive_mtree_fuzzer.cc b/contrib/oss-fuzz/libarchive_mtree_fuzzer.cc index e0c39249c..e0110d4e1 100644 --- a/contrib/oss-fuzz/libarchive_mtree_fuzzer.cc +++ b/contrib/oss-fuzz/libarchive_mtree_fuzzer.cc @@ -8,23 +8,11 @@ #include "archive.h" #include "archive_entry.h" +#include "fuzz_helpers.h" static constexpr size_t kMaxInputSize = 256 * 1024; -struct Buffer { - const uint8_t *buf; - size_t len; -}; -static ssize_t reader_callback(struct archive *a, void *client_data, - const void **block) { - (void)a; - Buffer *buffer = reinterpret_cast(client_data); - *block = buffer->buf; - ssize_t len = buffer->len; - buffer->len = 0; - return len; -} extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { if (len == 0 || len > kMaxInputSize) { @@ -42,7 +30,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { // Enable checkfs option to test more code paths archive_read_set_options(a, "mtree:checkfs"); - Buffer buffer = {buf, len}; + Buffer buffer = {buf, len, 0}; if (archive_read_open(a, &buffer, NULL, reader_callback, NULL) != ARCHIVE_OK) { archive_read_free(a); return 0; diff --git a/contrib/oss-fuzz/libarchive_rar5_fuzzer.cc b/contrib/oss-fuzz/libarchive_rar5_fuzzer.cc index 4850879b3..2a7b97f87 100644 --- a/contrib/oss-fuzz/libarchive_rar5_fuzzer.cc +++ b/contrib/oss-fuzz/libarchive_rar5_fuzzer.cc @@ -8,23 +8,11 @@ #include "archive.h" #include "archive_entry.h" +#include "fuzz_helpers.h" static constexpr size_t kMaxInputSize = 512 * 1024; // 512KB -struct Buffer { - const uint8_t *buf; - size_t len; -}; -static ssize_t reader_callback(struct archive *a, void *client_data, - const void **block) { - (void)a; - Buffer *buffer = reinterpret_cast(client_data); - *block = buffer->buf; - ssize_t len = buffer->len; - buffer->len = 0; - return len; -} extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { if (len == 0 || len > kMaxInputSize) { @@ -44,7 +32,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { // Set passphrase for encrypted archives archive_read_add_passphrase(a, "password"); - Buffer buffer = {buf, len}; + Buffer buffer = {buf, len, 0}; if (archive_read_open(a, &buffer, NULL, reader_callback, NULL) != ARCHIVE_OK) { archive_read_free(a); return 0; diff --git a/contrib/oss-fuzz/libarchive_rar_fuzzer.cc b/contrib/oss-fuzz/libarchive_rar_fuzzer.cc index bf88a8b18..dd94181bc 100644 --- a/contrib/oss-fuzz/libarchive_rar_fuzzer.cc +++ b/contrib/oss-fuzz/libarchive_rar_fuzzer.cc @@ -7,23 +7,11 @@ #include "archive.h" #include "archive_entry.h" +#include "fuzz_helpers.h" static constexpr size_t kMaxInputSize = 512 * 1024; -struct Buffer { - const uint8_t *buf; - size_t len; -}; -static ssize_t reader_callback(struct archive *a, void *client_data, - const void **block) { - (void)a; - Buffer *buffer = reinterpret_cast(client_data); - *block = buffer->buf; - ssize_t len = buffer->len; - buffer->len = 0; - return len; -} extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { if (len == 0 || len > kMaxInputSize) { @@ -41,7 +29,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { // Add passphrase for encrypted RARs archive_read_add_passphrase(a, "password"); - Buffer buffer = {buf, len}; + Buffer buffer = {buf, len, 0}; if (archive_read_open(a, &buffer, NULL, reader_callback, NULL) != ARCHIVE_OK) { archive_read_free(a); return 0; diff --git a/contrib/oss-fuzz/libarchive_read_disk_fuzzer.cc b/contrib/oss-fuzz/libarchive_read_disk_fuzzer.cc index 5d7fecf78..91ccea15f 100644 --- a/contrib/oss-fuzz/libarchive_read_disk_fuzzer.cc +++ b/contrib/oss-fuzz/libarchive_read_disk_fuzzer.cc @@ -12,49 +12,10 @@ #include "archive.h" #include "archive_entry.h" +#include "fuzz_helpers.h" static constexpr size_t kMaxInputSize = 16 * 1024; -class DataConsumer { -public: - DataConsumer(const uint8_t *data, size_t size) : data_(data), size_(size), pos_(0) { - memset(string_buf_, 0, sizeof(string_buf_)); - } - - bool empty() const { return pos_ >= size_; } - - uint8_t consume_byte() { - if (pos_ >= size_) return 0; - return data_[pos_++]; - } - - const char* consume_string(size_t max_len) { - if (max_len > sizeof(string_buf_) - 1) max_len = sizeof(string_buf_) - 1; - size_t avail = size_ - pos_; - size_t len = (avail < max_len) ? avail : max_len; - - size_t actual_len = 0; - while (actual_len < len && pos_ < size_) { - char c = static_cast(data_[pos_++]); - if (c == '\0') break; - // Sanitize path characters for safety - if (c == '/' || c == '\\' || c == ':' || c == '\n' || c == '\r') { - c = '_'; - } - string_buf_[actual_len++] = c; - } - string_buf_[actual_len] = '\0'; - return string_buf_; - } - - size_t remaining() const { return size_ - pos_; } - -private: - const uint8_t *data_; - size_t size_; - size_t pos_; - char string_buf_[256]; -}; extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { if (len == 0 || len > kMaxInputSize) { diff --git a/contrib/oss-fuzz/libarchive_roundtrip_fuzzer.cc b/contrib/oss-fuzz/libarchive_roundtrip_fuzzer.cc index abe2b22af..15d4434bc 100644 --- a/contrib/oss-fuzz/libarchive_roundtrip_fuzzer.cc +++ b/contrib/oss-fuzz/libarchive_roundtrip_fuzzer.cc @@ -10,62 +10,10 @@ #include "archive.h" #include "archive_entry.h" +#include "fuzz_helpers.h" static constexpr size_t kMaxInputSize = 64 * 1024; -class DataConsumer { -public: - DataConsumer(const uint8_t *data, size_t size) : data_(data), size_(size), pos_(0) { - memset(string_buf_, 0, sizeof(string_buf_)); - } - - bool empty() const { return pos_ >= size_; } - - uint8_t consume_byte() { - if (pos_ >= size_) return 0; - return data_[pos_++]; - } - - uint32_t consume_uint32() { - uint32_t val = 0; - for (int i = 0; i < 4 && pos_ < size_; i++) { - val |= static_cast(data_[pos_++]) << (i * 8); - } - return val; - } - - const char* consume_string(size_t max_len) { - if (max_len > sizeof(string_buf_) - 1) max_len = sizeof(string_buf_) - 1; - size_t avail = size_ - pos_; - size_t len = (avail < max_len) ? avail : max_len; - - size_t actual_len = 0; - while (actual_len < len && pos_ < size_) { - char c = static_cast(data_[pos_++]); - if (c == '\0') break; - string_buf_[actual_len++] = c; - } - string_buf_[actual_len] = '\0'; - return string_buf_; - } - - const uint8_t* consume_bytes(size_t *out_len, size_t max_len) { - size_t avail = size_ - pos_; - size_t len = (avail < max_len) ? avail : max_len; - const uint8_t *ptr = data_ + pos_; - pos_ += len; - *out_len = len; - return ptr; - } - - size_t remaining() const { return size_ - pos_; } - -private: - const uint8_t *data_; - size_t size_; - size_t pos_; - char string_buf_[128]; -}; extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { if (len < 10 || len > kMaxInputSize) { @@ -110,15 +58,15 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { archive_entry_set_pathname(entry, consumer.consume_string(32)); archive_entry_set_mode(entry, S_IFREG | 0644); - archive_entry_set_uid(entry, consumer.consume_uint32() & 0xFFFF); - archive_entry_set_gid(entry, consumer.consume_uint32() & 0xFFFF); + archive_entry_set_uid(entry, consumer.consume_u32() & 0xFFFF); + archive_entry_set_gid(entry, consumer.consume_u32() & 0xFFFF); - size_t data_len; - const uint8_t *data = consumer.consume_bytes(&data_len, 256); + uint8_t data_buf[256]; + size_t data_len = consumer.consume_bytes(data_buf, 256); archive_entry_set_size(entry, data_len); if (archive_write_header(writer, entry) == ARCHIVE_OK && data_len > 0) { - archive_write_data(writer, data, data_len); + archive_write_data(writer, data_buf, data_len); } archive_entry_free(entry); diff --git a/contrib/oss-fuzz/libarchive_seek_fuzzer.cc b/contrib/oss-fuzz/libarchive_seek_fuzzer.cc index 148727c7d..11e958030 100644 --- a/contrib/oss-fuzz/libarchive_seek_fuzzer.cc +++ b/contrib/oss-fuzz/libarchive_seek_fuzzer.cc @@ -9,6 +9,7 @@ #include "archive.h" #include "archive_entry.h" +#include "fuzz_helpers.h" static constexpr size_t kMaxInputSize = 256 * 1024; diff --git a/contrib/oss-fuzz/libarchive_string_fuzzer.cc b/contrib/oss-fuzz/libarchive_string_fuzzer.cc index 7fe3a99dc..24731da1c 100644 --- a/contrib/oss-fuzz/libarchive_string_fuzzer.cc +++ b/contrib/oss-fuzz/libarchive_string_fuzzer.cc @@ -10,6 +10,7 @@ #include "archive.h" #include "archive_entry.h" +#include "fuzz_helpers.h" static constexpr size_t kMaxInputSize = 32 * 1024; diff --git a/contrib/oss-fuzz/libarchive_warc_fuzzer.cc b/contrib/oss-fuzz/libarchive_warc_fuzzer.cc index f046bab48..2ae7a167f 100644 --- a/contrib/oss-fuzz/libarchive_warc_fuzzer.cc +++ b/contrib/oss-fuzz/libarchive_warc_fuzzer.cc @@ -7,23 +7,11 @@ #include "archive.h" #include "archive_entry.h" +#include "fuzz_helpers.h" static constexpr size_t kMaxInputSize = 512 * 1024; -struct Buffer { - const uint8_t *buf; - size_t len; -}; - -static ssize_t reader_callback(struct archive *a, void *client_data, - const void **block) { - (void)a; - Buffer *buffer = reinterpret_cast(client_data); - *block = buffer->buf; - ssize_t len = buffer->len; - buffer->len = 0; - return len; -} + extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { if (len == 0 || len > kMaxInputSize) { @@ -38,7 +26,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { archive_read_support_format_warc(a); archive_read_support_filter_all(a); - Buffer buffer = {buf, len}; + Buffer buffer = {buf, len, 0}; if (archive_read_open(a, &buffer, NULL, reader_callback, NULL) != ARCHIVE_OK) { archive_read_free(a); return 0; diff --git a/contrib/oss-fuzz/libarchive_write_fuzzer.cc b/contrib/oss-fuzz/libarchive_write_fuzzer.cc index 8612a6e9d..012c5a4f5 100644 --- a/contrib/oss-fuzz/libarchive_write_fuzzer.cc +++ b/contrib/oss-fuzz/libarchive_write_fuzzer.cc @@ -10,71 +10,11 @@ #include "archive.h" #include "archive_entry.h" +#include "fuzz_helpers.h" static constexpr size_t kMaxInputSize = 64 * 1024; // 64KB // Simple data consumer -class DataConsumer { -public: - DataConsumer(const uint8_t *data, size_t size) : data_(data), size_(size), pos_(0) { - memset(string_buf_, 0, sizeof(string_buf_)); - } - - bool empty() const { return pos_ >= size_; } - - uint8_t consume_byte() { - if (pos_ >= size_) return 0; - return data_[pos_++]; - } - - uint32_t consume_uint32() { - uint32_t val = 0; - for (int i = 0; i < 4 && pos_ < size_; i++) { - val |= static_cast(data_[pos_++]) << (i * 8); - } - return val; - } - - int64_t consume_int64() { - int64_t val = 0; - for (int i = 0; i < 8 && pos_ < size_; i++) { - val |= static_cast(data_[pos_++]) << (i * 8); - } - return val; - } - - const char* consume_string(size_t max_len) { - if (max_len > sizeof(string_buf_) - 1) max_len = sizeof(string_buf_) - 1; - size_t avail = size_ - pos_; - size_t len = (avail < max_len) ? avail : max_len; - - size_t actual_len = 0; - while (actual_len < len && pos_ < size_) { - char c = static_cast(data_[pos_++]); - if (c == '\0') break; - string_buf_[actual_len++] = c; - } - string_buf_[actual_len] = '\0'; - return string_buf_; - } - - const uint8_t* consume_bytes(size_t *out_len, size_t max_len) { - size_t avail = size_ - pos_; - size_t len = (avail < max_len) ? avail : max_len; - const uint8_t *ptr = data_ + pos_; - pos_ += len; - *out_len = len; - return ptr; - } - - size_t remaining() const { return size_ - pos_; } - -private: - const uint8_t *data_; - size_t size_; - size_t pos_; - char string_buf_[256]; -}; // Memory write callback static std::vector *g_output = nullptr; @@ -159,18 +99,18 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { } archive_entry_set_mode(entry, mode); - archive_entry_set_uid(entry, consumer.consume_uint32() & 0xFFFF); - archive_entry_set_gid(entry, consumer.consume_uint32() & 0xFFFF); - archive_entry_set_mtime(entry, consumer.consume_int64(), 0); + archive_entry_set_uid(entry, consumer.consume_u32() & 0xFFFF); + archive_entry_set_gid(entry, consumer.consume_u32() & 0xFFFF); + archive_entry_set_mtime(entry, consumer.consume_i64(), 0); // For regular files, write some data if (S_ISREG(mode)) { - size_t data_len; - const uint8_t *data = consumer.consume_bytes(&data_len, 1024); + uint8_t data_buf[1024]; + size_t data_len = consumer.consume_bytes(data_buf, 1024); archive_entry_set_size(entry, data_len); if (archive_write_header(a, entry) == ARCHIVE_OK && data_len > 0) { - archive_write_data(a, data, data_len); + archive_write_data(a, data_buf, data_len); } } else if (S_ISLNK(mode)) { archive_entry_set_symlink(entry, consumer.consume_string(64)); diff --git a/contrib/oss-fuzz/libarchive_xar_fuzzer.cc b/contrib/oss-fuzz/libarchive_xar_fuzzer.cc index 8f787432a..be8896431 100644 --- a/contrib/oss-fuzz/libarchive_xar_fuzzer.cc +++ b/contrib/oss-fuzz/libarchive_xar_fuzzer.cc @@ -8,23 +8,11 @@ #include "archive.h" #include "archive_entry.h" +#include "fuzz_helpers.h" static constexpr size_t kMaxInputSize = 512 * 1024; // 512KB -struct Buffer { - const uint8_t *buf; - size_t len; -}; -static ssize_t reader_callback(struct archive *a, void *client_data, - const void **block) { - (void)a; - Buffer *buffer = reinterpret_cast(client_data); - *block = buffer->buf; - ssize_t len = buffer->len; - buffer->len = 0; - return len; -} extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { if (len == 0 || len > kMaxInputSize) { @@ -41,7 +29,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { // Enable common filters archive_read_support_filter_all(a); - Buffer buffer = {buf, len}; + Buffer buffer = {buf, len, 0}; if (archive_read_open(a, &buffer, NULL, reader_callback, NULL) != ARCHIVE_OK) { archive_read_free(a); return 0; diff --git a/contrib/oss-fuzz/libarchive_zip_fuzzer.cc b/contrib/oss-fuzz/libarchive_zip_fuzzer.cc index 57331f4b7..15ce1f485 100644 --- a/contrib/oss-fuzz/libarchive_zip_fuzzer.cc +++ b/contrib/oss-fuzz/libarchive_zip_fuzzer.cc @@ -8,23 +8,11 @@ #include "archive.h" #include "archive_entry.h" +#include "fuzz_helpers.h" static constexpr size_t kMaxInputSize = 512 * 1024; -struct Buffer { - const uint8_t *buf; - size_t len; -}; -static ssize_t reader_callback(struct archive *a, void *client_data, - const void **block) { - (void)a; - Buffer *buffer = reinterpret_cast(client_data); - *block = buffer->buf; - ssize_t len = buffer->len; - buffer->len = 0; - return len; -} extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { if (len == 0 || len > kMaxInputSize) { @@ -47,7 +35,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { // Enable ZIP options archive_read_set_options(a, "zip:ignorecrc32"); - Buffer buffer = {buf, len}; + Buffer buffer = {buf, len, 0}; if (archive_read_open(a, &buffer, NULL, reader_callback, NULL) != ARCHIVE_OK) { archive_read_free(a); return 0;