Skip to content

Commit e5e5217

Browse files
committed
Add initial fuzz target
1 parent bae3972 commit e5e5217

File tree

8 files changed

+98
-28
lines changed

8 files changed

+98
-28
lines changed

CMakeLists.txt

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,12 @@ endif()
4444
# Building the testing tree is enabled by including CTest, but as it is not
4545
# strictly required to build the product itself, switch to off by default.
4646
option(BUILD_TESTING "Build the testing tree." OFF)
47+
option(BUILD_FUZZING "Build the fuzz target." OFF)
4748
option(BUILD_DOCUMENTATION "Build documentation." OFF)
4849

50+
#set(SANITIZE "" CACHE STRING "Sanitizers to enable for the build.")
51+
set(ANALYZER "" CACHE STRING "Analyzer to enable during build.")
52+
4953
if(CMAKE_VERSION VERSION_LESS 3.20)
5054
# CMAKE_<LANG>_BYTE_ORDER was added in version 3.20. Mimic the option in
5155
# prior versions.
@@ -63,6 +67,27 @@ include(GenerateExportHeader)
6367
include(GNUInstallDirs)
6468
include(CTest)
6569

70+
if(CMAKE_C_COMPILER_ID MATCHES "Clang" OR CMAKE_C_COMPILER_ID STREQUAL "GNU")
71+
if(DEFINED SANITIZE)
72+
string(REGEX REPLACE " " "" sanitizers "${SANITIZE}")
73+
string(REGEX REPLACE "[,;]+" ";" sanitizers "${sanitizers}")
74+
list(FILTER sanitizers INCLUDE REGEX "^(address|undefined|leak)$")
75+
elseif(BUILD_FUZZING AND CMAKE_C_COMPILER_ID MATCHES "Clang")
76+
set(sanitizers "address;undefined;leak")
77+
endif()
78+
79+
if(sanitizers)
80+
if("address" IN_LIST sanitizers)
81+
add_compile_options(-fno-omit-frame-pointer)
82+
add_link_options(-fno-omit-frame-pointer)
83+
endif()
84+
string(JOIN "," sanitize ${sanitizers})
85+
add_compile_options(-fsanitize=${sanitize})
86+
add_link_options(-fsanitize=${sanitize})
87+
message(STATUS "Sanitizers: ${sanitize}")
88+
endif()
89+
endif()
90+
6691
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
6792
add_compile_options(
6893
-Wall -Wextra -Wconversion -Wunused -Wmissing-prototypes
@@ -81,7 +106,6 @@ elseif(CMAKE_C_COMPILER_ID STREQUAL "MSVC")
81106
add_compile_options(/W3)
82107
endif()
83108

84-
set(ANALYZER "" CACHE STRING "Analyzer to enable on the build.")
85109
if(ANALYZER)
86110
# GCC and Visual Studio offer builtin analyzers. Clang supports static
87111
# analysis through separate tools, e.g. Clang-Tidy, which can be used in
@@ -97,43 +121,23 @@ if(ANALYZER)
97121
if(ANALYZER STREQUAL "clang-tidy")
98122
# Clang-Tidy is an extensible tool that offers more than static analysis.
99123
# https://clang.llvm.org/extra/clang-tidy/checks/list.html
100-
message(STATUS "Enabling analyzer: clang-tidy")
124+
message(STATUS "Analyzer: clang-tidy")
101125
set(CMAKE_C_CLANG_TIDY "clang-tidy;-checks=-*,clang-analyzer-*,-clang-analyzer-security.insecureAPI.strcpy,-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling")
102126
if(CMAKE_COMPILE_WARNING_AS_ERROR)
103127
set(CMAKE_C_CLANG_TIDY "${CMAKE_C_CLANG_TIDY};--warnings-as-errors=*")
104128
endif()
105129
elseif(ANALYZER STREQUAL "on")
106130
if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
107131
if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL "10")
108-
message(STATUS "Enabling analyzer: GCC")
132+
message(STATUS "Analyzer: GCC")
109133
# -Wanalyzer-malloc-leak generates lots of false positives
110134
add_compile_options(-fanalyzer -Wno-analyzer-malloc-leak)
111135
endif()
112136
endif()
113137
endif()
114138
endif()
115139

116-
set(SANITIZER "" CACHE STRING "Sanitizers to enable on the build.")
117-
if(SANITIZER)
118-
string(REGEX REPLACE " " "" SANITIZER "${SANITIZER}")
119-
string(REGEX REPLACE "[,;]+" ";" SANITIZER "${SANITIZER}")
120-
foreach(san ${SANITIZER})
121-
if(san STREQUAL "address")
122-
add_compile_options("-fno-omit-frame-pointer")
123-
add_link_options("-fno-omit-frame-pointer")
124-
endif()
125-
if(san AND NOT san STREQUAL "none")
126-
message(STATUS "Enabling sanitizer: ${san}")
127-
add_compile_options("-fsanitize=${san}")
128-
add_link_options("-fsanitize=${san}")
129-
endif()
130-
endforeach()
131-
endif()
132-
133140
add_library(zone STATIC)
134-
if(WIN32)
135-
target_link_libraries(zone INTERFACE ws2_32)
136-
endif()
137141

