From 59d868bdf1ebd15ffd7ac78d9704dbdad71240eb Mon Sep 17 00:00:00 2001 From: Markos Fountoulakis <markos.fountoulakis.senior@gmail.com> Date: Tue, 22 Jun 2021 11:24:37 +0300 Subject: [PATCH] Run sanitizer tests on PG12 Change sanitizer test to run on PG12 and make it use the same infrastructure as the other linux regression tests. Co-authored-by: Sven Klemm <sven@timescale.com> --- .../workflows/sanitizer-build-and-test.yaml | 146 ++++++++++++++++++ scripts/export_prefix_check.sh.in | 17 ++ scripts/suppressions/suppr_leak.txt | 3 + scripts/suppressions/suppr_ub.txt | 14 +- 4 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/sanitizer-build-and-test.yaml diff --git a/.github/workflows/sanitizer-build-and-test.yaml b/.github/workflows/sanitizer-build-and-test.yaml new file mode 100644 index 000000000..48ab7a903 --- /dev/null +++ b/.github/workflows/sanitizer-build-and-test.yaml @@ -0,0 +1,146 @@ +name: Sanitizer test +on: + schedule: + # run daily 20:00 on master branch + - cron: '0 20 * * *' + push: + branches: + - prerelease_test +env: + name: "Sanitizer" + PG_SRC_DIR: "pgbuild" + PG_INSTALL_DIR: "postgresql" + MAKE_JOBS: 6 + # llvm-symbolizer crashes so we don't use clang until we resolve that + extra_packages: "clang-10 llvm-10 llvm-10-dev llvm-10-tools" + llvm_config: "llvm-config-10" + CLANG: "clang-10" + # gcc-10 is the minimum version that can parse the suppression files barely adequately + CC: "gcc-10" + CXX: "g++-10" + # gcc CFLAGS, disable inlining for function name pattern matching to work for suppressions + CFLAGS: "-g -fsanitize=address,undefined -fno-omit-frame-pointer -O1 -fno-inline" + CXXFLAGS: "-g -fsanitize=address,undefined -fno-omit-frame-pointer -O1 -fno-inline" + # clang CFLAGS + #CFLAGS: "-g -fsanitize=address,undefined -fno-omit-frame-pointer -O1 -fno-inline-functions" + #CXXFLAGS: "-g -fsanitize=address,undefined -fno-omit-frame-pointer -O1 -fno-inline-functions" + + # We do not link libasan dynamically to avoid problems with libdl and our libraries. + # clang does this by default, but we need to explicitly state that for gcc. + # static gcc LDFLAGS + LDFLAGS: "-fsanitize=address,undefined -static-libasan -static-liblsan -static-libubsan" + # static sanitizer clang LDFLAGS or dynamic sanitizer gcc LDFLAGS + #LDFLAGS: "-fsanitize=address,undefined" + ASAN_OPTIONS: suppressions=${{ github.workspace }}/scripts/suppressions/suppr_asan.txt detect_odr_violation=0 log_path=${{ github.workspace }}/sanitizer.log log_exe_name=true print_suppressions=false exitcode=27 external_symbolizer_path=/usr/lib/llvm-10/bin/llvm-symbolizer + LSAN_OPTIONS: suppressions=${{ github.workspace }}/scripts/suppressions/suppr_leak.txt print_suppressions=0 log_path=${{ github.workspace }}/sanitizer.log log_exe_name=true print_suppressions=false exitcode=27 external_symbolizer_path=/usr/lib/llvm-10/bin/llvm-symbolizer + UBSAN_OPTIONS: suppressions=${{ github.workspace }}/scripts/suppressions/suppr_ub.txt print_stacktrace=1 halt_on_error=1 log_path=${{ github.workspace }}/sanitizer.log log_exe_name=true print_suppressions=false exitcode=27 external_symbolizer_path=/usr/lib/llvm-10/bin/llvm-symbolizer +jobs: + sanitizer: + name: PG${{ matrix.pg }} Sanitizer ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + # "os" has to be in the matrix due to a bug in "env": https://github.community/t/how-to-use-env-context/16975 + os: ["ubuntu-20.04"] + pg: ["12.7", "13.3"] + steps: + - name: Install Linux Dependencies + run: | + sudo apt-get update + sudo apt-get install flex bison lcov systemd-coredump gdb libipc-run-perl libtest-most-perl ${{ env.extra_packages }} + + # we cache the build directory instead of the install directory here + # because extension installation will write files to install directory + # leading to a tainted cache + - name: Cache PostgreSQL ${{ matrix.pg }} + id: cache-postgresql + uses: actions/cache@v2 + with: + path: ~/${{ env.PG_SRC_DIR }} + key: ${{ matrix.os }}-${{ env.name }}-postgresql-${{ matrix.pg }}-${{ env.CC }} + + - name: Checkout TimescaleDB + uses: actions/checkout@v2 + + - name: Build PostgreSQL ${{ matrix.pg }} if not in cache + if: steps.cache-postgresql.outputs.cache-hit != 'true' + run: | + wget -q -O postgresql.tar.bz2 https://ftp.postgresql.org/pub/source/v${{ matrix.pg }}/postgresql-${{ matrix.pg }}.tar.bz2 + mkdir -p ~/$PG_SRC_DIR + tar --extract --file postgresql.tar.bz2 --directory ~/$PG_SRC_DIR --strip-components 1 + cd ~/$PG_SRC_DIR + ./configure --prefix=$HOME/$PG_INSTALL_DIR --enable-debug --enable-cassert --with-openssl --without-readline --without-zlib --without-libxml + make -j $MAKE_JOBS + make -j $MAKE_JOBS -C src/test/isolation + make -j $MAKE_JOBS -C contrib/postgres_fdw + + - name: Install PostgreSQL ${{ matrix.pg }} + run: | + make -C ~/$PG_SRC_DIR install + make -C ~/$PG_SRC_DIR/contrib/postgres_fdw install + + - name: Build TimescaleDB + run: | + ./bootstrap -DCMAKE_BUILD_TYPE=Debug -DPG_SOURCE_DIR=~/$PG_SRC_DIR -DPG_PATH=~/$PG_INSTALL_DIR -DCODECOVERAGE=OFF + make -j $MAKE_JOBS -C build + make -C build install + + - name: make installcheck + run: | + set -o pipefail + # IGNORE some test since they fail under ASAN. At least the remote_txn + # test seems to fail due to a PostgreSQL bug where AbortStartTime in + # postmaster.c is not atomic but read/written across signal handlers + # and ServerLoop. + make -k -C build installcheck SKIPS='remote_txn' IGNORES='bgw_db_scheduler' | tee installcheck.log + + - name: Show regression diffs + if: always() + id: collectlogs + run: | + find . -name regression.diffs -exec cat {} + > regression.log + find . -name postmaster.log -exec cat {} + > postgres.log + if [[ "${{ runner.os }}" == "Linux" ]] ; then + # wait in case there are in-progress coredumps + sleep 10 + if coredumpctl -q list >/dev/null; then echo "::set-output name=coredumps::true"; fi + fi + if [[ -s regression.log ]]; then echo "::set-output name=regression_diff::true"; fi + grep -e 'FAILED' -e 'failed (ignored)' installcheck.log || true + cat regression.log + + - name: Save regression diffs + if: always() && steps.collectlogs.outputs.regression_diff == 'true' + uses: actions/upload-artifact@v2 + with: + name: Regression diff ${{ matrix.os }} ${{ env.name }} ${{ matrix.pg }} + path: regression.log + + - name: Save postmaster.log + if: always() + uses: actions/upload-artifact@v2 + with: + name: PostgreSQL log ${{ matrix.os }} ${{ env.name }} ${{ matrix.pg }} + path: postgres.log + + - name: Stack trace + if: always() && steps.collectlogs.outputs.coredumps == 'true' + run: | + echo "bt full" | sudo coredumpctl gdb + ./scripts/bundle_coredumps.sh + false + + - name: Coredumps + if: always() && steps.collectlogs.outputs.coredumps == 'true' + uses: actions/upload-artifact@v2 + with: + name: Coredumps ${{ matrix.os }} ${{ env.name }} ${{ matrix.pg }} + path: coredumps + + - name: sanitizer logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: sanitizer logs ${{ matrix.os }} ${{ env.name }} ${{ matrix.pg }} + path: ${{ github.workspace }}/sanitizer.log.* diff --git a/scripts/export_prefix_check.sh.in b/scripts/export_prefix_check.sh.in index 8e7a8180e..bc9411440 100755 --- a/scripts/export_prefix_check.sh.in +++ b/scripts/export_prefix_check.sh.in @@ -26,6 +26,13 @@ fi # loader_hello used to test that our name collision resistance works # test_symbol_conflict used to test that our name collision resistance works # tsl_license_update_check used to check for valid license +# __sanitizer.* __sancov.* llvm sanitizer +# _ZN11__sanitizer.* llvm sanitizer +# __asan.* __odr_asan.* address sanitizer +# __ubsan.* _ZN7__ubsan.* undefined behaviour sanitizer +# internal_sigreturn gcc +# OnPrint gcc +# backtrace_uncompress_zdebug libbacktrace # all of these symbols start with an additional leading '_' on macos exports=$(find @CMAKE_BINARY_DIR@ -not -path '*/\.*' -name '*.so' -print0 \ | xargs -0 @NM@ ${DEFINED_ONLY} ${EXTERN_ONLY} \ @@ -50,6 +57,16 @@ exports=$(find @CMAKE_BINARY_DIR@ -not -path '*/\.*' -name '*.so' -print0 \ -e '^_\?timescaledb_' \ -e '^_\?loader_hello$' \ -e '^_\?test_symbol_conflict$' \ + -e '^_\?__sanitizer' \ + -e '^_\?__sancov' \ + -e '^_\?__asan' \ + -e '^_\?__odr_asan' \ + -e '^_\?__ubsan' \ + -e '^_\?_ZN7__ubsan' \ + -e '^_\?_ZN11__sanitizer' \ + -e '^_\?internal_sigreturn$' \ + -e '^_\?OnPrint$' \ + -e '^_\?backtrace_uncompress_zdebug$' \ ) num_exports=$(echo "${exports}" | grep -v '^$' | wc -l) diff --git a/scripts/suppressions/suppr_leak.txt b/scripts/suppressions/suppr_leak.txt index d9093897a..cd5c732b8 100644 --- a/scripts/suppressions/suppr_leak.txt +++ b/scripts/suppressions/suppr_leak.txt @@ -2,6 +2,8 @@ leak:save_ps_display_args leak:psql/startup.c #don't care about the frontend leaks leak:fe_memutils.c +leak:fe-connect.c +leak:fe-exec.c leak:initdb.c #annoingly have to supress strdup because it leaks in PostmasterMain -D option leak:strdup @@ -9,6 +11,7 @@ leak:ProcessConfigFileInternal leak:internal_load_library leak:pg_timezone_abbrev_initialize +leak:check_timezone_abbreviations leak:check_session_authorization leak:InitializeGUCOptions leak:CheckMyDatabase diff --git a/scripts/suppressions/suppr_ub.txt b/scripts/suppressions/suppr_ub.txt index 3735c6a21..7d782dae7 100644 --- a/scripts/suppressions/suppr_ub.txt +++ b/scripts/suppressions/suppr_ub.txt @@ -9,6 +9,18 @@ nonnull-attribute:TransactionIdSetPageStatus nonnull-attribute:SerializeTransactionState nonnull-attribute:initscan nonnull-attribute:SetTransactionSnapshot -nonnull-attribute:/usr/src/postgresql/src/fe_utils/print.c +nonnull-attribute:shm_mq_receive +#care, gcc cannot parse the path, only the filename +nonnull-attribute:*/src/fe_utils/print.c +nonnull-attribute:print_aligned_text +#PG13.3-copyfuncs.c:2374:2: runtime error: null pointer passed as argument 2, which is declared to never be null +nonnull-attribute:_copyAppendRelInfo +#PG13.3-copyfuncs.c:1190:2: runtime error: null pointer passed as argument 2, which is declared to never be null +nonnull-attribute:_copyLimit +nonnull-attribute:*/src/backend/nodes/copyfuncs.c +#PG12.7-relcache.c:5960:6: runtime error: null pointer passed as argument 1, which is declared to never be null +#in write_item postgresql-12.6/src/backend/utils/cache/relcache.c:5960 +#looks like a real postgresql bug +nonnull-attribute:write_item #division by 0, looks like a real postgres ug float-divide-by-zero:_bt_vacuum_needs_cleanup