/src/clamav/fuzz/clamav_scanmap_fuzzer.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Fuzz target for cl_scanmap_callback() |
3 | | * |
4 | | * Copyright (C) 2018-2023 Cisco Systems, Inc. and/or its affiliates. All rights reserved. |
5 | | * Authors: Micah Snyder, Alex Gaynor |
6 | | * |
7 | | * Redistribution and use in source and binary forms, with or without |
8 | | * modification, are permitted provided that the following conditions are met: |
9 | | * |
10 | | * 1. Redistributions of source code must retain the above copyright notice, |
11 | | * this list of conditions and the following disclaimer. |
12 | | * |
13 | | * 2. Redistributions in binary form must reproduce the above copyright notice, |
14 | | * this list of conditions and the following disclaimer in the documentation |
15 | | * and/or other materials provided with the distribution. |
16 | | * |
17 | | * 3. Neither the name of the copyright holder nor the names of its contributors |
18 | | * may be used to endorse or promote products derived from this software without |
19 | | * specific prior written permission. |
20 | | * |
21 | | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
22 | | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
23 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
24 | | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
25 | | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
26 | | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
27 | | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
28 | | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
29 | | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
30 | | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
31 | | * POSSIBILITY OF SUCH DAMAGE. |
32 | | */ |
33 | | |
34 | | #include <stdint.h> |
35 | | #include <stdlib.h> |
36 | | #include <string.h> |
37 | | |
38 | | #include "clamav.h" |
39 | | |
40 | | void clamav_message_callback(enum cl_msg severity, const char *fullmsg, |
41 | | const char *msg, void *context) |
42 | 2.29M | { |
43 | 2.29M | } |
44 | | |
45 | | class ClamAVState |
46 | | { |
47 | | public: |
48 | | ClamAVState() |
49 | 156 | { |
50 | | // Silence all the log messages, none of them are meaningful. |
51 | 156 | cl_set_clcb_msg(clamav_message_callback); |
52 | | |
53 | 156 | cl_init(CL_INIT_DEFAULT); |
54 | 156 | engine = cl_engine_new(); |
55 | 156 | cl_engine_compile(engine); |
56 | | |
57 | 156 | memset(&scanopts, 0, sizeof(struct cl_scan_options)); |
58 | | |
59 | 156 | scanopts.parse |= |
60 | | #if defined(CLAMAV_FUZZ_ARCHIVE) |
61 | | CL_SCAN_PARSE_ARCHIVE; |
62 | | #elif defined(CLAMAV_FUZZ_MAIL) |
63 | | CL_SCAN_PARSE_MAIL; |
64 | | #elif defined(CLAMAV_FUZZ_OLE2) |
65 | | CL_SCAN_PARSE_OLE2; |
66 | | #elif defined(CLAMAV_FUZZ_PDF) |
67 | | CL_SCAN_PARSE_PDF; |
68 | | #elif defined(CLAMAV_FUZZ_HTML) |
69 | | CL_SCAN_PARSE_HTML; |
70 | | #elif defined(CLAMAV_FUZZ_PE) |
71 | | CL_SCAN_PARSE_PE; |
72 | | #elif defined(CLAMAV_FUZZ_ELF) |
73 | | CL_SCAN_PARSE_ELF; |
74 | | #elif defined(CLAMAV_FUZZ_SWF) |
75 | | CL_SCAN_PARSE_SWF; |
76 | | #elif defined(CLAMAV_FUZZ_XMLDOCS) |
77 | 78 | CL_SCAN_PARSE_XMLDOCS; |
78 | | #elif defined(CLAMAV_FUZZ_HWP3) |
79 | | CL_SCAN_PARSE_HWP3; |
80 | | #else |
81 | | ~(0); |
82 | | #endif |
83 | 156 | scanopts.general |= CL_SCAN_GENERAL_HEURISTICS; |
84 | 156 | scanopts.general |= CL_SCAN_GENERAL_COLLECT_METADATA; /* Enable the gen-json feature */ |
85 | 156 | scanopts.heuristic |= ~(0); /* Enable all heuristic code */ |
86 | 156 | scanopts.general |= CL_SCAN_GENERAL_ALLMATCHES; /* Enable all-match, so heuristic alerts don't end the scan early */ |
87 | 156 | } ClamAVState::ClamAVState() Line | Count | Source | 49 | 78 | { | 50 | | // Silence all the log messages, none of them are meaningful. | 51 | 78 | cl_set_clcb_msg(clamav_message_callback); | 52 | | | 53 | 78 | cl_init(CL_INIT_DEFAULT); | 54 | 78 | engine = cl_engine_new(); | 55 | 78 | cl_engine_compile(engine); | 56 | | | 57 | 78 | memset(&scanopts, 0, sizeof(struct cl_scan_options)); | 58 | | | 59 | 78 | scanopts.parse |= | 60 | | #if defined(CLAMAV_FUZZ_ARCHIVE) | 61 | | CL_SCAN_PARSE_ARCHIVE; | 62 | | #elif defined(CLAMAV_FUZZ_MAIL) | 63 | | CL_SCAN_PARSE_MAIL; | 64 | | #elif defined(CLAMAV_FUZZ_OLE2) | 65 | | CL_SCAN_PARSE_OLE2; | 66 | | #elif defined(CLAMAV_FUZZ_PDF) | 67 | | CL_SCAN_PARSE_PDF; | 68 | | #elif defined(CLAMAV_FUZZ_HTML) | 69 | | CL_SCAN_PARSE_HTML; | 70 | | #elif defined(CLAMAV_FUZZ_PE) | 71 | | CL_SCAN_PARSE_PE; | 72 | | #elif defined(CLAMAV_FUZZ_ELF) | 73 | | CL_SCAN_PARSE_ELF; | 74 | | #elif defined(CLAMAV_FUZZ_SWF) | 75 | | CL_SCAN_PARSE_SWF; | 76 | | #elif defined(CLAMAV_FUZZ_XMLDOCS) | 77 | 78 | CL_SCAN_PARSE_XMLDOCS; | 78 | | #elif defined(CLAMAV_FUZZ_HWP3) | 79 | | CL_SCAN_PARSE_HWP3; | 80 | | #else | 81 | | ~(0); | 82 | | #endif | 83 | 78 | scanopts.general |= CL_SCAN_GENERAL_HEURISTICS; | 84 | 78 | scanopts.general |= CL_SCAN_GENERAL_COLLECT_METADATA; /* Enable the gen-json feature */ | 85 | 78 | scanopts.heuristic |= ~(0); /* Enable all heuristic code */ | 86 | 78 | scanopts.general |= CL_SCAN_GENERAL_ALLMATCHES; /* Enable all-match, so heuristic alerts don't end the scan early */ | 87 | 78 | } |
ClamAVState::ClamAVState() Line | Count | Source | 49 | 78 | { | 50 | | // Silence all the log messages, none of them are meaningful. | 51 | 78 | cl_set_clcb_msg(clamav_message_callback); | 52 | | | 53 | 78 | cl_init(CL_INIT_DEFAULT); | 54 | 78 | engine = cl_engine_new(); | 55 | 78 | cl_engine_compile(engine); | 56 | | | 57 | 78 | memset(&scanopts, 0, sizeof(struct cl_scan_options)); | 58 | | | 59 | 78 | scanopts.parse |= | 60 | | #if defined(CLAMAV_FUZZ_ARCHIVE) | 61 | | CL_SCAN_PARSE_ARCHIVE; | 62 | | #elif defined(CLAMAV_FUZZ_MAIL) | 63 | | CL_SCAN_PARSE_MAIL; | 64 | | #elif defined(CLAMAV_FUZZ_OLE2) | 65 | | CL_SCAN_PARSE_OLE2; | 66 | | #elif defined(CLAMAV_FUZZ_PDF) | 67 | | CL_SCAN_PARSE_PDF; | 68 | | #elif defined(CLAMAV_FUZZ_HTML) | 69 | | CL_SCAN_PARSE_HTML; | 70 | | #elif defined(CLAMAV_FUZZ_PE) | 71 | | CL_SCAN_PARSE_PE; | 72 | | #elif defined(CLAMAV_FUZZ_ELF) | 73 | | CL_SCAN_PARSE_ELF; | 74 | | #elif defined(CLAMAV_FUZZ_SWF) | 75 | | CL_SCAN_PARSE_SWF; | 76 | | #elif defined(CLAMAV_FUZZ_XMLDOCS) | 77 | | CL_SCAN_PARSE_XMLDOCS; | 78 | | #elif defined(CLAMAV_FUZZ_HWP3) | 79 | | CL_SCAN_PARSE_HWP3; | 80 | | #else | 81 | 78 | ~(0); | 82 | 78 | #endif | 83 | 78 | scanopts.general |= CL_SCAN_GENERAL_HEURISTICS; | 84 | 78 | scanopts.general |= CL_SCAN_GENERAL_COLLECT_METADATA; /* Enable the gen-json feature */ | 85 | 78 | scanopts.heuristic |= ~(0); /* Enable all heuristic code */ | 86 | 78 | scanopts.general |= CL_SCAN_GENERAL_ALLMATCHES; /* Enable all-match, so heuristic alerts don't end the scan early */ | 87 | 78 | } |
|
88 | | |
89 | | ~ClamAVState() |
90 | 0 | { |
91 | 0 | cl_engine_free(engine); |
92 | 0 | } |
93 | | |
94 | | struct cl_engine *engine; |
95 | | struct cl_scan_options scanopts; |
96 | | }; |
97 | | |
98 | | // Global with static initializer to setup an engine so we don't need to do |
99 | | // that on each execution. |
100 | | ClamAVState kClamAVState; |
101 | | |
102 | | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) |
103 | 133k | { |
104 | | |
105 | 133k | cl_fmap_t *clamav_data = cl_fmap_open_memory(data, size); |
106 | | |
107 | 133k | const char *virus_name = nullptr; |
108 | 133k | unsigned long scanned = 0; |
109 | | |
110 | 133k | cl_scanmap_callback( |
111 | 133k | clamav_data, |
112 | 133k | NULL, |
113 | 133k | &virus_name, |
114 | 133k | &scanned, |
115 | 133k | kClamAVState.engine, |
116 | 133k | &kClamAVState.scanopts, |
117 | 133k | nullptr); |
118 | | |
119 | 133k | cl_fmap_close(clamav_data); |
120 | | |
121 | 133k | return 0; |
122 | 133k | } |