blob: 9a61597f11f048ab813284bf95b03235042ee21e [file] [log] [blame]
#!/bin/bash
# Copyright 2020 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
################################################################################
# This script is meant to be run by the oss-fuzz infrastructure from the script
# https://github.com/google/oss-fuzz/blob/master/projects/libavif/build.sh
# It builds the different fuzz targets.
# To test changes to this file:
# - make changes and commit to your REPO
# - run:
# git clone --depth=1 git@github.com:google/oss-fuzz.git
# cd oss-fuzz
# - modify projects/libavif/Dockerfile to point to your REPO
# - run:
# python3 infra/helper.py build_image libavif
# # enter 'y' and wait for everything to be downloaded
# - run:
# python3 infra/helper.py build_fuzzers --sanitizer address libavif
# # wait for the tests to be built
# And then run the fuzzer locally, for example:
# python3 infra/helper.py run_fuzzer libavif \
# avif_fuzztest_enc_dec_incr@EncodeDecodeAvifFuzzTest.EncodeDecodeGridValid \
# --sanitizer address
set -eu
# Build dav1d with sanitizer flags.
# Adds extra flags: -Db_sanitize=$SANITIZER -Db_lundef=false, and -Denable_asm=false for msan
DAV1D_EXTRA_FLAGS=""
if [[ "$SANITIZER" != "coverage" && "$SANITIZER" != "introspector" ]]; then
DAV1D_EXTRA_FLAGS="${DAV1D_EXTRA_FLAGS} -Db_sanitize=$SANITIZER -Db_lundef=false"
fi
if [[ "$SANITIZER" == "memory" ]]; then
DAV1D_EXTRA_FLAGS="${DAV1D_EXTRA_FLAGS} -Denable_asm=false"
fi
sed -i "s/meson setup \(.*\) \.\./meson setup \1${DAV1D_EXTRA_FLAGS} ../g" ./ext/dav1d.cmd
# Build libaom with sanitizer flags.
# Adds extra flags: -DAOM_TARGET_CPU=generic for msan.
if [[ "$SANITIZER" == "memory" ]]; then
sed -i 's/cmake \(.*\) \.\./cmake \1 -DAOM_TARGET_CPU=generic ../g' ./ext/aom.cmd
fi
# Build libjpeg-turbo with sanitizer flags. Add extra flag -DWITH_SIMD=0 for msan.
# See https://github.com/libjpeg-turbo/libjpeg-turbo/blob/main/README.md#memory-debugger-pitfalls
if [[ "$SANITIZER" == "memory" ]]; then
sed -i 's/cmake -S libjpeg-turbo \(.*\)/cmake -S libjpeg-turbo \1 -DWITH_SIMD=0/g' ./ext/libjpeg.cmd
fi
# Prepare dependencies.
cd ext && bash aom.cmd && bash dav1d.cmd && bash fuzztest.cmd && bash libjpeg.cmd &&
bash libsharpyuv.cmd && bash libyuv.cmd && bash zlibpng.cmd && cd ..
# build libavif
mkdir build
cd build
EXTRA_CMAKE_FLAGS=""
if [[ "$FUZZING_ENGINE" == "libfuzzer" ]]; then
CXXFLAGS="${CXXFLAGS} -DFUZZTEST_COMPATIBILITY_MODE"
EXTRA_CMAKE_FLAGS="${EXTRA_CMAKE_FLAGS} -DAVIF_ENABLE_FUZZTEST=ON -DFUZZTEST_COMPATIBILITY_MODE=libfuzzer"
fi
cmake .. -G Ninja -DBUILD_SHARED_LIBS=OFF -DAVIF_CODEC_AOM=LOCAL -DAVIF_CODEC_DAV1D=LOCAL \
-DAVIF_CODEC_AOM_DECODE=ON -DAVIF_CODEC_AOM_ENCODE=ON \
-DAVIF_LOCAL_FUZZTEST=ON \
-DAVIF_JPEG=LOCAL -DAVIF_LIBSHARPYUV=LOCAL \
-DAVIF_LIBYUV=LOCAL -DAVIF_ZLIBPNG=LOCAL \
-DAVIF_BUILD_TESTS=ON -DAVIF_ENABLE_GTEST=OFF -DAVIF_ENABLE_WERROR=ON \
${EXTRA_CMAKE_FLAGS}
ninja
# build decode fuzzer
$CXX $CXXFLAGS -std=c++11 -I../include \
../tests/oss-fuzz/avif_decode_fuzzer.cc -o $OUT/avif_decode_fuzzer \
$LIB_FUZZING_ENGINE libavif.a ../ext/dav1d/build/src/libdav1d.a \
../ext/libyuv/build/libyuv.a ../ext/aom/build.libavif/libaom.a
# Restrict fuzztest tests to the only compatible fuzz engine: libfuzzer.
if [[ "$FUZZING_ENGINE" == "libfuzzer" ]]; then
# build fuzztests
# The following is taken from https://github.com/google/oss-fuzz/blob/31ac7244748ea7390015455fb034b1f4eda039d9/infra/base-images/base-builder/compile_fuzztests.sh#L59
# Iterate the fuzz binaries and list each fuzz entrypoint in the binary. For
# each entrypoint create a wrapper script that calls into the binaries the
# given entrypoint as argument.
# The scripts will be named:
# {binary_name}@{fuzztest_entrypoint}
FUZZ_TEST_BINARIES_OUT_PATHS=$(ls ./tests/avif_fuzztest_*)
echo "Fuzz binaries: $FUZZ_TEST_BINARIES_OUT_PATHS"
for fuzz_main_file in $FUZZ_TEST_BINARIES_OUT_PATHS; do
FUZZ_TESTS=$($fuzz_main_file --list_fuzz_tests | cut -d ' ' -f 4)
cp -f ${fuzz_main_file} $OUT/
fuzz_basename=$(basename $fuzz_main_file)
chmod -x $OUT/$fuzz_basename
for fuzz_entrypoint in $FUZZ_TESTS; do
TARGET_FUZZER="${fuzz_basename}@$fuzz_entrypoint"
# Write executer script
echo "#!/bin/sh
# LLVMFuzzerTestOneInput for fuzzer detection.
this_dir=\$(dirname \"\$0\")
export TEST_DATA_DIRS=\$this_dir/corpus
chmod +x \$this_dir/$fuzz_basename
\$this_dir/$fuzz_basename --fuzz=$fuzz_entrypoint -- \$@
chmod -x \$this_dir/$fuzz_basename" > $OUT/$TARGET_FUZZER
chmod +x $OUT/$TARGET_FUZZER
done
done
fi
# create a bigger seed corpus for avif_decode_fuzzer
cp $SRC/avif_decode_seed_corpus.zip $OUT/avif_decode_fuzzer_seed_corpus.zip
zip -j $OUT/avif_decode_fuzzer_seed_corpus.zip \
$(find $SRC/libavif/tests/data -maxdepth 1 -type f)
# copy seed corpus for fuzztest tests
unzip $OUT/avif_decode_fuzzer_seed_corpus.zip -d $OUT/corpus