138142
generate_export_header(
139143
zone BASE_NAME ZONE EXPORT_FILE_NAME include/zone/export.h)
@@ -233,6 +237,10 @@ if(BUILD_TESTING)
233237
add_subdirectory(tests)
234238
endif()
235239

240+
if(BUILD_FUZZING)
241+
add_subdirectory(fuzz)
242+
endif()
243+
236244
if(BUILD_DOCUMENTATION)
237245
set(DOXYGEN_GENERATE_HTML YES)
238246
set(DOXYGEN_GENERATE_XML NO)

fuzz/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
2+
add_executable(zone-fuzzer fuzzer.c)
3+
target_compile_options(zone-fuzzer PUBLIC -fsanitize=fuzzer)
4+
target_link_options(zone-fuzzer PUBLIC -fsanitize=fuzzer)
5+
target_link_libraries(zone-fuzzer PRIVATE zone)
6+
endif()

fuzz/corpus/A

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
example.com. A 192.168.0.1

fuzz/corpus/SOA

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
$ORIGIN example.com.
2+
$TTL 86400
3+
@ IN SOA dns1.example.com. hostmaster.example.com. (
4+
2001062501 ; serial
5+
21600 ; refresh after 6 hours
6+
3600 ; retry after 1 hour
7+
604800 ; expire after 1 week
8+
86400 ) ; minimum TTL of 1 day

fuzz/corpus/relative-A

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
$ORIGIN example.com.
2+
A 192.168.0.1

fuzz/fuzzer.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#include <stdint.h>
2+
#include <stdlib.h>
3+
#include <string.h>
4+
5+
#include "zone.h"
6+
7+
static int32_t add_rr(zone_parser_t *parser, const zone_name_t *owner,
8+
uint16_t type, uint16_t class, uint32_t ttl,
9+
uint16_t rdlength, const uint8_t *rdata,
10+
void *user_data) {
11+
(void)parser;
12+
(void)owner;
13+
(void)type;
14+
(void)class;
15+
(void)ttl;
16+
(void)rdlength;
17+
(void)rdata;
18+
(void)user_data;
19+
return ZONE_SUCCESS;
20+
}
21+
22+
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
23+
size_t size_of_input = size + ZONE_BLOCK_SIZE + 1;
24+
char *null_terminated = (char*)malloc(size_of_input);
25+
memcpy(null_terminated, data, size);
26+
null_terminated[size] = '\0';
27+
28+
zone_parser_t parser = {0};
29+
zone_name_buffer_t name;
30+
zone_rdata_buffer_t rdata;
31+
zone_buffers_t buffers = {1, &name, &rdata};
32+
zone_options_t options = {0};
33+
34+
options.accept.callback = add_rr;
35+
options.origin = "example.com.";
36+
options.default_ttl = 3600;
37+
options.default_class = 1;
38+
39+
zone_parse_string(&parser, &options, &buffers, null_terminated, size,
40+
NULL);
41+
42+
free(null_terminated);
43+
return 0;
44+
}

src/haswell/bits.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ static inline uint64_t count_ones(uint64_t bits) {
2121
return (uint64_t)_mm_popcnt_u64(bits);
2222
}
2323

24+
__attribute__((no_sanitize("undefined")))
2425
static inline uint64_t trailing_zeroes(uint64_t bits) {
2526
return (uint64_t)__builtin_ctzll(bits);
2627
}

src/zone.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,20 +104,20 @@ static int parse_origin(const char *origin, uint8_t str[255], size_t *len)
104104
#include "isadetection.h"
105105

106106
#if HAVE_HASWELL
107-
extern int32_t zone_haswell_parse(parser_t *, void *);
107+
extern int32_t zone_haswell_parse(parser_t *);
108108
#endif
109109

110110
#if HAVE_WESTMERE
111-
extern int32_t zone_westmere_parse(parser_t *, void *);
111+
extern int32_t zone_westmere_parse(parser_t *);
112112
#endif
113113

114-
extern int32_t zone_fallback_parse(parser_t *, void *);
114+
extern int32_t zone_fallback_parse(parser_t *);
115115

116116
typedef struct kernel kernel_t;
117117
struct kernel {
118118
const char *name;
119119
uint32_t instruction_set;
120-
int32_t (*parse)(parser_t *, void *);
120+
int32_t (*parse)(parser_t *);
121121
};
122122

123123
static const kernel_t kernels[] = {
@@ -165,7 +165,7 @@ static int32_t parse(parser_t *parser, void *user_data)
165165
kernel = select_kernel();
166166
assert(kernel);
167167
parser->user_data = user_data;
168-
return kernel->parse(parser, user_data);
168+
return kernel->parse(parser);
169169
}
170170

171171
diagnostic_push()

0 commit comments

Comments
 (0)