mirror of
https://github.com/boostorg/url.git
synced 2026-01-19 04:42:15 +00:00
committed by
Alan de Freitas
parent
33cfb939d0
commit
516e0093c5
109
.github/actions/build/action.yml
vendored
109
.github/actions/build/action.yml
vendored
@@ -1,109 +0,0 @@
|
||||
name: Run and build
|
||||
description: Build the project
|
||||
|
||||
inputs:
|
||||
toolset:
|
||||
description: B2 toolset module to use
|
||||
required: true
|
||||
version:
|
||||
description: B2 toolset version to use
|
||||
required: false
|
||||
default: ''
|
||||
comment:
|
||||
description: Human-readable job description
|
||||
required: false
|
||||
default: ''
|
||||
path:
|
||||
description: Path to project root
|
||||
required: false
|
||||
default: ''
|
||||
buildtype:
|
||||
description: Build type
|
||||
required: false
|
||||
default: ''
|
||||
cxxstd:
|
||||
description: C++ standard versions to use (separated by commas)
|
||||
required: false
|
||||
default: ''
|
||||
defines:
|
||||
description: Macro definitions to use (separated by commas)
|
||||
required: false
|
||||
default: ''
|
||||
variant:
|
||||
description: B2 build variant to use
|
||||
required: false
|
||||
default: release
|
||||
testflags:
|
||||
description: B2 test properties to set
|
||||
required: false
|
||||
default: ''
|
||||
targets:
|
||||
description: B2 targets to build (separated by spaces)
|
||||
required: false
|
||||
default: ''
|
||||
b2_flags:
|
||||
description: Extra B2 flags to use
|
||||
required: false
|
||||
default: 'warnings=extra warnings-as-errors=on'
|
||||
valgrind_options:
|
||||
description: Valgrind options to use
|
||||
required: false
|
||||
default: ''
|
||||
asan:
|
||||
description: Use '1' to enable address sanitizer
|
||||
required: false
|
||||
default: ''
|
||||
ubsan:
|
||||
description: Use '1' to enable UB sanitizer
|
||||
required: false
|
||||
default: ''
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Setup environment variables
|
||||
shell: bash
|
||||
run: |
|
||||
B2_TOOLSET=${{ inputs.toolset }}
|
||||
case $B2_TOOLSET in
|
||||
gcc) CXX=g++ ;;
|
||||
clang) CXX=clang++ ;;
|
||||
*) CXX=$B2_TOOLSET ;;
|
||||
esac
|
||||
if [ -n "${{ inputs.version }}" ]; then
|
||||
B2_TOOLSET=$B2_TOOLSET-${{ inputs.version }}
|
||||
CXX=$CXX-${{ inputs.version }}
|
||||
fi
|
||||
|
||||
echo "CXX=$CXX" >> $GITHUB_ENV
|
||||
echo "COMMENT=${{ inputs.comment }}" >> $GITHUB_ENV
|
||||
echo "LCOV_BRANCH_COVERAGE=$LCOV_BRANCH_COVERAGE" >> $GITHUB_ENV
|
||||
echo "B2_CI_VERSION=1" >> $GITHUB_ENV
|
||||
echo "B2_CXXSTD=${{ inputs.cxxstd }}" >> $GITHUB_ENV
|
||||
echo "B2_TOOLSET=$B2_TOOLSET" >> $GITHUB_ENV
|
||||
echo "B2_DEFINES=${{ inputs.defines }}" >> $GITHUB_ENV
|
||||
echo "B2_VARIANT=${{ inputs.variant }}" >> $GITHUB_ENV
|
||||
echo "B2_TESTFLAGS=${{ inputs.testflags }}" >> $GITHUB_ENV
|
||||
echo "VALGRIND_OPTS=${{ inputs.valgrind_opts }}" >> $GITHUB_ENV
|
||||
echo "B2_ASAN=${{ inputs.asan }}" >> $GITHUB_ENV
|
||||
echo "B2_UBSAN=${{ inputs.ubsan }}" >> $GITHUB_ENV
|
||||
echo "B2_TARGETS=${{ inputs.targets }}" >> $GITHUB_ENV
|
||||
echo "B2_FLAGS=${{ inputs.b2_flags }}" >> $GITHUB_ENV
|
||||
echo "DRONE_BUILD_EVENT=${{ github.event_name }}" >> $GITHUB_ENV
|
||||
echo "DRONE_JOB_BUILDTYPE=${{ inputs.buildtype }}" >> $GITHUB_ENV
|
||||
echo "DRONE_COMMIT=${{ github.sha }}" >> $GITHUB_ENV
|
||||
echo "DRONE_BRANCH=${{ github.base_ref }}" >> $GITHUB_ENV
|
||||
echo "DRONE_REPO=${{ github.repository }}" >> $GITHUB_ENV
|
||||
|
||||
- name: linux
|
||||
if: runner.os == 'Linux'
|
||||
shell: bash
|
||||
run: . .drone/drone.sh
|
||||
working-directory: ${{ inputs.path }}
|
||||
|
||||
- name: windows
|
||||
if: runner.os == 'Windows'
|
||||
shell: cmd
|
||||
run: call .drone/drone.bat
|
||||
working-directory: ${{ inputs.path }}
|
||||
|
||||
35
.github/workflows/ci.yml
vendored
35
.github/workflows/ci.yml
vendored
@@ -69,7 +69,7 @@ jobs:
|
||||
factors: |
|
||||
gcc Asan Shared No-Threads
|
||||
msvc Shared x86
|
||||
clang Time-Trace
|
||||
clang Time-Trace Fuzz
|
||||
mingw Shared
|
||||
trace-commands: true
|
||||
|
||||
@@ -120,19 +120,42 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
set -xe
|
||||
# Identify boost module being tested
|
||||
module=${GITHUB_REPOSITORY#*/}
|
||||
echo "module=$module" >> $GITHUB_OUTPUT
|
||||
|
||||
# Identify GitHub workspace root
|
||||
workspace_root=$(echo "$GITHUB_WORKSPACE" | sed 's/\\/\//g')
|
||||
echo -E "workspace_root=$workspace_root" >> $GITHUB_OUTPUT
|
||||
|
||||
# Remove module from boost-source
|
||||
rm -r "libs/$module" || true
|
||||
cd ..
|
||||
|
||||
# Copy cached boost-source to an isolated boost-root
|
||||
mkdir boost-root || true
|
||||
cp -r "boost-source"/* "boost-root"
|
||||
|
||||
# Set boost-root output
|
||||
cd boost-root
|
||||
boost_root="$(pwd)"
|
||||
boost_root=$(echo "$boost_root" | sed 's/\\/\//g')
|
||||
echo -E "boost_root=$boost_root" >> $GITHUB_OUTPUT
|
||||
|
||||
# Patch boost-root with workspace module
|
||||
mkdir "libs/$module"
|
||||
cp -r "$workspace_root"/* "libs/$module"
|
||||
cxxstd=${{ matrix.cxxstd }}
|
||||
latest_std=$(echo $cxxstd | awk -F ',' '{print $NF}')
|
||||
echo "latest_std=$latest_std" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Fuzz corpus
|
||||
if: ${{ matrix.fuzz }}
|
||||
uses: actions/cache@v3.3.1
|
||||
id: cache-corpus
|
||||
with:
|
||||
path: ${{ steps.patch.outputs.workspace_root }}/corpus.tar
|
||||
key: corpus-${{ github.run_id }}
|
||||
enableCrossOsArchive: true
|
||||
restore-keys: |
|
||||
corpus-
|
||||
|
||||
- name: Boost CMake Workflow
|
||||
uses: alandefreitas/cpp-actions/cmake-workflow@v1.5.0
|
||||
@@ -141,7 +164,7 @@ jobs:
|
||||
build-dir: __build_cmake_test__
|
||||
generator: ${{ matrix.generator }}
|
||||
build-type: ${{ matrix.build-type }}
|
||||
build-target: tests boost_url_tests boost_url_limits boost_url_extra
|
||||
build-target: tests boost_url_tests boost_url_limits boost_url_extra ${{ (matrix.fuzz && 'fuzz') || ''}}
|
||||
run-tests: true
|
||||
install-prefix: $GITHUB_WORKSPACE/.local
|
||||
cxxstd: ${{ matrix.latest-cxxstd }}
|
||||
@@ -151,7 +174,7 @@ jobs:
|
||||
cxxflags: ${{ matrix.cxxflags }}
|
||||
shared: ${{ matrix.shared }}
|
||||
cmake-version: '>=3.15'
|
||||
extra-args: ${{ format('-D Boost_VERBOSE=ON -D BOOST_INCLUDE_LIBRARIES={0} -D BOOST_URL_DISABLE_THREADS={1}', steps.patch.outputs.module, ( matrix.no-threads && 'ON' ) || 'OFF') }}
|
||||
extra-args: -D Boost_VERBOSE=ON -D BOOST_INCLUDE_LIBRARIES=${{ steps.patch.outputs.module }} -D BOOST_URL_DISABLE_THREADS=${{ ( matrix.no-threads && 'ON' ) || 'OFF' }} -D BOOST_URL_BUILD_FUZZERS=${{ ( matrix.fuzz && format('ON -D BOOST_URL_FUZZER_CORPUS_PATH={0}/corpus.tar', steps.patch.outputs.workspace_root) ) || 'OFF' }}
|
||||
export-compile-commands: ${{ matrix.time-trace }}
|
||||
package: false
|
||||
package-artifact: false
|
||||
|
||||
54
.github/workflows/run_fuzzer.yml
vendored
54
.github/workflows/run_fuzzer.yml
vendored
@@ -1,54 +0,0 @@
|
||||
name: fuzz
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: "25 */12 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
fuzz:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Fetch head
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: 'head'
|
||||
- name: Restore corpus
|
||||
uses: actions/cache@v3
|
||||
id: cache-corpus
|
||||
with:
|
||||
path: head/test/fuzz/corpus.tar
|
||||
key: corpus-${{ github.run_id }}
|
||||
restore-keys: corpus-
|
||||
- name: Unzip corpus
|
||||
if: steps.cache-corpus.outputs.cache-hit == 'true'
|
||||
working-directory: head/test/fuzz/
|
||||
run: |
|
||||
tar -vxf corpus.tar
|
||||
- name: Build boost and run fuzzer
|
||||
uses: ./head/.github/actions/build
|
||||
with:
|
||||
buildtype: 'boost'
|
||||
path: 'head'
|
||||
toolset: clang
|
||||
targets: libs/url/test/fuzz//run
|
||||
- name: Pack the corpus
|
||||
working-directory: boost-root/libs/url/test/fuzz/
|
||||
run: |
|
||||
tar cf - cmin > corpus.tar.tmp
|
||||
mv corpus.tar.tmp "${GITHUB_WORKSPACE}"/head/test/fuzz/corpus.tar
|
||||
- name: Archive any crashes as an artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: crashes
|
||||
path: |
|
||||
boost-root/crash-*
|
||||
boost-root/leak-*
|
||||
boost-root/timeout-*
|
||||
if-no-files-found: ignore
|
||||
|
||||
@@ -1,30 +1,130 @@
|
||||
#
|
||||
# Copyright (c) 2023 alandefreitas (alandefreitas@gmail.com)
|
||||
# Copyright (c) 2023 Alan de Freitas (alandefreitas@gmail.com)
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# https://www.boost.org/LICENSE_1_0.txt
|
||||
#
|
||||
|
||||
# Files
|
||||
source_group("" FILES fuzz_parse.cpp)
|
||||
# Get number of cores
|
||||
include(ProcessorCount)
|
||||
ProcessorCount(PROCESSOR_COUNT)
|
||||
|
||||
function(add_boost_url_fuzzer NAME SOURCE_FILES)
|
||||
# Fuzzer library
|
||||
add_library(fuzzerlib_${NAME} ${SOURCE_FILES})
|
||||
target_link_libraries(fuzzerlib_${NAME} PRIVATE Boost::url)
|
||||
set_property(TARGET fuzzerlib_${NAME} PROPERTY FOLDER "fuzzing")
|
||||
# Determine total fuzz time per file
|
||||
file(GLOB BOOST_URL_FUZZER_SOURCE_FILES *.cpp)
|
||||
list(LENGTH BOOST_URL_FUZZER_SOURCE_FILES BOOST_URL_FUZZER_SOURCE_FILES_COUNT)
|
||||
set(BOOST_URL_FUZZER_TOTAL_TIME_DEFAULT 30)
|
||||
math(EXPR BOOST_URL_FUZZER_TOTAL_TIME_DEFAULT "${BOOST_URL_FUZZER_TOTAL_TIME_DEFAULT} / (${PROCESSOR_COUNT} * ${BOOST_URL_FUZZER_SOURCE_FILES_COUNT}) + 1")
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
# Fuzzer executable
|
||||
add_executable(fuzzer_${NAME} ${SOURCE_FILES})
|
||||
target_link_libraries(fuzzer_${NAME} PRIVATE Boost::url)
|
||||
target_compile_options(fuzzer_${NAME} PRIVATE -g -O2 -fsanitize=fuzzer,address,undefined -fno-sanitize-recover=undefined)
|
||||
target_link_libraries(fuzzer_${NAME} PRIVATE -fsanitize=fuzzer -fuse-ld=lld)
|
||||
# Fuzzing options
|
||||
set(BOOST_URL_FUZZER_TOTAL_TIME ${BOOST_URL_FUZZER_TOTAL_TIME_DEFAULT} CACHE STRING "Total time for fuzzing")
|
||||
set(BOOST_URL_FUZZER_RSS_LIMIT 8192 CACHE STRING "RSS limit for fuzzing")
|
||||
set(BOOST_URL_FUZZER_TIMEOUT 30 CACHE STRING "Timeout for fuzzing")
|
||||
set(BOOST_URL_FUZZER_MAX_LEN 4000 CACHE STRING "Maximum size of the input")
|
||||
set(BOOST_URL_FUZZER_JOBS ${PROCESSOR_COUNT} CACHE STRING "Number of jobs for fuzzing")
|
||||
option(BOOST_URL_FUZZER_ADD_TO_CTEST "Add fuzzing targets to ctest" OFF)
|
||||
set(BOOST_URL_FUZZER_CORPUS_PATH ${CMAKE_CURRENT_BINARY_DIR}/corpus.tar CACHE STRING "Path to corpus.tar")
|
||||
|
||||
# Custom target to run fuzzer executable
|
||||
add_custom_target(fuzz_${NAME} fuzzer_${NAME} -rss_limit_mb=8192 -max_total_time=30 -timeout=30 DEPENDS fuzz_${NAME})
|
||||
set_property(TARGET fuzzer_${NAME} PROPERTY FOLDER "fuzzing")
|
||||
endif ()
|
||||
# Corpus
|
||||
set(BOOST_URL_FUZZER_SEEDS_PATH ${CMAKE_CURRENT_SOURCE_DIR}/seeds.tar)
|
||||
set(BOOST_URL_FUZZER_SEEDS_DIR ${CMAKE_CURRENT_BINARY_DIR}/seeds)
|
||||
get_filename_component(BOOST_URL_FUZZER_SEEDS_PARENT_DIR ${BOOST_URL_FUZZER_SEEDS_DIR} DIRECTORY)
|
||||
add_custom_target(
|
||||
untar_seeds
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Untar fuzz seeds from ${BOOST_URL_FUZZER_SEEDS_PATH} to ${BOOST_URL_FUZZER_SEEDS_PARENT_DIR}/seeds"
|
||||
COMMAND ${CMAKE_COMMAND} -E tar xf ${BOOST_URL_FUZZER_SEEDS_PATH}
|
||||
WORKING_DIRECTORY ${BOOST_URL_FUZZER_SEEDS_PARENT_DIR}
|
||||
COMMENT "Unzipping fuzz seeds"
|
||||
VERBATIM)
|
||||
|
||||
set(BOOST_URL_FUZZER_CORPUS_DIR ${CMAKE_CURRENT_BINARY_DIR}/corpus)
|
||||
set(BOOST_URL_FUZZER_MERGED_CORPUS_DIR ${CMAKE_CURRENT_BINARY_DIR}/merged-corpus)
|
||||
if(EXISTS ${BOOST_URL_FUZZER_CORPUS_PATH})
|
||||
add_custom_target(
|
||||
untar_corpus
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Untar fuzz corpus archive from \"${BOOST_URL_FUZZER_CORPUS_PATH}\" to \"${CMAKE_CURRENT_BINARY_DIR}/corpus\""
|
||||
COMMAND ${CMAKE_COMMAND} -E tar xf ${BOOST_URL_FUZZER_CORPUS_PATH}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
COMMENT "Unzipping fuzz corpus"
|
||||
VERBATIM)
|
||||
else()
|
||||
add_custom_target(untar_corpus
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "No fuzz corpus archive in ${BOOST_URL_FUZZER_CORPUS_PATH}. Create empty fuzz corpus dir \"${BOOST_URL_FUZZER_CORPUS_DIR}.\""
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${BOOST_URL_FUZZER_CORPUS_DIR}
|
||||
COMMENT "Creating fuzz corpus directory"
|
||||
VERBATIM)
|
||||
endif()
|
||||
add_dependencies(untar_corpus untar_seeds)
|
||||
|
||||
# Target that runs all fuzz targets
|
||||
get_filename_component(BOOST_URL_FUZZER_CORPUS_PARENT_DIR ${BOOST_URL_FUZZER_CORPUS_PATH} DIRECTORY)
|
||||
add_custom_target(
|
||||
fuzz
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Archive corpus from \"${BOOST_URL_FUZZER_CORPUS_DIR}\" to \"${BOOST_URL_FUZZER_CORPUS_PATH}\""
|
||||
COMMAND ${CMAKE_COMMAND} -E tar cf ${BOOST_URL_FUZZER_CORPUS_PATH} ${BOOST_URL_FUZZER_CORPUS_DIR}
|
||||
WORKING_DIRECTORY ${BOOST_URL_FUZZER_CORPUS_PARENT_DIR}
|
||||
VERBATIM)
|
||||
|
||||
# Boost.URL with fuzz options
|
||||
add_library(boost_url_fuzz ${BOOST_URL_HEADERS} ${BOOST_URL_SOURCES})
|
||||
boost_url_setup_properties(boost_url_fuzz)
|
||||
target_compile_options(boost_url_fuzz PRIVATE -g -O2 -fsanitize=fuzzer,address,undefined -fno-sanitize-recover=undefined)
|
||||
target_link_libraries(boost_url_fuzz PRIVATE -fsanitize=fuzzer,address,undefined)
|
||||
|
||||
# Register a single fuzzer and add as dependency to fuzz target
|
||||
function(add_boost_url_fuzzer NAME)
|
||||
# Fuzzer executable
|
||||
set(SOURCE_FILES ${ARGN})
|
||||
add_executable(fuzzer_${NAME} ${SOURCE_FILES})
|
||||
target_link_libraries(fuzzer_${NAME} PRIVATE boost_url_fuzz)
|
||||
target_compile_options(fuzzer_${NAME} PRIVATE -g -O2 -fsanitize=fuzzer,address,undefined -fno-sanitize-recover=undefined)
|
||||
target_link_libraries(fuzzer_${NAME} PRIVATE -fsanitize=fuzzer,address,undefined)
|
||||
set_property(TARGET fuzzer_${NAME} PROPERTY FOLDER "fuzzing")
|
||||
|
||||
# Custom target to run fuzzer executable
|
||||
add_custom_target(
|
||||
fuzz_${NAME}
|
||||
ALL
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${BOOST_URL_FUZZER_CORPUS_DIR}/${NAME}
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Running fuzzer ${NAME} with corpus from ${BOOST_URL_FUZZER_CORPUS_DIR}/${NAME} and seeds from ${BOOST_URL_FUZZER_SEEDS_DIR}/${NAME}"
|
||||
COMMAND
|
||||
fuzzer_${NAME}
|
||||
-rss_limit_mb=${BOOST_URL_FUZZER_RSS_LIMIT}
|
||||
-max_total_time=${BOOST_URL_FUZZER_TOTAL_TIME}
|
||||
-timeout=${BOOST_URL_FUZZER_TIMEOUT}
|
||||
-max_len=${BOOST_URL_FUZZER_MAX_LEN}
|
||||
-jobs=${BOOST_URL_FUZZER_JOBS}
|
||||
${BOOST_URL_FUZZER_CORPUS_DIR}/${NAME}
|
||||
${BOOST_URL_FUZZER_SEEDS_DIR}/${NAME}
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${BOOST_URL_FUZZER_MERGED_CORPUS_DIR}/${NAME}
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Merging corpus from ${BOOST_URL_FUZZER_CORPUS_DIR}/${NAME} to ${BOOST_URL_FUZZER_MERGED_CORPUS_DIR}/${NAME}"
|
||||
COMMAND
|
||||
fuzzer_${NAME}
|
||||
-merge=1
|
||||
${BOOST_URL_FUZZER_MERGED_CORPUS_DIR}/${NAME}
|
||||
${BOOST_URL_FUZZER_CORPUS_DIR}/${NAME}
|
||||
${BOOST_URL_FUZZER_SEEDS_DIR}/${NAME}
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Replacing corpus in ${BOOST_URL_FUZZER_CORPUS_DIR}/${NAME} with merged corpus from ${BOOST_URL_FUZZER_MERGED_CORPUS_DIR}/${NAME}"
|
||||
COMMAND ${CMAKE_COMMAND} -E remove_directory ${BOOST_URL_FUZZER_CORPUS_DIR}/${NAME}
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${BOOST_URL_FUZZER_CORPUS_DIR}/${NAME}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${BOOST_URL_FUZZER_MERGED_CORPUS_DIR}/${NAME} ${BOOST_URL_FUZZER_CORPUS_DIR}/${NAME}
|
||||
COMMAND ${CMAKE_COMMAND} -E remove_directory ${BOOST_URL_FUZZER_MERGED_CORPUS_DIR}/${NAME}
|
||||
DEPENDS untar_corpus fuzzer_${NAME})
|
||||
add_dependencies(fuzz_${NAME} fuzzer_${NAME})
|
||||
add_dependencies(fuzz fuzz_${NAME})
|
||||
set_property(TARGET fuzz_${NAME} PROPERTY ENVIRONMENT "UBSAN_OPTIONS=halt_on_error=false")
|
||||
|
||||
if (BOOST_URL_FUZZER_ADD_TO_CTEST)
|
||||
add_test(
|
||||
NAME test_fuzz_${NAME}
|
||||
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target fuzz_${NAME})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
add_boost_url_fuzzer(parse fuzz_parse.cpp)
|
||||
# Register all fuzzers
|
||||
file(GLOB BOOST_URL_FUZZER_SOURCE_FILES *.cpp)
|
||||
source_group("" FILES ${BOOST_URL_FUZZER_SOURCE_FILES})
|
||||
foreach(BOOST_URL_FUZZER_SOURCE_FILE ${BOOST_URL_FUZZER_SOURCE_FILES})
|
||||
file(RELATIVE_PATH BOOST_URL_FUZZER_SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR} ${BOOST_URL_FUZZER_SOURCE_FILE})
|
||||
string(REGEX REPLACE "(.*).cpp" "\\1" RULE_NAME ${BOOST_URL_FUZZER_SOURCE_FILE})
|
||||
add_boost_url_fuzzer(${RULE_NAME} ${BOOST_URL_FUZZER_SOURCE_FILE})
|
||||
endforeach()
|
||||
|
||||
@@ -1,185 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2023 alandefreitas (alandefreitas@gmail.com)
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# https://www.boost.org/LICENSE_1_0.txt
|
||||
#
|
||||
|
||||
# This code has been adapted from libs/json/fuzzing/Jamfile
|
||||
#
|
||||
# Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
|
||||
# Copyright (c) 2019 Paul Dreik
|
||||
# Copyright (c) 2021 Dmitry Arkhipov (grisumbras@gmail.com)
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
# Official repository: https://github.com/boostorg/json
|
||||
#
|
||||
|
||||
import common ;
|
||||
import link ;
|
||||
import os ;
|
||||
import path ;
|
||||
import property ;
|
||||
import sequence ;
|
||||
|
||||
# set the maximum size of the input, to avoid
|
||||
# big inputs which blow up the corpus size
|
||||
.MAXLEN = [ os.environ MAXLEN ] ;
|
||||
.MAXLEN ?= -max_len=4000 ;
|
||||
|
||||
# set a timelimit (you may want to adjust this if you run locally)
|
||||
.MAXTIME = [ os.environ MAXTIME ] ;
|
||||
.MAXTIME ?= -max_total_time=30 ;
|
||||
|
||||
# If doing fuzzing locally (not in CI), adjust this to utilize more
|
||||
# of your cpu.
|
||||
#JOBS="-jobs=32"
|
||||
.JOBS = [ os.environ JOBS ] ;
|
||||
|
||||
# make sure ubsan stops in case anything is found
|
||||
.UBSAN_OPTIONS = [
|
||||
common.variable-setting-command UBSAN_OPTIONS : halt_on_error=1
|
||||
] ;
|
||||
|
||||
local corpus.tar = [ glob-ex . : corpus.tar ] ;
|
||||
if $(corpus.tar)
|
||||
{
|
||||
# if an old corpus exists, use it
|
||||
make old-corpus
|
||||
: $(corpus.tar)
|
||||
: @untar-corpus
|
||||
: <location>oldcorpus
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
alias old-corpus ;
|
||||
}
|
||||
explicit old-corpus ;
|
||||
|
||||
local initial-corpus = [ glob-tree-ex ../test : *.json ] ;
|
||||
|
||||
local variants = parse ;
|
||||
for local variant in parse
|
||||
{
|
||||
local $(variant)-runs ;
|
||||
local fuzzer = fuzzer_$(variant) ;
|
||||
lib $(fuzzer) : fuzz_$(variant).cpp /boost/url//boost_url ;
|
||||
exe $(fuzzer)
|
||||
: fuzz_$(variant).cpp /boost/url//url_sources
|
||||
: requirements
|
||||
<toolset>clang
|
||||
<conditional>@fuzzer-props
|
||||
;
|
||||
|
||||
# make sure the old crashes pass without problems
|
||||
local old-runs = [ glob-tree-ex old_crashes/$(variant) : * ] ;
|
||||
if $(old-runs)
|
||||
{
|
||||
run $(fuzzer)
|
||||
: target-name $(variant)-run-crashes
|
||||
: input-files [ SORT $(old-runs) ]
|
||||
;
|
||||
$(variant)-runs += $(variant)-run-crashes ;
|
||||
}
|
||||
|
||||
make oldcorpus/$(variant)
|
||||
: old-corpus
|
||||
: common.MkDir
|
||||
: <location>.
|
||||
;
|
||||
explicit oldcorpus/$(variant) ;
|
||||
|
||||
# make an initial corpus from the test data already in the repo
|
||||
local seed-corpus ;
|
||||
for file in $(initial-corpus)
|
||||
{
|
||||
local copied = $(variant)/$(file:D=) ;
|
||||
make $(copied) : $(file) : common.copy : <location>seedcorpus ;
|
||||
explicit $(copied) ;
|
||||
seed-corpus += $(copied) ;
|
||||
}
|
||||
make seedcorpus/$(variant)
|
||||
: $(seed-corpus)
|
||||
: common.MkDir
|
||||
: <location>.
|
||||
;
|
||||
explicit seedcorpus/$(variant) ;
|
||||
|
||||
# run the fuzzer for a short while
|
||||
make out/$(variant)
|
||||
: $(fuzzer)
|
||||
oldcorpus/$(variant)
|
||||
seedcorpus/$(variant)
|
||||
: @run-fuzzer
|
||||
: <location>.
|
||||
<flags>$(.MAXTIME)
|
||||
<flags>$(.MAXLEN)
|
||||
<flags>$(.JOBS)
|
||||
;
|
||||
$(variant)-runs += out/$(variant) ;
|
||||
|
||||
# minimize the corpus
|
||||
make cmin/$(variant)
|
||||
: $(fuzzer)
|
||||
oldcorpus/$(variant)
|
||||
out/$(variant)
|
||||
: @run-fuzzer
|
||||
: <location>.
|
||||
<flags>-merge=1
|
||||
<flags>$(.MAXLEN)
|
||||
;
|
||||
$(variant)-runs += cmin/$(variant) ;
|
||||
|
||||
alias $(variant)-run : $($(variant)-runs) ;
|
||||
explicit $($(variant)-runs) ;
|
||||
}
|
||||
|
||||
alias run : $(variants)-run ;
|
||||
explicit run $(variants)-run ;
|
||||
|
||||
rule fuzzer-props ( props * )
|
||||
{
|
||||
local toolset = [ property.select toolset : $(props) ] ;
|
||||
if clang = $(toolset:G=)
|
||||
{
|
||||
return
|
||||
<debug-symbols>on
|
||||
<optimization>speed
|
||||
<address-sanitizer>on
|
||||
<undefined-sanitizer>norecover
|
||||
<cxxflags>-fsanitize=fuzzer
|
||||
<linkflags>-fsanitize=fuzzer
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
return <build>no ;
|
||||
}
|
||||
}
|
||||
|
||||
rule run-fuzzer ( target : sources * : props * )
|
||||
{
|
||||
local flags = [ property.select flags : $(props) ] ;
|
||||
FLAGS on $(target) = $(flags:G=) ;
|
||||
|
||||
local dir = [ path.make [ on $(target) return $(LOCATE) ] ] ;
|
||||
dir = $(dir)/$(target:G=) ;
|
||||
common.MkDir $(dir) ;
|
||||
DEPENDS $(target) : $(dir) ;
|
||||
}
|
||||
|
||||
actions run-fuzzer
|
||||
{
|
||||
$(.UBSAN_OPTIONS)
|
||||
$(>[1]) $(<) $(>[2]) $(>[3]) $(FLAGS)
|
||||
}
|
||||
|
||||
.TOUCH_FILE = [ common.file-touch-command ] ;
|
||||
actions untar-corpus
|
||||
{
|
||||
tar xf $(>) -C $(<:D)
|
||||
$(.TOUCH_FILE) $(<)
|
||||
}
|
||||
26
test/fuzz/absolute_uri.cpp
Normal file
26
test/fuzz/absolute_uri.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// Copyright (c) 2023 alandefreitas (alandefreitas@gmail.com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
|
||||
#include <boost/url/parse.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
|
||||
using namespace boost::urls;
|
||||
namespace core = boost::core;
|
||||
|
||||
extern "C"
|
||||
int
|
||||
LLVMFuzzerTestOneInput(
|
||||
const uint8_t* data,
|
||||
size_t size)
|
||||
{
|
||||
core::string_view s{reinterpret_cast<
|
||||
const char*>(data), size};
|
||||
boost::ignore_unused(parse_absolute_uri(s));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2023 alandefreitas (alandefreitas@gmail.com)
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# https://www.boost.org/LICENSE_1_0.txt
|
||||
#
|
||||
# This code has been adapted from libs/json/fuzzing/fuzz.sh
|
||||
# By Paul Dreik 2019-2020 for the boost json project
|
||||
# License: Boost 1.0
|
||||
|
||||
set -e
|
||||
|
||||
# Current directory
|
||||
fuzzdir=$(dirname $0)
|
||||
me=$(basename $0)
|
||||
|
||||
cd $fuzzdir
|
||||
|
||||
# Find Clang
|
||||
if [ -z $CLANG ]; then
|
||||
for clangver in -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -6.0 ""; do
|
||||
CLANG=clang++$clangver
|
||||
if which $CLANG >/dev/null; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if ! which $CLANG >/dev/null; then
|
||||
if ! -x $CLANG; then
|
||||
echo $me: sorry, could not find clang $CLANG
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
echo "\$CLANG: $CLANG"
|
||||
|
||||
# Fuzzer parameters
|
||||
MAXLEN="-max_len=4000" # max input size, to avoid blowing up the corpus size
|
||||
JOBS= # Adjust this to utilize more of your cpu: JOBS="-jobs=32"
|
||||
MAXTIME="-max_total_time=30" # seconds
|
||||
|
||||
# Compile and run each fuzzer
|
||||
variants="parse"
|
||||
for variant in $variants; do
|
||||
# Paths
|
||||
srcfile=fuzz_$variant.cpp
|
||||
fuzzer=./fuzzer_$variant
|
||||
seedcorpus=seedcorpus/$variant
|
||||
|
||||
echo "Fuzz \"$variant\""
|
||||
echo "\$srcfile= $srcfile"
|
||||
echo "\$fuzzer= $fuzzer"
|
||||
echo "\$seedcorpus= $seedcorpus"
|
||||
|
||||
# Compile
|
||||
if [ ! -e $fuzzer -o $srcfile -nt $fuzzer ]; then
|
||||
$CLANG \
|
||||
-std=c++11 \
|
||||
-O3 \
|
||||
-g \
|
||||
-fsanitize=fuzzer,address,undefined \
|
||||
-fno-sanitize-recover=undefined \
|
||||
-I../../include \
|
||||
-o $fuzzer \
|
||||
../../src/src.cpp \
|
||||
$srcfile
|
||||
fi
|
||||
|
||||
# Create initial corpus from old crashes in repo
|
||||
if [ -d old_crashes/$variant ]; then
|
||||
find old_crashes/$variant -type f -print0 | xargs -0 --no-run-if-empty $fuzzer
|
||||
fi
|
||||
if [ ! -d $seedcorpus ]; then
|
||||
mkdir -p $seedcorpus
|
||||
find ../test -name "*.json" -type f -print0 | xargs -0 --no-run-if-empty cp -f -t $seedcorpus/
|
||||
fi
|
||||
|
||||
# Potentially merge file with old corpus
|
||||
if [ -e corpus.tar ]; then
|
||||
mkdir -p oldcorpus
|
||||
tar xf corpus.tar -C oldcorpus || echo "corpus.tar was broken! ignoring it"
|
||||
OLDCORPUS=oldcorpus/cmin/$variant
|
||||
mkdir -p $OLDCORPUS
|
||||
else
|
||||
OLDCORPUS=
|
||||
fi
|
||||
|
||||
# Run fuzzer with corpus
|
||||
export UBSAN_OPTIONS="halt_on_error=1"
|
||||
mkdir -p out/$variant
|
||||
$fuzzer out/$variant $OLDCORPUS $seedcorpus/ $MAXTIME $MAXLEN $JOBS
|
||||
|
||||
# Minimize the corpus
|
||||
mkdir -p cmin/$variant
|
||||
$fuzzer cmin/$variant $OLDCORPUS out/$variant $seedcorpus/ -merge=1 $MAXLEN
|
||||
done
|
||||
@@ -1,67 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2023 alandefreitas (alandefreitas@gmail.com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
|
||||
#include <boost/url/parse.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
|
||||
using namespace boost::urls;
|
||||
namespace core = boost::core;
|
||||
|
||||
enum class parser {
|
||||
absolute_uri,
|
||||
origin_form,
|
||||
relative_ref,
|
||||
uri,
|
||||
uri_reference
|
||||
};
|
||||
|
||||
bool
|
||||
fuzz_parse(parser p, core::string_view sv)
|
||||
{
|
||||
boost::system::result<url_view> r;
|
||||
switch (p)
|
||||
{
|
||||
case parser::absolute_uri:
|
||||
r = parse_absolute_uri(sv);
|
||||
break;
|
||||
case parser::origin_form:
|
||||
r = parse_origin_form(sv);
|
||||
break;
|
||||
case parser::relative_ref:
|
||||
r = parse_relative_ref(sv);
|
||||
break;
|
||||
case parser::uri:
|
||||
r = parse_uri(sv);
|
||||
break;
|
||||
case parser::uri_reference:
|
||||
r = parse_uri_reference(sv);
|
||||
break;
|
||||
}
|
||||
return r.has_value();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
int
|
||||
LLVMFuzzerTestOneInput(
|
||||
const uint8_t* data,
|
||||
size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return -1;
|
||||
try
|
||||
{
|
||||
auto p = static_cast<parser>(data[0] % 5);
|
||||
core::string_view s{reinterpret_cast<
|
||||
const char*>(data + 1), size - 1};
|
||||
fuzz_parse(p, s);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
26
test/fuzz/origin_form.cpp
Normal file
26
test/fuzz/origin_form.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// Copyright (c) 2023 alandefreitas (alandefreitas@gmail.com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
|
||||
#include <boost/url/parse.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
|
||||
using namespace boost::urls;
|
||||
namespace core = boost::core;
|
||||
|
||||
extern "C"
|
||||
int
|
||||
LLVMFuzzerTestOneInput(
|
||||
const uint8_t* data,
|
||||
size_t size)
|
||||
{
|
||||
core::string_view s{reinterpret_cast<
|
||||
const char*>(data), size};
|
||||
boost::ignore_unused(parse_origin_form(s));
|
||||
return 0;
|
||||
}
|
||||
|
||||
26
test/fuzz/relative_ref.cpp
Normal file
26
test/fuzz/relative_ref.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// Copyright (c) 2023 alandefreitas (alandefreitas@gmail.com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
|
||||
#include <boost/url/parse.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
|
||||
using namespace boost::urls;
|
||||
namespace core = boost::core;
|
||||
|
||||
extern "C"
|
||||
int
|
||||
LLVMFuzzerTestOneInput(
|
||||
const uint8_t* data,
|
||||
size_t size)
|
||||
{
|
||||
core::string_view s{reinterpret_cast<
|
||||
const char*>(data), size};
|
||||
boost::ignore_unused(parse_relative_ref(s));
|
||||
return 0;
|
||||
}
|
||||
|
||||
BIN
test/fuzz/seeds.tar
Normal file
BIN
test/fuzz/seeds.tar
Normal file
Binary file not shown.
26
test/fuzz/uri.cpp
Normal file
26
test/fuzz/uri.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// Copyright (c) 2023 alandefreitas (alandefreitas@gmail.com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
|
||||
#include <boost/url/parse.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
|
||||
using namespace boost::urls;
|
||||
namespace core = boost::core;
|
||||
|
||||
extern "C"
|
||||
int
|
||||
LLVMFuzzerTestOneInput(
|
||||
const uint8_t* data,
|
||||
size_t size)
|
||||
{
|
||||
core::string_view s{reinterpret_cast<
|
||||
const char*>(data), size};
|
||||
boost::ignore_unused(parse_uri(s));
|
||||
return 0;
|
||||
}
|
||||
|
||||
26
test/fuzz/uri_reference.cpp
Normal file
26
test/fuzz/uri_reference.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// Copyright (c) 2023 alandefreitas (alandefreitas@gmail.com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
|
||||
#include <boost/url/parse.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
|
||||
using namespace boost::urls;
|
||||
namespace core = boost::core;
|
||||
|
||||
extern "C"
|
||||
int
|
||||
LLVMFuzzerTestOneInput(
|
||||
const uint8_t* data,
|
||||
size_t size)
|
||||
{
|
||||
core::string_view s{reinterpret_cast<
|
||||
const char*>(data), size};
|
||||
boost::ignore_unused(parse_uri_reference(s));
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user