1#!/bin/bash 2set -eo pipefail 3 4# Copyright 2018-2019 by 5# Armin Hasitzka. 6# 7# This file is part of the FreeType project, and may only be used, modified, 8# and distributed under the terms of the FreeType project license, 9# LICENSE.TXT. By continuing to use, modify, or distribute this file you 10# indicate that you have read the license and understand and accept it 11# fully. 12 13dir="${PWD}" 14cd $( dirname $( readlink -f "${0}" ) ) # go to `/fuzzing/scripts' 15 16# ---------------------------------------------------------------------------- 17# collect parameters: 18 19opt_help="0" # 0|1 20opt_rebuild="0" # 0|1 21 22while [[ "${#}" -gt "0" ]]; do 23 case "${1}" in 24 --help) 25 opt_help="1" 26 shift 27 ;; 28 --rebuild) 29 opt_rebuild="1" 30 shift 31 ;; 32 *) # show usage when invalid parameters are used: 33 opt_help="1" 34 shift 35 ;; 36 esac 37done 38 39# ---------------------------------------------------------------------------- 40# usage: 41 42if [[ "${opt_help}" == "1" ]]; then 43 cat <<EOF 44 45usage: ${0} [OPTIONS] 46 47This script listens to a few environmental variables. It is not mandatory to 48set any of these variables but if they are set, they will be used. 49 50 CFLAGS Additional C compiler flags. 51 CXXFLAGS Additional C++ compiler flags. 52 LDFLAGS Additional linker flags. 53 54OPTIONS: 55 56 --rebuild Rebuild the last build. Nothing will be reset, nothing will be 57 changed. Using this option calls 'make' in every module without 58 flushing or resetting anything. Useful for debugging. 59 60 --help Print usage information. 61 62EOF 63 64 exit 66 65fi 66 67# ---------------------------------------------------------------------------- 68# rebuild shortcut: 69 70if [[ "${opt_rebuild}" == "1" ]]; then 71 bash build/glog.sh --no-init 72 bash build/libarchive.sh --no-init 73 bash build/freetype.sh --no-init 74 bash build/targets.sh --no-init 75 exit 76fi 77 78# ---------------------------------------------------------------------------- 79# settings: 80 81ansi_reset="\e[0m" 82ansi_bold="\e[1m" 83ansi_underline="\e[4m" 84ansi_red="\e[31m" 85ansi_yellow="\e[33m" 86 87build_type= # d|f 88build_asan= # y|n 89build_ubsan= # y|n 90build_coverage= # y|n 91build_debugging= # 0|1|2|3|n 92build_ft_trace= # y|n 93build_ccache= # y|n 94 95cc="clang" 96cxx="clang++" 97 98cflags="${CFLAGS}" 99cxxflags="${CXXFLAGS} -std=c++11" 100ldflags="${LDFLAGS}" 101 102# Base name of the driver: 103driver_name="driver" 104 105# ---------------------------------------------------------------------------- 106# helpers: 107 108# Print the new line character (\n). 109function print_nl() 110{ 111 printf "\n" 112} 113 114# Print a question. 115# 116# $1: Question string. 117function print_q() 118{ 119 printf "\n${ansi_bold}%s${ansi_reset}\n" "${1}" 120} 121 122# Print some information. 123# 124# $1: Name of an option. 125# $2: Description of the option. 126# 127# .. or ... 128# 129# $1: General information. 130function print_info() 131{ 132 if [[ "$#" == "1" ]]; then 133 printf " %s\n" "${1}" 134 elif [[ "$#" == "2" ]]; then 135 printf " ${ansi_yellow}%s${ansi_reset}: %s\n" "${1}" "${2}" 136 else 137 exit 66 138 fi 139} 140 141# Print a url. 142# 143# $1: URL. 144function print_url() 145{ 146 printf " ${ansi_underline}%s${ansi_reset}\n" "${1}" 147} 148 149# Print (+ verify) the selection of an option. 150# 151# $1: The chosen option. 152# ${2n + 2, n >= 0}: The nth option. 153# ${2n + 3, n >= 0}: The nth description of an option. 154# 155# Example: $ print_sel ${selection} "y" "yes" "n" "no" ... 156function print_sel() 157{ 158 i=2 159 while [[ i -le "$#" ]]; do 160 if [[ "${1}" == "${!i}" ]]; then 161 i=$(( i + 1 )) 162 printf "\n selection: ${ansi_yellow}%s${ansi_reset}\n" "${!i}" 163 return 164 fi 165 i=$(( i + 2 )) 166 done 167 printf "\n ${ansi_red}${ansi_bold}invalid selection: %s${ansi_reset}\n\n" "${1}" 168 exit 66 169} 170 171# Print (+ verify) the slection of an option that can either be "y" (yes) or 172# "n" (no). 173# 174# $1: The chosen option. 175function print_sel_yes_no() 176{ 177 print_sel "${1}" "y" "yes" "n" "no" 178} 179 180# Ask the user and print the (accepted + valid) result. 181# 182# $1: a list of options like "a|b|c" 183# $2 (optional): a default option like "a" 184function ask_user() 185{ 186 options="${1}" 187 if [[ "$#" == "2" ]]; then 188 options="${options}, default: ${2}" 189 fi 190 while : ; do 191 read -p "(${options}) > " answer 192 answer=$(echo "${answer}" | tr '[:upper:]' '[:lower:]') 193 if [[ "${answer}" == "" && "$#" == "2" ]]; then 194 echo "${2}" 195 break 196 fi 197 if [[ "${1}" == *"|${answer}|"* || 198 "${1}" == *"|${answer}" || 199 "${1}" == "${answer}|"* ]]; then 200 echo "${answer}" 201 break 202 fi 203 done 204} 205 206# ---------------------------------------------------------------------------- 207# interaction: 208 209printf "${ansi_yellow}" 210printf " ____ ____ ____ ____ ______ __ ___ ____\n" 211printf "| __) _ \| __) __)_ __) / / _ \| __)\n" 212printf "| |__| |_) ) |__| |__ | | \ \/ /| |_) ) |__\n" 213printf "| __) /| __) __) | | \ / | __/| __)\n" 214printf "| | | |\ \| |__| |__ | | / / | | | |__\n" 215printf "|_| |_| \_\____)____) |_| /_/ |_| |____)\n\n" 216printf "${ansi_reset}" 217printf " Custom Build\n" 218 219print_q "Build the driver or the fuzzer?" 220print_info "driver" "run selected samples or failed instances" 221print_info "fuzzer" "fuzz a corpus of samples with libFuzzer" 222print_nl 223 224build_type=$( ask_user "d|f" ) 225print_sel "${build_type}" "d" "driver" "f" "fuzzer" 226 227if [[ "${build_type}" == "f" ]]; then 228 cflags=" ${cflags} -fsanitize=fuzzer-no-link" 229 cxxflags="${cxxflags} -fsanitize=fuzzer-no-link" 230 231 export CMAKE_FUZZING_ENGINE="-fsanitize=fuzzer" 232fi 233 234print_q "Add the AddressSanitizer?" 235print_url "https://clang.llvm.org/docs/AddressSanitizer.html" 236print_nl 237 238build_asan=$( ask_user "y|n" "y" ) 239print_sel_yes_no "${build_asan}" 240 241if [[ "${build_asan}" == "y" ]]; then 242 cflags=" ${cflags} -fsanitize=address -fsanitize-address-use-after-scope" 243 cxxflags="${cxxflags} -fsanitize=address -fsanitize-address-use-after-scope" 244 ldflags=" ${ldflags} -fsanitize=address" 245 246 driver_name="${driver_name}-asan" 247fi 248 249print_q "Add the UndefinedBehaviorSanitizer?" 250print_url "https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html" 251print_nl 252 253build_ubsan=$( ask_user "y|n" "y" ) 254print_sel_yes_no "${build_ubsan}" 255 256if [[ "${build_ubsan}" == "y" ]]; then 257 cflags=" ${cflags} -fsanitize=undefined" 258 cxxflags="${cxxflags} -fsanitize=undefined" 259 ldflags=" ${ldflags} -fsanitize=undefined" 260 261 driver_name="${driver_name}-ubsan" 262fi 263 264print_q "Add coverage instrumentation?" 265print_url "https://clang.llvm.org/docs/SourceBasedCodeCoverage.html" 266print_nl 267 268build_coverage=$( ask_user "y|n" "n" ) 269print_sel_yes_no "${build_coverage}" 270 271if [[ "${build_coverage}" == "y" ]]; then 272 cflags=" ${cflags} -fprofile-instr-generate -fcoverage-mapping" 273 cxxflags="${cxxflags} -fprofile-instr-generate -fcoverage-mapping" 274 ldflags=" ${ldflags} -fprofile-instr-generate" 275 276 driver_name="${driver_name}-cov" 277fi 278 279if [[ "${build_asan}" == "y" || "${build_ubsan}" == "y" ]]; then 280 print_q "Choose the optimisation level:" 281 print_info "0" "compile with '-g -O0'" 282 print_info "1" "compile with '-g -O1'" 283 print_info "2" "compile with '-g -O2'" 284 print_info "3" "compile with '-g -O3'" 285 print_nl 286 287 build_debugging=$( ask_user "0|1|2|3" "1" ) 288 print_sel "${build_debugging}" \ 289 "0" "-g -O0" \ 290 "1" "-g -O1" \ 291 "2" "-g -O2" \ 292 "3" "-g -O3" 293else 294 print_q "Add debugging flags?" 295 print_info "0" "compile with '-g -O0'" 296 print_info "1" "compile with '-g -O1'" 297 print_info "2" "compile with '-g -O2'" 298 print_info "3" "compile with '-g -O3'" 299 print_info "n" "compile without debugging flags" 300 print_nl 301 302 build_debugging=$( ask_user "0|1|2|3|n" "1" ) 303 print_sel "${build_debugging}" \ 304 "0" "-g -O0" \ 305 "1" "-g -O1" \ 306 "2" "-g -O2" \ 307 "3" "-g -O3" \ 308 "n" "no" 309fi 310 311if [[ "${build_debugging}" != "n" ]]; then 312 cflags=" ${cflags} -g -O${build_debugging}" 313 cxxflags="${cxxflags} -g -O${build_debugging}" 314 315 driver_name="${driver_name}-o${build_debugging}" 316fi 317 318if [[ "${build_type}" == "f" ]]; then 319 build_glog="n" 320else 321 print_q "Use Glog logger?" 322 print_url "https://github.com/google/glog" 323 print_info "no" "logging will be compiled out and glog will not be linked" 324 print_nl 325 326 build_glog=$( ask_user "y|n" "n" ) 327 print_sel_yes_no "${build_glog}" 328fi 329 330if [[ "${build_glog}" == "y" ]]; then 331 export CMAKE_USE_LOGGER_GLOG=1 332 333 driver_name="${driver_name}-glog" 334fi 335 336if [[ "${build_type}" == "f" ]]; then 337 build_ft_trace="n" 338else 339 print_q "Add FreeType tracing?" 340 print_info "yes" "activate 'FT_DEBUG_LEVEL_{TRACE,ERROR}' and 'FT_DEBUG_MEMORY'" 341 print_nl 342 343 build_ft_trace=$( ask_user "y|n" "n" ) 344 print_sel_yes_no "${build_ft_trace}" 345fi 346 347if [[ "${build_ft_trace}" == "y" ]]; then 348 cflags=" ${cflags} -DFT_DEBUG_LEVEL_TRACE -DFT_DEBUG_LEVEL_ERROR -DFT_DEBUG_MEMORY" 349 cxxflags="${cxxflags} -DFT_DEBUG_LEVEL_TRACE -DFT_DEBUG_LEVEL_ERROR -DFT_DEBUG_MEMORY" 350 351 driver_name="${driver_name}-fttrace" 352fi 353 354if ! command -v "ccache" >"/dev/null"; then 355 build_ccache="n" 356else 357 print_q "Use ccache?" 358 print_info "ccache seems to be available on this system" 359 print_nl 360 361 build_ccache=$( ask_user "y|n" "y" ) 362 print_sel_yes_no "${build_ccache}" 363fi 364 365if [[ "${build_ccache}" == "y" ]]; then 366 cc="ccache ${cc}" 367 cxx="ccache ${cxx}" 368 369 driver_name="${driver_name}-ccache" 370fi 371 372print_nl 373 374# ---------------------------------------------------------------------------- 375# export flags and build everything: 376 377export CC="${cc}" 378export CXX="${cxx}" 379 380export CFLAGS="${cflags}" 381export CXXFLAGS="${cxxflags}" 382export LDFLAGS="${ldflags}" 383 384export CMAKE_DRIVER_EXE_NAME="${driver_name}" 385 386if [[ "${build_glog}" == "y" ]]; then 387 bash "build/glog.sh" 388fi 389 390bash "build/libarchive.sh" 391bash "build/brotli.sh" 392bash "build/bzip2.sh" 393bash "build/freetype.sh" 394bash "build/targets.sh" 395 396cd "${dir}" 397