From c5600ee5c08f09b36eb7db3ee22e189f3aa342d2 Mon Sep 17 00:00:00 2001
From: Egor Ivkov <e.o.ivkov@gmail.com>
Date: Tue, 19 Dec 2023 18:32:49 +0300
Subject: [PATCH] test/fuzz: support clusterfuzzlite

NO_DOC=internal
NO_TEST=internal
NO_CHANGELOG=internal

(cherry picked from commit 05b62fe0e7db8a6d10172c45cdc77cd9db2ec0e7)
---
 .clusterfuzzlite/Dockerfile   | 15 ++++++
 .clusterfuzzlite/build.sh     | 86 +++++++++++++++++++++++++++++++++++
 .clusterfuzzlite/project.yaml |  1 +
 test/fuzz/README.md           | 34 ++++++++++++++
 4 files changed, 136 insertions(+)
 create mode 100644 .clusterfuzzlite/Dockerfile
 create mode 100755 .clusterfuzzlite/build.sh
 create mode 100644 .clusterfuzzlite/project.yaml
 create mode 100644 test/fuzz/README.md

diff --git a/.clusterfuzzlite/Dockerfile b/.clusterfuzzlite/Dockerfile
new file mode 100644
index 0000000000..c501a1a1a7
--- /dev/null
+++ b/.clusterfuzzlite/Dockerfile
@@ -0,0 +1,15 @@
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y \
+    build-essential cmake make coreutils sed lld \
+    autoconf automake libtool zlib1g-dev \
+    libreadline-dev libncurses5-dev libssl-dev \
+    libunwind-dev luajit wget ninja-build \
+    libzstd-dev libyaml-dev libcurl4-openssl-dev
+
+RUN wget https://github.com/unicode-org/icu/releases/download/release-71-1/icu4c-71_1-src.tgz && \
+    tar xzvf ./icu4c-71_1-src.tgz -C $SRC
+
+COPY . $SRC/tarantool
+WORKDIR $SRC/tarantool
+
+COPY ./.clusterfuzzlite/build.sh $SRC/
diff --git a/.clusterfuzzlite/build.sh b/.clusterfuzzlite/build.sh
new file mode 100755
index 0000000000..149440f7fd
--- /dev/null
+++ b/.clusterfuzzlite/build.sh
@@ -0,0 +1,86 @@
+#!/bin/bash
+
+# Clean up potentially persistent build directory.
+[[ -e $SRC/tarantool/build ]] && rm -rf $SRC/tarantool/build
+
+# Build ICU for linking statically.
+mkdir -p $SRC/tarantool/build/icu && cd $SRC/tarantool/build/icu
+
+[ ! -e config.status ] && LDFLAGS="-lpthread" CXXFLAGS="$CXXFLAGS -lpthread" \
+  $SRC/icu/source/configure --disable-shared --enable-static --disable-layoutex \
+  --disable-tests --disable-samples --with-data-packaging=static
+make install -j$(nproc)
+
+# For fuzz-introspector, exclude all functions in the tests directory,
+# libprotobuf-mutator and protobuf source code.
+# See https://github.com/ossf/fuzz-introspector/blob/main/doc/Config.md#code-exclusion-from-the-report
+export FUZZ_INTROSPECTOR_CONFIG=$SRC/fuzz_introspector_exclusion.config
+cat > $FUZZ_INTROSPECTOR_CONFIG <<EOF
+FILES_TO_AVOID
+icu/
+tarantool/build/test
+EOF
+
+cd $SRC/tarantool
+
+case $SANITIZER in
+  address) SANITIZERS_ARGS="-DENABLE_ASAN=ON" ;;
+  undefined) SANITIZERS_ARGS="-DENABLE_UB_SANITIZER=ON" ;;
+  *) SANITIZERS_ARGS="" ;;
+esac
+
+: ${LD:="${CXX}"}
+: ${LDFLAGS:="${CXXFLAGS}"}  # to make sure we link with sanitizer runtime
+
+cmake_args=(
+    # Specific to Tarantool
+    -DENABLE_FUZZER=ON
+    -DOSS_FUZZ=ON
+    -DLUA_USE_APICHECK=ON
+    -DLUA_USE_ASSERT=ON
+    -DLUAJIT_USE_SYSMALLOC=ON
+    -DLUAJIT_ENABLE_GC64=ON
+    $SANITIZERS_ARGS
+
+    # C compiler
+    -DCMAKE_C_COMPILER="${CC}"
+    -DCMAKE_C_FLAGS="${CFLAGS} -Wno-error=unused-command-line-argument -fuse-ld=lld"
+
+    # C++ compiler
+    -DCMAKE_CXX_COMPILER="${CXX}"
+    -DCMAKE_CXX_FLAGS="${CXXFLAGS} -Wno-error=unused-command-line-argument -fuse-ld=lld"
+
+    # Linker
+    -DCMAKE_LINKER="${LD}"
+    -DCMAKE_EXE_LINKER_FLAGS="${LDFLAGS}"
+    -DCMAKE_MODULE_LINKER_FLAGS="${LDFLAGS}"
+    -DCMAKE_SHARED_LINKER_FLAGS="${LDFLAGS}"
+
+    # Dependencies
+    -DENABLE_BUNDLED_ZSTD=OFF
+)
+
+# To deal with a host filesystem from inside of container.
+git config --global --add safe.directory '*'
+
+# Build the project and fuzzers.
+[[ -e build ]] && rm -rf build
+cmake "${cmake_args[@]}" -S . -B build -G Ninja
+cmake --build build --target fuzzers --parallel
+
+# Archive and copy to $OUT seed corpus if the build succeeded.
+for f in $(find build/test/fuzz/ -name '*_fuzzer' -type f);
+do
+  name=$(basename $f);
+  module=$(echo $name | sed 's/_fuzzer//')
+  corpus_dir="test/static/corpus/$module"
+  echo "Copying for $module";
+  cp $f $OUT/
+  dict_path="test/static/$name.dict"
+  if [ -e "$dict_path" ]; then
+    cp $dict_path $OUT/
+  fi
+  if [ -e "$corpus_dir" ]; then
+    zip -j $OUT/"$name"_seed_corpus.zip $corpus_dir/*
+  fi
+done
diff --git a/.clusterfuzzlite/project.yaml b/.clusterfuzzlite/project.yaml
new file mode 100644
index 0000000000..b455aa397c
--- /dev/null
+++ b/.clusterfuzzlite/project.yaml
@@ -0,0 +1 @@
+language: c
diff --git a/test/fuzz/README.md b/test/fuzz/README.md
new file mode 100644
index 0000000000..b8bc41c6fc
--- /dev/null
+++ b/test/fuzz/README.md
@@ -0,0 +1,34 @@
+## Running Fuzzers Locally
+
+To check that fuzzing works locally first clone the **oss-fuzz** tools.
+
+```bash
+git clone https://github.com/google/oss-fuzz.git
+
+cd oss-fuzz
+```
+
+Build the docker image, which is used to build fuzzers.
+Then build the actual fuzz targets.
+`<path-to-tarantool>` is the path to the root of this repository.
+
+```bash
+python3 infra/helper.py build_image --external <path-to-tarantool>
+
+python3 infra/helper.py build_fuzzers --external <path-to-tarantool> --sanitizer=address
+```
+
+Run all fuzzers for a short period of time to check that they were built correctly.
+
+```bash
+python3 infra/helper.py check_build --external <path-to-tarantool> --sanitizer=address
+```
+
+To run a specific fuzzer execute the following command.
+Replace `<fuzz-target>` with any fuzzer in the `test/fuzz` directory. Example: `uri_fuzzer`
+
+```bash
+python3 infra/helper.py run_fuzzer --external <path-to-tarantool> <fuzzer-target>
+```
+
+For more information on fuzzing see [ClusterFuzzLite docs](https://google.github.io/clusterfuzzlite/build-integration/#testing-locally).
-- 
GitLab