/src/libxlsxwriter/dev/fuzzing/xlsx_fuzzer.cpp
Line | Count | Source |
1 | | #include <cstdint> |
2 | | #include <unistd.h> |
3 | | #include <fuzzer/FuzzedDataProvider.h> |
4 | | |
5 | | #include "xlsxwriter.h" |
6 | | |
7 | | const std::string mem_dir{"/dev/shm"}; |
8 | | const std::string file_template = "/fuzzXXXXXX"; |
9 | | char temp_file_dir[FILENAME_MAX] = {0}; |
10 | | |
11 | | /** |
12 | | * \brief: Performs all prep-work needed for continuous fuzzing |
13 | | * \return: Whether initialization was successful |
14 | | */ |
15 | | int init_for_fuzzing() |
16 | 1 | { |
17 | | // Initialize the temporary file directory, based off what is available on the system |
18 | | |
19 | 1 | if (0 == access(mem_dir.c_str(), W_OK | R_OK)) |
20 | 1 | { |
21 | | // We can read and write to the in-memory directory |
22 | 1 | memcpy(temp_file_dir, mem_dir.c_str(), strnlen(mem_dir.c_str(), FILENAME_MAX)); |
23 | 1 | } |
24 | 0 | else |
25 | 0 | { |
26 | | // Default to a temporary directory |
27 | 0 | const char* tmp_prefix = getenv("TMPDIR"); |
28 | 0 | if (nullptr == tmp_prefix) |
29 | 0 | { |
30 | 0 | tmp_prefix = "/tmp"; |
31 | 0 | } |
32 | 0 | memcpy((void*) temp_file_dir, tmp_prefix, strnlen(tmp_prefix, FILENAME_MAX)); |
33 | 0 | } |
34 | 1 | return 0; |
35 | 1 | } |
36 | | |
37 | | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, const size_t size) |
38 | 1.34k | { |
39 | 1.34k | static bool init_fuzzing = init_for_fuzzing(); |
40 | | |
41 | 1.34k | char fuzz_file[FILENAME_MAX + 1] = {0}; |
42 | 1.34k | int fuzz_fd = 0; |
43 | 1.34k | int ret = -1; |
44 | 1.34k | ssize_t wc = 0; |
45 | 1.34k | size_t byte_len; |
46 | 1.34k | lxw_workbook *workbook = nullptr; |
47 | 1.34k | lxw_worksheet *worksheet = nullptr; |
48 | 1.34k | FuzzedDataProvider fdp{data, size}; |
49 | 1.34k | std::vector<std::uint8_t> file_bytes{}; |
50 | | |
51 | 1.34k | strncpy(fuzz_file, temp_file_dir, strlen(temp_file_dir)); |
52 | 1.34k | strncat(fuzz_file, file_template.c_str(), file_template.length()); |
53 | | |
54 | 1.34k | if ((fuzz_fd = mkstemp(fuzz_file)) < 0) |
55 | 0 | { |
56 | 0 | goto fail; |
57 | 0 | } |
58 | | |
59 | 1.34k | byte_len = fdp.ConsumeIntegralInRange<size_t>(0, fdp.remaining_bytes()); |
60 | 1.34k | file_bytes = fdp.ConsumeBytes<uint8_t>(byte_len); |
61 | 1.34k | write(fuzz_fd, file_bytes.data(), std::min(file_bytes.size(), byte_len)); |
62 | | |
63 | 1.34k | workbook = workbook_new(fuzz_file); |
64 | 1.34k | worksheet = workbook_add_worksheet(workbook, nullptr); |
65 | | |
66 | 7.45k | for (int row = 0; row < fdp.ConsumeIntegralInRange(0, 25); ++row) |
67 | 6.11k | { |
68 | 73.5k | for (int col = 0; col < fdp.ConsumeIntegralInRange(0, 25); ++col) |
69 | 67.4k | { |
70 | 67.4k | worksheet_write_string(worksheet, row, col, fdp.ConsumeRandomLengthString().c_str(), nullptr); |
71 | 67.4k | } |
72 | 6.11k | } |
73 | | |
74 | 1.34k | ret = 0; |
75 | | |
76 | 1.34k | fail: |
77 | 1.34k | if (nullptr != workbook) |
78 | 1.34k | { |
79 | 1.34k | workbook_close(workbook); |
80 | 1.34k | } |
81 | 1.34k | close(fuzz_fd); |
82 | 1.34k | unlink(fuzz_file); |
83 | 1.34k | return ret; |
84 | 1.34k | } |