diff --git a/.github/workflows/ASan.yml b/.github/workflows/ASan.yml index 2884983f..734b940b 100644 --- a/.github/workflows/ASan.yml +++ b/.github/workflows/ASan.yml @@ -44,15 +44,24 @@ jobs: RSPM: https://packagemanager.rstudio.com/cran/__linux__/noble/latest USING_ASAN: true GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} - ASAN_OPTIONS: detect_container_overflow=1:verify_asan_link_order=0 + # detect_leaks=0 matches CRAN's gcc-ASAN setup; LSan otherwise + # reports noisy leaks from third-party libraries (libcrypto, + # libxml2) and even from the sed binary that test discovery + # shells out to. We rely on valgrind for leak coverage. + ASAN_OPTIONS: detect_container_overflow=1:verify_asan_link_order=0:detect_leaks=0 steps: - uses: actions/checkout@v6 + - name: Lower ASLR entropy for ASan + # Defence-in-depth alongside the LD_PRELOAD step below: + # ubuntu-24.04 runners ship a high vm.mmap_rnd_bits that can + # interact poorly with ASan's shadow memory layout + # (google/sanitizers#856, llvm/llvm-project#85780). + run: sudo sysctl -w vm.mmap_rnd_bits=28 + - name: Initialize ASan configuration run: | - export LD_PRELOAD=$(gcc -print-file-name=libasan.so) - echo "PKG_CFLAGS = -g -O0 -fsanitize=address -fno-omit-frame-pointer" > src/Makevars echo "PKG_CXXFLAGS = -g -O0 -fsanitize=address -fno-omit-frame-pointer" >> src/Makevars @@ -78,5 +87,13 @@ jobs: cd TreeTools - name: ASAN - memcheck ${{ matrix.config.test }} + # LD_PRELOAD libasan.so so the sanitizer initialises at R + # process startup, before R's heap and any package loaded by + # the test script can occupy the address range ASan needs for + # its shadow region. Without this, libasan is loaded only when + # R dlopen()s an instrumented package's .so, which works for + # the small examples/vignettes scripts but aborts for the + # tests subjob once testthat's dependency stack is in memory. run: | - Rscript memcheck/${{ matrix.config.test }}.R + LD_PRELOAD=$(gcc -print-file-name=libasan.so) \ + Rscript memcheck/${{ matrix.config.test }}.R