Skip to content

Commit c73b3aa

Browse files
authored
Merge pull request #836 from rgommers/ci-asan
CI/MAINT: add a CI job with ASan and UBSan on macOS, fix one UB issue
2 parents b8ddd4d + 5ec16ed commit c73b3aa

File tree

2 files changed

+62
-6
lines changed

2 files changed

+62
-6
lines changed

.github/workflows/tests.yml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,3 +243,61 @@ jobs:
243243
pytest --pyargs pywt
244244
fi
245245
popd
246+
247+
clang_ASan_UBSan:
248+
name: Test under ASan and UBSan
249+
runs-on: macos-latest
250+
steps:
251+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
252+
with:
253+
submodules: recursive
254+
fetch-tags: true
255+
persist-credentials: false
256+
257+
- name: Set up pyenv
258+
run: |
259+
git clone https://github.com/pyenv/pyenv.git "$HOME/.pyenv"
260+
PYENV_ROOT="$HOME/.pyenv"
261+
PYENV_BIN="$PYENV_ROOT/bin"
262+
PYENV_SHIMS="$PYENV_ROOT/shims"
263+
echo "$PYENV_BIN" >> $GITHUB_PATH
264+
echo "$PYENV_SHIMS" >> $GITHUB_PATH
265+
echo "PYENV_ROOT=$PYENV_ROOT" >> $GITHUB_ENV
266+
267+
- name: Set up LLVM
268+
run: |
269+
brew install llvm@19
270+
LLVM_PREFIX=$(brew --prefix llvm@19)
271+
echo CC="$LLVM_PREFIX/bin/clang" >> $GITHUB_ENV
272+
echo CXX="$LLVM_PREFIX/bin/clang++" >> $GITHUB_ENV
273+
echo LDFLAGS="-L$LLVM_PREFIX/lib" >> $GITHUB_ENV
274+
echo CPPFLAGS="-I$LLVM_PREFIX/include" >> $GITHUB_ENV
275+
276+
- name: Build Python with AddressSanitizer
277+
run: |
278+
CONFIGURE_OPTS="--with-address-sanitizer" pyenv install 3.14
279+
pyenv global 3.14
280+
281+
- name: Install NumPy dependencies from PyPI
282+
run: |
283+
pip install meson-python ninja cython
284+
285+
- name: Build NumPy with ASan
286+
run: |
287+
pip install numpy --no-binary numpy --no-build-isolation -Csetup-args="-Db_sanitize=address" -v
288+
289+
- name: Install dependencies from PyPI
290+
run: |
291+
pip install spin pytest pytest-timeout
292+
293+
- name: Build PyWavelets with ASan and UBSan
294+
run: |
295+
export CFLAGS=-fno-sanitize=function # suppressed upstream, see cython#7437
296+
spin build -- -Db_sanitize=address,undefined -Db_lundef=false
297+
298+
- name: Test
299+
run: |
300+
# pass -s to pytest to see ASAN errors and warnings, otherwise pytest captures them
301+
ASAN_OPTIONS=detect_leaks=0:symbolize=1:strict_init_order=true:allocator_may_return_null=1:use_sigaltstack=0 \
302+
UBSAN_OPTIONS=halt_on_error=1 \
303+
spin test -- -v -s --timeout=600 --durations=10

pywt/_extensions/c/wt.template.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,7 @@ int CAT(TYPE, _downcoef_axis)(const TYPE * const restrict input, const ArrayInfo
7777
}
7878

7979
for (i = 0; i < num_loops; ++i){
80-
size_t j;
81-
size_t input_offset = 0, output_offset = 0;
80+
pywt_index_t j, axis_idx, input_offset = 0, output_offset = 0;
8281
const TYPE * input_row;
8382
TYPE * output_row;
8483

@@ -88,7 +87,7 @@ int CAT(TYPE, _downcoef_axis)(const TYPE * const restrict input, const ArrayInfo
8887
for (j = 0; j < output_info.ndim; ++j){
8988
size_t j_rev = output_info.ndim - 1 - j;
9089
if (j_rev != axis){
91-
size_t axis_idx = reduced_idx % output_info.shape[j_rev];
90+
axis_idx = reduced_idx % output_info.shape[j_rev];
9291
reduced_idx /= output_info.shape[j_rev];
9392

9493
input_offset += (axis_idx * input_info.strides[j_rev]);
@@ -232,8 +231,7 @@ int CAT(TYPE, _idwt_axis)(const TYPE * const restrict coefs_a, const ArrayInfo *
232231
}
233232

234233
for (i = 0; i < num_loops; ++i){
235-
size_t j;
236-
size_t a_offset = 0, d_offset = 0, output_offset = 0;
234+
pywt_index_t j, axis_idx, a_offset = 0, d_offset = 0, output_offset = 0;
237235
TYPE * output_row;
238236

239237
// Calculate offset into linear buffer
@@ -242,7 +240,7 @@ int CAT(TYPE, _idwt_axis)(const TYPE * const restrict coefs_a, const ArrayInfo *
242240
for (j = 0; j < output_info.ndim; ++j){
243241
size_t j_rev = output_info.ndim - 1 - j;
244242
if (j_rev != axis){
245-
size_t axis_idx = reduced_idx % output_info.shape[j_rev];
243+
axis_idx = reduced_idx % output_info.shape[j_rev];
246244
reduced_idx /= output_info.shape[j_rev];
247245

248246
if (have_a)

0 commit comments

Comments
 (0)