Skip to content

Commit ee9762e

Browse files
committed
CI runs fuzzers
1 parent 1b87492 commit ee9762e

File tree

5 files changed

+188
-1
lines changed

5 files changed

+188
-1
lines changed

.github/workflows/ci.yml renamed to .github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: CI
1+
name: build
22

33
on: [push, pull_request]
44

.github/workflows/fuzz.yml

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
name: fuzz
2+
3+
on:
4+
push:
5+
pull_request:
6+
workflow_dispatch:
7+
schedule:
8+
- cron: "25 00 * * *"
9+
10+
jobs:
11+
fuzz:
12+
runs-on: ubuntu-24.04
13+
steps:
14+
- uses: actions/checkout@v3
15+
16+
- name: Install packages
17+
run: |
18+
sudo apt-get update
19+
sudo apt-get install -y clang
20+
21+
- name: Setup Boost
22+
run: |
23+
echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY
24+
LIBRARY=${GITHUB_REPOSITORY#*/}
25+
echo LIBRARY: $LIBRARY
26+
echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV
27+
echo GITHUB_BASE_REF: $GITHUB_BASE_REF
28+
echo GITHUB_REF: $GITHUB_REF
29+
REF=${GITHUB_BASE_REF:-$GITHUB_REF}
30+
REF=${REF#refs/heads/}
31+
echo REF: $REF
32+
BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true
33+
echo BOOST_BRANCH: $BOOST_BRANCH
34+
cd ..
35+
git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
36+
cd boost-root
37+
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
38+
git submodule update --init tools/boostdep
39+
python3 tools/boostdep/depinst/depinst.py $LIBRARY
40+
./bootstrap.sh
41+
./b2
42+
43+
- name: Fuzz corpus
44+
uses: actions/[email protected]
45+
id: cache-corpus
46+
with:
47+
path: ${{ github.workspace }}/corpus.tar
48+
key: corpus-${{ github.run_id }}
49+
enableCrossOsArchive: true
50+
restore-keys: |
51+
corpus-
52+
53+
- name: Run fuzzer
54+
run: |
55+
cd ../boost-root/libs/beast
56+
mkdir build
57+
cd build
58+
cmake \
59+
-DCMAKE_CXX_COMPILER=clang++ \
60+
-DCMAKE_C_COMPILER=clang \
61+
-DBeast_BUILD_TESTS=ON \
62+
-DBeast_BUILD_FUZZERS=ON \
63+
-DBOOST_BEAST_FUZZER_CORPUS_PATH=${{ github.workspace }}/corpus.tar ..
64+
make boost_beast_fuzz_all

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ project (Beast VERSION 354)
8888
set_property (GLOBAL PROPERTY USE_FOLDERS ON)
8989
option (Beast_BUILD_EXAMPLES "Build examples" ON)
9090
option (Beast_BUILD_TESTS "Build tests" ${BUILD_TESTING})
91+
option (Beast_BUILD_FUZZERS "Build fuzzers" OFF)
9192
option (Beast_ENABLE_HANDLER_TRACKING "Define BOOST_ASIO_ENABLE_HANDLER_TRACKING when building libraries" OFF)
9293
option (Boost_USE_STATIC_LIBS "Use Static Boost libraries" ON)
9394

test/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,6 @@ add_subdirectory (beast)
7171
add_subdirectory (bench)
7272
add_subdirectory (doc)
7373
add_subdirectory (example)
74+
if (Beast_BUILD_FUZZERS AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
75+
add_subdirectory(fuzz)
76+
endif()

test/fuzz/CMakeLists.txt

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
#
2+
# Copyright (c) 2023 Alan de Freitas ([email protected])
3+
# Copyright (c) 2024 Mohammad Nejati
4+
#
5+
# Distributed under the Boost Software License, Version 1.0.
6+
# https://www.boost.org/LICENSE_1_0.txt
7+
#
8+
9+
# Get number of cores
10+
include(ProcessorCount)
11+
ProcessorCount(PROCESSOR_COUNT)
12+
13+
# Determine total fuzz time per file
14+
file(GLOB BOOST_BEAST_FUZZER_SOURCE_FILES *.cpp)
15+
list(LENGTH BOOST_BEAST_FUZZER_SOURCE_FILES BOOST_BEAST_FUZZER_SOURCE_FILES_COUNT)
16+
set(BOOST_BEAST_FUZZER_TOTAL_TIME_DEFAULT 300)
17+
math(EXPR BOOST_BEAST_FUZZER_TOTAL_TIME_DEFAULT "${BOOST_BEAST_FUZZER_TOTAL_TIME_DEFAULT} / (${PROCESSOR_COUNT} * ${BOOST_BEAST_FUZZER_SOURCE_FILES_COUNT}) + 1")
18+
19+
# Fuzzing options
20+
set(BOOST_BEAST_FUZZER_TOTAL_TIME ${BOOST_BEAST_FUZZER_TOTAL_TIME_DEFAULT} CACHE STRING "Total time for fuzzing")
21+
set(BOOST_BEAST_FUZZER_RSS_LIMIT 8192 CACHE STRING "RSS limit for fuzzing")
22+
set(BOOST_BEAST_FUZZER_TIMEOUT 30 CACHE STRING "Timeout for fuzzing")
23+
set(BOOST_BEAST_FUZZER_MAX_LEN 4000 CACHE STRING "Maximum size of the input")
24+
set(BOOST_BEAST_FUZZER_JOBS ${PROCESSOR_COUNT} CACHE STRING "Number of jobs for fuzzing")
25+
option(BOOST_BEAST_FUZZER_ADD_TO_CTEST "Add fuzzing targets to ctest" OFF)
26+
set(BOOST_BEAST_FUZZER_CORPUS_PATH ${CMAKE_CURRENT_BINARY_DIR}/corpus.tar CACHE STRING "Path to corpus.tar")
27+
28+
# Corpus
29+
set(BOOST_BEAST_FUZZER_SEEDS_PATH ${CMAKE_CURRENT_SOURCE_DIR}/seeds.tar)
30+
set(BOOST_BEAST_FUZZER_SEEDS_DIR ${CMAKE_CURRENT_BINARY_DIR}/seeds)
31+
get_filename_component(BOOST_BEAST_FUZZER_SEEDS_PARENT_DIR ${BOOST_BEAST_FUZZER_SEEDS_DIR} DIRECTORY)
32+
add_custom_target(
33+
untar_seeds
34+
COMMAND ${CMAKE_COMMAND} -E echo "Untar fuzz seeds from ${BOOST_BEAST_FUZZER_SEEDS_PATH} to ${BOOST_BEAST_FUZZER_SEEDS_PARENT_DIR}/seeds"
35+
COMMAND ${CMAKE_COMMAND} -E tar xf ${BOOST_BEAST_FUZZER_SEEDS_PATH}
36+
WORKING_DIRECTORY ${BOOST_BEAST_FUZZER_SEEDS_PARENT_DIR}
37+
COMMENT "Unzipping fuzz seeds"
38+
VERBATIM)
39+
40+
set(BOOST_BEAST_FUZZER_CORPUS_DIR ${CMAKE_CURRENT_BINARY_DIR}/corpus)
41+
set(BOOST_BEAST_FUZZER_MERGED_CORPUS_DIR ${CMAKE_CURRENT_BINARY_DIR}/merged-corpus)
42+
if(EXISTS ${BOOST_BEAST_FUZZER_CORPUS_PATH})
43+
add_custom_target(
44+
untar_corpus
45+
COMMAND ${CMAKE_COMMAND} -E echo "Untar fuzz corpus archive from \"${BOOST_BEAST_FUZZER_CORPUS_PATH}\" to \"${CMAKE_CURRENT_BINARY_DIR}/corpus\""
46+
COMMAND ${CMAKE_COMMAND} -E tar xf ${BOOST_BEAST_FUZZER_CORPUS_PATH}
47+
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
48+
COMMENT "Unzipping fuzz corpus"
49+
VERBATIM)
50+
else()
51+
add_custom_target(untar_corpus
52+
COMMAND ${CMAKE_COMMAND} -E echo "No fuzz corpus archive in ${BOOST_BEAST_FUZZER_CORPUS_PATH}. Create empty fuzz corpus dir \"${BOOST_BEAST_FUZZER_CORPUS_DIR}.\""
53+
COMMAND ${CMAKE_COMMAND} -E make_directory ${BOOST_BEAST_FUZZER_CORPUS_DIR}
54+
COMMENT "Creating fuzz corpus directory"
55+
VERBATIM)
56+
endif()
57+
add_dependencies(untar_corpus untar_seeds)
58+
59+
# Target that runs all fuzz targets
60+
get_filename_component(BOOST_BEAST_FUZZER_CORPUS_PARENT_DIR ${BOOST_BEAST_FUZZER_CORPUS_PATH} DIRECTORY)
61+
add_custom_target(
62+
boost_beast_fuzz_all
63+
COMMAND ${CMAKE_COMMAND} -E echo "Archive corpus from \"${BOOST_BEAST_FUZZER_CORPUS_DIR}\" to \"${BOOST_BEAST_FUZZER_CORPUS_PATH}\""
64+
COMMAND ${CMAKE_COMMAND} -E tar cf ${BOOST_BEAST_FUZZER_CORPUS_PATH} ${BOOST_BEAST_FUZZER_CORPUS_DIR}
65+
WORKING_DIRECTORY ${BOOST_BEAST_FUZZER_CORPUS_PARENT_DIR}
66+
VERBATIM)
67+
68+
# Register a single fuzzer and add as dependency to fuzz target
69+
function(add_boost_beast_fuzzer NAME)
70+
# Fuzzer executable
71+
set(SOURCE_FILES ${ARGN})
72+
add_executable(fuzzer_${NAME} ${SOURCE_FILES})
73+
target_link_libraries(fuzzer_${NAME} PRIVATE lib-beast)
74+
target_compile_options(fuzzer_${NAME} PRIVATE -g -O2 -fsanitize=fuzzer,address,undefined -fno-sanitize-recover=undefined)
75+
target_link_libraries(fuzzer_${NAME} PRIVATE -fsanitize=fuzzer,address,undefined)
76+
set_property(TARGET fuzzer_${NAME} PROPERTY FOLDER "fuzzing")
77+
78+
# Custom target to run fuzzer executable
79+
add_custom_target(
80+
fuzz_${NAME}
81+
ALL
82+
COMMAND ${CMAKE_COMMAND} -E make_directory ${BOOST_BEAST_FUZZER_CORPUS_DIR}/${NAME}
83+
COMMAND ${CMAKE_COMMAND} -E echo "Running fuzzer ${NAME} with corpus from ${BOOST_BEAST_FUZZER_CORPUS_DIR}/${NAME} and seeds from ${BOOST_BEAST_FUZZER_SEEDS_DIR}/${NAME}"
84+
COMMAND
85+
fuzzer_${NAME}
86+
-rss_limit_mb=${BOOST_BEAST_FUZZER_RSS_LIMIT}
87+
-max_total_time=${BOOST_BEAST_FUZZER_TOTAL_TIME}
88+
-timeout=${BOOST_BEAST_FUZZER_TIMEOUT}
89+
-max_len=${BOOST_BEAST_FUZZER_MAX_LEN}
90+
-jobs=${BOOST_BEAST_FUZZER_JOBS}
91+
${BOOST_BEAST_FUZZER_CORPUS_DIR}/${NAME}
92+
${BOOST_BEAST_FUZZER_SEEDS_DIR}/${NAME}
93+
COMMAND ${CMAKE_COMMAND} -E make_directory ${BOOST_BEAST_FUZZER_MERGED_CORPUS_DIR}/${NAME}
94+
COMMAND ${CMAKE_COMMAND} -E echo "Merging corpus from ${BOOST_BEAST_FUZZER_CORPUS_DIR}/${NAME} to ${BOOST_BEAST_FUZZER_MERGED_CORPUS_DIR}/${NAME}"
95+
COMMAND
96+
fuzzer_${NAME}
97+
-merge=1
98+
${BOOST_BEAST_FUZZER_MERGED_CORPUS_DIR}/${NAME}
99+
${BOOST_BEAST_FUZZER_CORPUS_DIR}/${NAME}
100+
${BOOST_BEAST_FUZZER_SEEDS_DIR}/${NAME}
101+
COMMAND ${CMAKE_COMMAND} -E echo "Replacing corpus in ${BOOST_BEAST_FUZZER_CORPUS_DIR}/${NAME} with merged corpus from ${BOOST_BEAST_FUZZER_MERGED_CORPUS_DIR}/${NAME}"
102+
COMMAND ${CMAKE_COMMAND} -E remove_directory ${BOOST_BEAST_FUZZER_CORPUS_DIR}/${NAME}
103+
COMMAND ${CMAKE_COMMAND} -E make_directory ${BOOST_BEAST_FUZZER_CORPUS_DIR}/${NAME}
104+
COMMAND ${CMAKE_COMMAND} -E copy_directory ${BOOST_BEAST_FUZZER_MERGED_CORPUS_DIR}/${NAME} ${BOOST_BEAST_FUZZER_CORPUS_DIR}/${NAME}
105+
COMMAND ${CMAKE_COMMAND} -E remove_directory ${BOOST_BEAST_FUZZER_MERGED_CORPUS_DIR}/${NAME}
106+
DEPENDS untar_corpus fuzzer_${NAME})
107+
add_dependencies(fuzz_${NAME} fuzzer_${NAME})
108+
add_dependencies(boost_beast_fuzz_all fuzz_${NAME})
109+
set_property(TARGET fuzz_${NAME} PROPERTY ENVIRONMENT "UBSAN_OPTIONS=halt_on_error=false")
110+
endfunction()
111+
112+
# Register all fuzzers
113+
file(GLOB BOOST_BEAST_FUZZER_SOURCE_FILES *.cpp)
114+
source_group("" FILES ${BOOST_BEAST_FUZZER_SOURCE_FILES})
115+
foreach(BOOST_BEAST_FUZZER_SOURCE_FILE ${BOOST_BEAST_FUZZER_SOURCE_FILES})
116+
file(RELATIVE_PATH BOOST_BEAST_FUZZER_SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR} ${BOOST_BEAST_FUZZER_SOURCE_FILE})
117+
string(REGEX REPLACE "(.*).cpp" "\\1" RULE_NAME ${BOOST_BEAST_FUZZER_SOURCE_FILE})
118+
add_boost_beast_fuzzer(${RULE_NAME} ${BOOST_BEAST_FUZZER_SOURCE_FILE})
119+
endforeach()

0 commit comments

Comments
 (0)