Skip to content

Fix AVX-512 AudioChannelMixer tail over-read; guard-page buffers in kernel tests - #1633

Merged
Gin890 merged 6 commits into
mainfrom
claude/amazing-wu-0e15f4
Oct 21, 2026
Merged

Gin890 merged 6 commits into
mainfrom
claude/amazing-wu-0e15f4

Conversation

@Gin890

@Gin890 Gin890 commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

Fix a read past the end of the input in the AVX-512 kernel that mixes 2 audio channels into 1. Change the SIMD kernel tests to use guard-page buffers, so that they find this type of bug in each run.

GuardPageBuffer is a test array that ends right before a page that the program cannot access. A read or write past its end crashes the test at once.

The bug crashed the unit tests at random on CI runners with AVX-512, for example in #1619. It can also crash the program when it mixes stereo audio to mono. The bug is from #1551.

Other changes:

  • The AudioChannelMixer tests now compare all output channels, not only channel 0.
  • The image kernel tests use guard-page images too. These tests do not run yet, because they are not registered.

0 test files added, 15 test files changed:

  • SerialPrograms/Source/Kernels/AbsFFT/Kernels_AbsFFT_TestInfra.cpp
  • SerialPrograms/Source/Kernels/AudioChannelInterleave/Kernels_AudioChannelInterleave_TestInfra.cpp
  • SerialPrograms/Source/Kernels/AudioChannelMixer/Kernels_AudioChannelMixer_TestInfra.cpp
  • SerialPrograms/Source/Kernels/AudioPipeline/Kernels_AudioPipeline_RoundTrip_TestInfra.cpp
  • SerialPrograms/Source/Kernels/AudioPipeline/Kernels_AudioPipeline_Tests.cpp
  • SerialPrograms/Source/Kernels/AudioPipeline/Kernels_ChannelMixer_TestInfra.cpp
  • SerialPrograms/Source/Kernels/AudioResampler/Kernels_AudioResampler_Tests.cpp
  • SerialPrograms/Source/Kernels/AudioStreamConverter/Kernels_AudioStreamConverter_TestInfra.cpp
  • SerialPrograms/Source/Kernels/BinaryMatrix/Kernels_BinaryMatrix_Tests.cpp
  • SerialPrograms/Source/Kernels/ImageFilters/Kernels_ImageFilter_Tests.cpp
  • SerialPrograms/Source/Kernels/ImageStats/Kernels_ImagePixelSumSqrDev_TestInfra.cpp
  • SerialPrograms/Source/Kernels/ImageStats/Kernels_ImagePixelSumSqr_TestInfra.cpp
  • SerialPrograms/Source/Kernels/ScaleInvariantMatrixMatch/Kernels_ScaleInvariantMatrixMatch_TestInfra.cpp
  • SerialPrograms/Source/Kernels/SpikeConvolution/Kernels_SpikeConvolution_TestInfra.cpp
  • SerialPrograms/Source/Kernels/Waterfill/Kernels_Waterfill_Tests.cpp

Test results: before the fix, the new tests crashed each time on an AVX-512 runner (run). With the fix, all tests pass with AVX-512 (Ubuntu clang, Windows MSVC) and without it (Windows clang).

🤖 Generated with Claude Code

Gin and others added 4 commits October 19, 2026 19:38
The tail of mix_channels_x64_AVX512<2, 1> loaded input channel 1 with a
plain _mm512_loadu_ps(). When fewer than 16 samples remain, that reads up
to 60 bytes past the end of the channel. If the channel ends next to an
unmapped page, this faults. That is the intermittent segfault in the
"x64_AVX512(2 -> 1 x 18)" unit test on CI runners with AVX512, and the
same path runs for stereo -> mono mixing in ChannelMixer.

Use _mm512_maskz_loadu_ps() like the other tails. Masked-off lanes of a
masked load never fault.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…hannel.

Add GuardPageBuffer: an array whose last element sits right before a
no-access page (mmap + mprotect, or VirtualAlloc + VirtualProtect on
Windows). Reading or writing even one element past the end faults right
away.

The AudioChannelMixer tests now put the input and the output of the kernel
under test in such buffers. A SIMD tail that loads or stores past the end
then crashes on every run. Before, it only crashed when the heap happened to
end there, which is how the AVX512 2 -> 1 over-read slipped through as a
rare CI segfault.

The tests also compared only output channel 0. Compare all of them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Use GuardPageBuffer for the buffers that the kernels under test read and
write, so a tail that reads or writes past the end faults on every run:

- AbsFFT, AudioChannelInterleave, AudioStreamConverter, ImageStats
  (pixel_sum_sqr, sum_sqr_deviation): inputs and outputs.
- SpikeConvolution: "in", "kernel" and the ISA output, which is now exactly
  the documented size (outputs rounded up to 16 floats). The buffers are
  mapped once per test, and each input length uses the end of them.
- ScaleInvariantMatrixMatch: all matrices. The tail padding is gone, so the
  last row ends at the guard page.
- AudioPipeline and AudioResampler: the inputs, and the resampler block
  kernel outputs.

GuardPageBuffer gets an optional alignment (AbsFFT needs 64-byte aligned
buffers, SpikeConvolution a 64-byte aligned output) and move support.

The image filter, BinaryMatrix and Waterfill tests are unchanged: they run
on image files through ImageRGB32, which owns its memory.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add GuardPageImageRGB32 (Tests/GuardPageImage.h): an RGB32 image with no row
padding (bytes_per_row = width * 4) whose last row ends right before a
no-access page. ImageRGB32 pads rows to 64 bytes, so tests on it never notice
a kernel that reads or writes a little past the end of a row.

The ImageFilters, BinaryMatrix and Waterfill tests now copy the test image
into one, and the filter outputs are guarded images too.

These tests are not registered yet (their add_tests functions are empty), so
this only takes effect once they are.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@Mysticial Mysticial left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved, after addressing comments.

Gin and others added 2 commits October 20, 2026 22:26
Review feedback on PR 1633. The Default implementation is a kernel as well,
so its output in the AudioChannelMixer and SpikeConvolution tests now ends at
a guard page too. SpikeConvolution gives both outputs the documented output
size, so OUTPUT_PAD is gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review request on PR 1633. The comments say why the class exists, how it
places the data next to the guard page, where the tests use it, and its
limits.
No functional change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Gin890
Gin890 merged commit 3ce2f8a into main Oct 21, 2026
7 checks passed
@Gin890
Gin890 deleted the claude/amazing-wu-0e15f4 branch October 21, 2026 06:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants