Skip to content

Commit 14589e5

Browse files
authored
feat: add fuzzing harnesses (#925)
1 parent 1b9e0e2 commit 14589e5

20 files changed

+780
-24
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,5 @@ CMakeSettings.json
1616
.pixi
1717

1818
CMakeUserPresets.json
19+
20+
tags

CMakeLists.txt

+54-24
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,9 @@ cmake_minimum_required(VERSION 3.16.3) # version on Ubuntu Focal
22

33
project(behaviortree_cpp VERSION 4.6.2 LANGUAGES C CXX)
44

5-
set(CMAKE_CONFIG_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_LIST_DIR}/cmake")
6-
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CONFIG_PATH}")
7-
8-
set(BTCPP_LIBRARY ${PROJECT_NAME})
9-
10-
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
11-
message(STATUS "Setting build type to 'Release' as none was specified.")
12-
set(CMAKE_BUILD_TYPE "Release" CACHE
13-
STRING "Choose the type of build." FORCE)
14-
# Set the possible values of build type for cmake-gui
15-
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
16-
"Debug" "Release" "MinSizeRel" "RelWithDebInfo")
17-
endif()
18-
19-
if(MSVC)
20-
add_definitions(-D_CRT_SECURE_NO_WARNINGS -DWIN32_LEAN_AND_MEAN)
21-
else()
22-
add_definitions(-Wpedantic -fno-omit-frame-pointer)
23-
endif()
24-
255
# create compile_commands.json
266
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
277

28-
298
#---- project configuration ----
309
option(BTCPP_SHARED_LIBS "Build shared libraries" ON)
3110
option(BTCPP_BUILD_TOOLS "Build commandline tools" ON)
@@ -35,6 +14,48 @@ option(BTCPP_GROOT_INTERFACE "Add Groot2 connection. Requires ZeroMQ" ON)
3514
option(BTCPP_SQLITE_LOGGING "Add SQLite logging." ON)
3615

3716
option(USE_V3_COMPATIBLE_NAMES "Use some alias to compile more easily old 3.x code" OFF)
17+
option(ENABLE_FUZZING "Enable fuzzing builds" OFF)
18+
option(USE_AFLPLUSPLUS "Use AFL++ instead of libFuzzer" OFF)
19+
option(ENABLE_DEBUG "Enable debug build with full symbols" OFF)
20+
option(FORCE_STATIC_LINKING "Force static linking of all dependencies" OFF)
21+
22+
set(BASE_FLAGS "")
23+
24+
if(ENABLE_DEBUG)
25+
list(APPEND BASE_FLAGS
26+
-g3
27+
-ggdb3
28+
-O0
29+
-fno-omit-frame-pointer
30+
)
31+
endif()
32+
33+
# Include fuzzing configuration if enabled
34+
if(ENABLE_FUZZING)
35+
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/fuzzing_build.cmake)
36+
else()
37+
# Apply base flags for non-fuzzing builds
38+
add_compile_options(${BASE_FLAGS})
39+
add_link_options(${BASE_FLAGS})
40+
endif()
41+
42+
set(CMAKE_CONFIG_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_LIST_DIR}/cmake")
43+
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CONFIG_PATH}")
44+
45+
set(BTCPP_LIBRARY ${PROJECT_NAME})
46+
47+
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
48+
message(STATUS "Setting build type to 'Release' as none was specified.")
49+
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build." FORCE)
50+
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
51+
"Debug" "Release" "MinSizeRel" "RelWithDebInfo")
52+
endif()
53+
54+
if(MSVC)
55+
add_definitions(-D_CRT_SECURE_NO_WARNINGS -DWIN32_LEAN_AND_MEAN)
56+
else()
57+
add_definitions(-Wpedantic -fno-omit-frame-pointer)
58+
endif()
3859

