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.
This commit is contained in:
Leslie P. Polzer 2025-12-22 04:53:06 +00:00
parent 544b07541b
commit eb6f992ba1
22 changed files with 58 additions and 483 deletions

View File

@ -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<Buffer *>(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;

View File

@ -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<Buffer *>(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;

View File

@ -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<Buffer *>(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;

View File

@ -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<Buffer *>(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;

View File

@ -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<Buffer *>(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;

View File

@ -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<Buffer *>(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) {

View File

@ -3,20 +3,7 @@
#include <vector>
#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<Buffer *>(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<uint8_t> data_buffer(getpagesize(), 0);

View File

@ -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<Buffer *>(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;

View File

@ -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<Buffer *>(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;

View File

@ -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<uint32_t>(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<int64_t>(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<char>(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;
}

View File

@ -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<int64_t>(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<char>(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;
}

View File

@ -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<Buffer *>(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;

View File

@ -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<Buffer *>(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;

View File

@ -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<Buffer *>(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;

View File

@ -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<char>(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) {

View File

@ -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<uint32_t>(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<char>(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);

View File

@ -9,6 +9,7 @@
#include "archive.h"
#include "archive_entry.h"
#include "fuzz_helpers.h"
static constexpr size_t kMaxInputSize = 256 * 1024;

View File

@ -10,6 +10,7 @@
#include "archive.h"
#include "archive_entry.h"
#include "fuzz_helpers.h"
static constexpr size_t kMaxInputSize = 32 * 1024;

View File

@ -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<Buffer *>(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;

View File

@ -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<uint32_t>(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<int64_t>(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<char>(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<uint8_t> *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));

View File

@ -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<Buffer *>(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;

View File

@ -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<Buffer *>(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;