From 9504a5389e163aade9dbe1990337cb115259f0a0 Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Thu, 4 Dec 2025 18:49:26 +0000 Subject: [PATCH 1/5] ASAN tests --- .github/workflows/asan.yml | 88 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 .github/workflows/asan.yml diff --git a/.github/workflows/asan.yml b/.github/workflows/asan.yml new file mode 100644 index 00000000..a963f128 --- /dev/null +++ b/.github/workflows/asan.yml @@ -0,0 +1,88 @@ +name: Address Sanitizer Tests + +on: + push: + branches: + - main + pull_request: + workflow_dispatch: + +defaults: + run: + shell: bash + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + clang_ASAN_UBSAN: + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + fetch-tags: true + + - name: Install system dependencies + run: | + brew install mpfr fftw cmake + + - name: Set up LLVM + run: | + brew install llvm@19 + LLVM_PREFIX=$(brew --prefix llvm@19) + echo "CC=$LLVM_PREFIX/bin/clang" >> $GITHUB_ENV + echo "CXX=$LLVM_PREFIX/bin/clang++" >> $GITHUB_ENV + echo "LDFLAGS=-L$LLVM_PREFIX/lib" >> $GITHUB_ENV + echo "CPPFLAGS=-I$LLVM_PREFIX/include" >> $GITHUB_ENV + + - name: Set up pyenv + run: | + git clone https://github.com/pyenv/pyenv.git "$HOME/.pyenv" + PYENV_ROOT="$HOME/.pyenv" + PYENV_BIN="$PYENV_ROOT/bin" + PYENV_SHIMS="$PYENV_ROOT/shims" + echo "$PYENV_BIN" >> $GITHUB_PATH + echo "$PYENV_SHIMS" >> $GITHUB_PATH + echo "PYENV_ROOT=$PYENV_ROOT" >> $GITHUB_ENV + + - name: Check pyenv is working + run: pyenv --version + + - name: Build CPython with address sanitizer + run: | + CONFIGURE_OPTS="--with-address-sanitizer" pyenv install 3.14t + pyenv global 3.14t + + - name: Install Python build dependencies + run: | + pip install meson meson-python ninja cython pytest hypothesis wheel build patchelf pytest-timeout + + - name: Clone and build NumPy with ASan + run: | + git clone --depth 1 https://github.com/numpy/numpy.git numpy-asan + cd numpy-asan + git submodule update --init --recursive + # Build NumPy with address sanitizer using pip + pip install . -v --no-build-isolation \ + -Csetup-args=-Db_sanitize=address,undefined \ + -Csetup-args=-Db_lundef=false + + - name: Build and install quaddtype with ASan + working-directory: quaddtype + run: | + pip install .[test] -v --no-build-isolation \ + -Csetup-args=-Db_sanitize=address,undefined \ + -Csetup-args=-Db_lundef=false + + - name: Run quaddtype tests with ASan + working-directory: quaddtype + run: | + # pass -s to pytest to see ASAN errors and warnings, otherwise pytest captures them + ASAN_OPTIONS=detect_leaks=0:symbolize=1:strict_init_order=true:allocator_may_return_null=1 \ + UBSAN_OPTIONS=halt_on_error=1 \ + pytest -vvv -s --color=yes --timeout=600 --durations=10 From 00a4b9f339d1087986a33eac3b2ba7a3a4be5719 Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Thu, 4 Dec 2025 19:07:54 +0000 Subject: [PATCH 2/5] dont halt --- .github/workflows/asan.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/asan.yml b/.github/workflows/asan.yml index a963f128..f4594e47 100644 --- a/.github/workflows/asan.yml +++ b/.github/workflows/asan.yml @@ -83,6 +83,7 @@ jobs: working-directory: quaddtype run: | # pass -s to pytest to see ASAN errors and warnings, otherwise pytest captures them + # Note: UBSAN halt_on_error=0 because NumPy has some UBSAN issues that would abort tests ASAN_OPTIONS=detect_leaks=0:symbolize=1:strict_init_order=true:allocator_may_return_null=1 \ - UBSAN_OPTIONS=halt_on_error=1 \ + UBSAN_OPTIONS=halt_on_error=0 \ pytest -vvv -s --color=yes --timeout=600 --durations=10 From 09e0e2f92072f8c79f5d2bb08bbe18f4c1d2cae0 Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Thu, 4 Dec 2025 19:33:28 +0000 Subject: [PATCH 3/5] filter only quaddtype + separete logs --- .github/workflows/asan.yml | 47 ++++++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/.github/workflows/asan.yml b/.github/workflows/asan.yml index f4594e47..37f4b6d7 100644 --- a/.github/workflows/asan.yml +++ b/.github/workflows/asan.yml @@ -82,8 +82,47 @@ jobs: - name: Run quaddtype tests with ASan working-directory: quaddtype run: | - # pass -s to pytest to see ASAN errors and warnings, otherwise pytest captures them + # Create a directory for sanitizer logs + mkdir -p ${{ github.workspace }}/sanitizer_logs + + # Run tests with sanitizer output redirected to log files # Note: UBSAN halt_on_error=0 because NumPy has some UBSAN issues that would abort tests - ASAN_OPTIONS=detect_leaks=0:symbolize=1:strict_init_order=true:allocator_may_return_null=1 \ - UBSAN_OPTIONS=halt_on_error=0 \ - pytest -vvv -s --color=yes --timeout=600 --durations=10 + ASAN_OPTIONS=detect_leaks=0:symbolize=1:strict_init_order=true:allocator_may_return_null=1:log_path=${{ github.workspace }}/sanitizer_logs/asan \ + UBSAN_OPTIONS=halt_on_error=0:log_path=${{ github.workspace }}/sanitizer_logs/ubsan \ + pytest -vvv --color=yes --timeout=600 --durations=10 + + - name: Display quaddtype sanitizer warnings + if: always() + run: | + echo "==========================================" + echo "QUADDTYPE SANITIZER WARNINGS SUMMARY" + echo "==========================================" + + # Combine all sanitizer logs and filter for quaddtype-related issues + if ls ${{ github.workspace }}/sanitizer_logs/* 1> /dev/null 2>&1; then + cat ${{ github.workspace }}/sanitizer_logs/* 2>/dev/null | \ + grep -A2 -B2 "quaddtype\|_quaddtype\|numpy_quaddtype" | \ + sort -u || echo "No quaddtype-specific sanitizer warnings found." + else + echo "No sanitizer log files found." + fi + + echo "" + echo "==========================================" + echo "ASAN LOGS" + echo "==========================================" + if ls ${{ github.workspace }}/sanitizer_logs/asan* 1> /dev/null 2>&1; then + cat ${{ github.workspace }}/sanitizer_logs/asan* 2>/dev/null || echo "No ASAN logs available." + else + echo "No ASAN log files found." + fi + + echo "" + echo "==========================================" + echo "UBSAN LOGS" + echo "==========================================" + if ls ${{ github.workspace }}/sanitizer_logs/ubsan* 1> /dev/null 2>&1; then + cat ${{ github.workspace }}/sanitizer_logs/ubsan* 2>/dev/null || echo "No UBSAN logs available." + else + echo "No UBSAN log files found." + fi From 77e437fc1e32125f0f92823498338ae9fbfc02fb Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Thu, 4 Dec 2025 19:38:42 +0000 Subject: [PATCH 4/5] log separate --- .github/workflows/{asan.yml => compiler_sanitization.yml} | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) rename .github/workflows/{asan.yml => compiler_sanitization.yml} (97%) diff --git a/.github/workflows/asan.yml b/.github/workflows/compiler_sanitization.yml similarity index 97% rename from .github/workflows/asan.yml rename to .github/workflows/compiler_sanitization.yml index 37f4b6d7..5629474c 100644 --- a/.github/workflows/asan.yml +++ b/.github/workflows/compiler_sanitization.yml @@ -1,4 +1,4 @@ -name: Address Sanitizer Tests +name: Compiler Sanitizer Tests on: push: @@ -75,6 +75,7 @@ jobs: - name: Build and install quaddtype with ASan working-directory: quaddtype run: | + # Build with sanitizers - these flags propagate to subprojects (SLEEF, qblas) by default pip install .[test] -v --no-build-isolation \ -Csetup-args=-Db_sanitize=address,undefined \ -Csetup-args=-Db_lundef=false From a2a0f190522e7910a9fddb9086973a98ac33e3fe Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Fri, 5 Dec 2025 08:22:46 +0000 Subject: [PATCH 5/5] fail if found --- .github/workflows/compiler_sanitization.yml | 33 +++++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/.github/workflows/compiler_sanitization.yml b/.github/workflows/compiler_sanitization.yml index 5629474c..128dbd83 100644 --- a/.github/workflows/compiler_sanitization.yml +++ b/.github/workflows/compiler_sanitization.yml @@ -95,19 +95,6 @@ jobs: - name: Display quaddtype sanitizer warnings if: always() run: | - echo "==========================================" - echo "QUADDTYPE SANITIZER WARNINGS SUMMARY" - echo "==========================================" - - # Combine all sanitizer logs and filter for quaddtype-related issues - if ls ${{ github.workspace }}/sanitizer_logs/* 1> /dev/null 2>&1; then - cat ${{ github.workspace }}/sanitizer_logs/* 2>/dev/null | \ - grep -A2 -B2 "quaddtype\|_quaddtype\|numpy_quaddtype" | \ - sort -u || echo "No quaddtype-specific sanitizer warnings found." - else - echo "No sanitizer log files found." - fi - echo "" echo "==========================================" echo "ASAN LOGS" @@ -127,3 +114,23 @@ jobs: else echo "No UBSAN log files found." fi + + - name: Check for quaddtype sanitizer issues + if: always() + run: | + # Fail if any quaddtype-related sanitizer issues are found + QUADDTYPE_ISSUES="" + if ls ${{ github.workspace }}/sanitizer_logs/* 1> /dev/null 2>&1; then + QUADDTYPE_ISSUES=$(cat ${{ github.workspace }}/sanitizer_logs/* 2>/dev/null | \ + grep -E "quaddtype|_quaddtype|numpy_quaddtype" || true) + fi + + if [ -n "$QUADDTYPE_ISSUES" ]; then + echo "==========================================" + echo "ERROR: Sanitizer issues found in quaddtype!" + echo "==========================================" + echo "$QUADDTYPE_ISSUES" + exit 1 + else + echo "No quaddtype-specific sanitizer issues found." + fi