3960
if(USE_V3_COMPATIBLE_NAMES)
4061
add_definitions(-DUSE_BTCPP3_OLD_NAMES)
@@ -189,20 +210,29 @@ target_compile_definitions(${BTCPP_LIBRARY} PUBLIC BTCPP_LIBRARY_VERSION="${CMAK
189210
target_compile_features(${BTCPP_LIBRARY} PUBLIC cxx_std_17)
190211

191212
if(MSVC)
192-
target_compile_options(${BTCPP_LIBRARY} PRIVATE "/source-charset:utf-8")
213+
target_compile_options(${BTCPP_LIBRARY} PRIVATE "/source-charset:utf-8")
193214
else()
194-
target_compile_options(${BTCPP_LIBRARY} PRIVATE -Wall -Wextra)
215+
if(ENABLE_DEBUG)
216+
target_compile_options(${BTCPP_LIBRARY} PRIVATE -Wall -Wextra -g3 -ggdb3 -O0 -fno-omit-frame-pointer)
217+
else()
218+
target_compile_options(${BTCPP_LIBRARY} PRIVATE -Wall -Wextra)
219+
endif()
195220
endif()
196221

197222
add_library(BT::${BTCPP_LIBRARY} ALIAS ${BTCPP_LIBRARY})
198223

224+
# Add fuzzing targets
225+
if(ENABLE_FUZZING)
226+
add_fuzzing_targets()
227+
endif()
228+
199229
#############################################################
200230
message( STATUS "BTCPP_LIB_DESTINATION: ${BTCPP_LIB_DESTINATION} " )
201231
message( STATUS "BTCPP_INCLUDE_DESTINATION: ${BTCPP_INCLUDE_DESTINATION} " )
202232
message( STATUS "BTCPP_UNIT_TESTS: ${BTCPP_UNIT_TESTS} " )
203233

204234
if (BTCPP_UNIT_TESTS OR BTCPP_EXAMPLES)
205-
add_subdirectory(sample_nodes)
235+
add_subdirectory(sample_nodes)
206236
endif()
207237

208238
######################################################

cmake/fuzzing_build.cmake

+153
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
# Fuzzing configuration
2+
# Supports both local fuzzing and OSS-Fuzz integration
3+
4+
# Detect if we're running in OSS-Fuzz environment
5+
if(DEFINED ENV{LIB_FUZZING_ENGINE})
6+
set(OSS_FUZZ ON)
7+
message(STATUS "OSS-Fuzz environment detected")
8+
else()
9+
set(OSS_FUZZ OFF)
10+
endif()
11+
12+
# Auto-detect AFL++ compiler if not in OSS-Fuzz mode
13+
if(NOT OSS_FUZZ AND (CMAKE_C_COMPILER MATCHES ".*afl-.*" OR CMAKE_CXX_COMPILER MATCHES ".*afl-.*"))
14+
set(USE_AFLPLUSPLUS ON CACHE BOOL "Use AFL++ instead of libFuzzer" FORCE)
15+
message(STATUS "AFL++ compiler detected - automatically enabling AFL++ mode")
16+
endif()
17+
18+
# When building for fuzzing, we want static library by default
19+
set(BTCPP_SHARED_LIBS OFF CACHE BOOL "Build static library for fuzzing" FORCE)
20+
21+
# Only apply static linking settings if explicitly requested
22+
if(FORCE_STATIC_LINKING)
23+
set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
24+
set(BUILD_SHARED_LIBS OFF)
25+
26+
# Force static linking for dependencies
27+
if(BTCPP_GROOT_INTERFACE)
28+
set(ZeroMQ_USE_STATIC_LIBS ON)
29+
set(ZEROMQ_STATIC_LIBRARY ON)
30+
endif()
31+
32+
if(BTCPP_SQLITE_LOGGING)
33+
set(SQLite3_USE_STATIC_LIBS ON)
34+
endif()
35+
endif()
36+
37+
# Set up flags for local fuzzing (not used for OSS-Fuzz)
38+
if(NOT OSS_FUZZ)
39+
list(APPEND BASE_FLAGS -O2)
40+
41+
if(USE_AFLPLUSPLUS)
42+
set(SANITIZER_FLAGS
43+
-fsanitize=address,undefined
44+
)
45+
else()
46+
# For libFuzzer, use fuzzer-no-link for the library
47+
set(SANITIZER_FLAGS
48+
-fsanitize=address,undefined,fuzzer-no-link
49+
)
50+
endif()
51+
52+
# Apply sanitizer flags to the base library
53+
list(APPEND BASE_FLAGS ${SANITIZER_FLAGS})
54+
55+
add_compile_options(${BASE_FLAGS})
56+
add_link_options(${BASE_FLAGS})
57+
endif()
58+
59+
# Disable certain features during fuzzing
60+
set(BTCPP_EXAMPLES OFF CACHE BOOL "Disable examples during fuzzing" FORCE)
61+
set(BTCPP_BUILD_TOOLS OFF CACHE BOOL "Disable tools during fuzzing" FORCE)
62+
set(BTCPP_UNIT_TESTS OFF CACHE BOOL "Disable tests during fuzzing" FORCE)
63+
set(BTCPP_SHARED_LIBS OFF CACHE BOOL "Build static library for fuzzing" FORCE)
64+
65+
# Function to apply fuzzing flags for local development builds
66+
function(apply_local_fuzzing_flags target)
67+
target_compile_options(${target} PRIVATE
68+
${BASE_FLAGS}
69+
${SANITIZER_FLAGS}
70+
)
71+
72+
if(FORCE_STATIC_LINKING)
73+
if(USE_AFLPLUSPLUS)
74+
target_link_options(${target} PRIVATE
75+
${BASE_FLAGS}
76+
${SANITIZER_FLAGS}
77+
-static-libstdc++
78+
-static-libgcc
79+
-fsanitize=fuzzer
80+
)
81+
else()
82+
target_link_options(${target} PRIVATE
83+
${BASE_FLAGS}
84+
-fsanitize=fuzzer
85+
${SANITIZER_FLAGS}
86+
-static-libstdc++
87+
-static-libgcc
88+
)
89+
endif()
90+
else()
91+
if(USE_AFLPLUSPLUS)
92+
target_link_options(${target} PRIVATE
93+
${BASE_FLAGS}
94+
${SANITIZER_FLAGS}
95+
-fsanitize=fuzzer
96+
)
97+
else()
98+
target_link_options(${target} PRIVATE
99+
${BASE_FLAGS}
100+
-fsanitize=fuzzer
101+
${SANITIZER_FLAGS}
102+
)
103+
endif()
104+
endif()
105+
endfunction()
106+
107+
# Function to add fuzzing targets - compatible with both local and OSS-Fuzz builds
108+
function(add_fuzzing_targets)
109+
set(FUZZERS bt_fuzzer script_fuzzer bb_fuzzer)
110+
111+
foreach(fuzzer ${FUZZERS})
112+
add_executable(${fuzzer} fuzzing/${fuzzer}.cpp)
113+
114+
if(OSS_FUZZ)
115+
# For OSS-Fuzz environment, we rely on environment variables
116+
# like $CC, $CXX, $CFLAGS, $CXXFLAGS, and $LIB_FUZZING_ENGINE
117+
target_link_libraries(${fuzzer} PRIVATE
118+
${BTCPP_LIBRARY}
119+
${BTCPP_EXTRA_LIBRARIES}
120+
$ENV{LIB_FUZZING_ENGINE}
121+
)
122+
else()
123+
# For local development, use our own flags
124+
apply_local_fuzzing_flags(${fuzzer})
125+
target_link_libraries(${fuzzer} PRIVATE
126+
${BTCPP_LIBRARY}
127+
${BTCPP_EXTRA_LIBRARIES}
128+
)
129+
endif()
130+
131+
# Setup corpus directories (useful for both environments)
132+
set(CORPUS_DIR ${CMAKE_BINARY_DIR}/corpus/${fuzzer})
133+
file(MAKE_DIRECTORY ${CORPUS_DIR})
134+
endforeach()
135+
136+
# Copy corpus files if they exist (useful for local testing)
137+
# OSS-Fuzz provides its own corpus handling
138+
if(NOT OSS_FUZZ)
139+
file(GLOB BT_CORPUS_FILES "${CMAKE_SOURCE_DIR}/fuzzing/corpus/bt_corpus/*")
140+
file(GLOB SCRIPT_CORPUS_FILES "${CMAKE_SOURCE_DIR}/fuzzing/corpus/script_corpus/*")
141+
file(GLOB BB_CORPUS_FILES "${CMAKE_SOURCE_DIR}/fuzzing/corpus/bb_corpus/*")
142+
143+
if(BT_CORPUS_FILES)
144+
file(COPY ${BT_CORPUS_FILES} DESTINATION ${CMAKE_BINARY_DIR}/corpus/bt_fuzzer)
145+
endif()
146+
if(SCRIPT_CORPUS_FILES)
147+
file(COPY ${SCRIPT_CORPUS_FILES} DESTINATION ${CMAKE_BINARY_DIR}/corpus/script_fuzzer)
148+
endif()
149+
if(BB_CORPUS_FILES)
150+
file(COPY ${BB_CORPUS_FILES} DESTINATION ${CMAKE_BINARY_DIR}/corpus/bb_fuzzer)
151+
endif()
152+
endif()
153+
endfunction()

fuzzing/README.md

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Fuzzing BehaviorTree.CPP
2+
3+
You can build the existing harnesses either for libfuzzer or AFL++.
4+
Building the fuzzers requires `clang` (libfuzzer) or an installed version
5+
of [AFL++](https://github.com/AFLplusplus/AFLplusplus).
6+
7+
## libfuzzer
8+
9+
```bash
10+
mkdir build_libfuzzer && cd build_libfuzzer
11+
cmake -DENABLE_FUZZING=ON ..
12+
```
13+
14+
## AFL++
15+
16+
```bash
17+
export CC=afl-clang-fast
18+
export CXX=afl-clang-fast++
19+
mkdir build_afl && cd build_afl
20+
cmake -DENABLE_FUZZING=ON -DUSE_AFLPLUSPLUS=ON ..
21+
```

0 commit comments

Comments
 (0)