|
43 | 43 | - uses: chartboost/ruff-action@v1 |
44 | 44 |
|
45 | 45 |
|
| 46 | + asan_ubsan: |
| 47 | + |
| 48 | + runs-on: ubuntu-24.04 |
| 49 | + timeout-minutes: 25 |
| 50 | + needs: [lint] |
| 51 | + |
| 52 | + steps: |
| 53 | + - uses: actions/checkout@v4 |
| 54 | + with: |
| 55 | + # Just fetching one commit is not enough for setuptools-scm, so we fetch all. |
| 56 | + fetch-depth: 0 |
| 57 | + fetch-tags: true |
| 58 | + |
| 59 | + - name: Set up Python |
| 60 | + uses: actions/setup-python@v5 |
| 61 | + with: |
| 62 | + python-version: '3.12' |
| 63 | + |
| 64 | + - name: Install system packages |
| 65 | + run: | |
| 66 | + sudo apt-get update |
| 67 | + sudo apt-get install -y pkg-config build-essential |
| 68 | + sudo apt-get install -y libssl-dev libacl1-dev libxxhash-dev liblz4-dev libzstd-dev |
| 69 | +
|
| 70 | + - name: Install Python dependencies |
| 71 | + run: | |
| 72 | + python -m pip install --upgrade pip |
| 73 | + pip install -r requirements.d/development.txt |
| 74 | +
|
| 75 | + - name: Build Borg with ASan/UBSan |
| 76 | + # Build the C/Cython extensions with AddressSanitizer and UndefinedBehaviorSanitizer enabled. |
| 77 | + # How this works: |
| 78 | + # - The -fsanitize=address,undefined flags inject runtime checks into our native code. If a bug is hit |
| 79 | + # (e.g., buffer overflow, use-after-free, out-of-bounds, or undefined behavior), the sanitizer prints |
| 80 | + # a detailed error report to stderr, including a stack trace, and forces the process to exit with |
| 81 | + # non-zero status. In CI, this will fail the step/job so you will notice. |
| 82 | + # - ASAN_OPTIONS/UBSAN_OPTIONS configure the sanitizers' runtime behavior (see below for meanings). |
| 83 | + env: |
| 84 | + CFLAGS: "-O1 -g -fno-omit-frame-pointer -fsanitize=address,undefined" |
| 85 | + CXXFLAGS: "-O1 -g -fno-omit-frame-pointer -fsanitize=address,undefined" |
| 86 | + LDFLAGS: "-fsanitize=address,undefined" |
| 87 | + # ASAN_OPTIONS controls AddressSanitizer runtime tweaks: |
| 88 | + # - detect_leaks=0: Disable LeakSanitizer to avoid false positives with CPython/pymalloc in short-lived tests. |
| 89 | + # - strict_string_checks=1: Make invalid string operations (e.g., over-reads) more likely to be detected. |
| 90 | + # - check_initialization_order=1: Catch uses that depend on static initialization order (C++). |
| 91 | + # - detect_stack_use_after_return=1: Detect stack-use-after-return via stack poisoning (may increase overhead). |
| 92 | + ASAN_OPTIONS: "detect_leaks=0:strict_string_checks=1:check_initialization_order=1:detect_stack_use_after_return=1" |
| 93 | + # UBSAN_OPTIONS controls UndefinedBehaviorSanitizer runtime: |
| 94 | + # - print_stacktrace=1: Include a stack trace for UB reports to ease debugging. |
| 95 | + # Note: UBSan is recoverable by default (process may continue after reporting). If you want CI to |
| 96 | + # abort immediately and fail on the first UB, add `halt_on_error=1` (e.g., UBSAN_OPTIONS="print_stacktrace=1:halt_on_error=1"). |
| 97 | + UBSAN_OPTIONS: "print_stacktrace=1" |
| 98 | + # PYTHONDEVMODE enables additional Python runtime checks and warnings. |
| 99 | + PYTHONDEVMODE: "1" |
| 100 | + run: pip install -e . |
| 101 | + |
| 102 | + - name: Run tests under sanitizers |
| 103 | + env: |
| 104 | + ASAN_OPTIONS: "detect_leaks=0:strict_string_checks=1:check_initialization_order=1:detect_stack_use_after_return=1" |
| 105 | + UBSAN_OPTIONS: "print_stacktrace=1" |
| 106 | + PYTHONDEVMODE: "1" |
| 107 | + # Ensure the ASan runtime is loaded first to avoid "ASan runtime does not come first" warnings. |
| 108 | + # We discover libasan/libubsan paths via gcc and preload them for the Python test process. |
| 109 | + # the remote tests are slow and likely won't find anything useful |
| 110 | + run: | |
| 111 | + set -euo pipefail |
| 112 | + export LD_PRELOAD="$(gcc -print-file-name=libasan.so):$(gcc -print-file-name=libubsan.so)" |
| 113 | + echo "Using LD_PRELOAD=$LD_PRELOAD" |
| 114 | + pytest -v --benchmark-skip -k "not remote" |
| 115 | +
|
46 | 116 | posix_tests: |
47 | 117 |
|
48 | 118 | needs: [lint] |
|
0 commit comments