From 6b4d997f6826ee7c9f7a814d8090727b27fb80f4 Mon Sep 17 00:00:00 2001 From: javi11 Date: Sat, 25 Apr 2026 17:30:30 +0200 Subject: [PATCH] fix(par2): skip PAR2 creation for files smaller than SIMD alignment The par2go C backend may read up to (stride-1) bytes past the input buffer when the slice size isn't a multiple of the SIMD stride (64 B on AVX-512). PR #189 fixed this for files >=128 B by rounding the slice size down to a 128-byte boundary, but the else branch still fed sub-stride slices (e.g. 8 B for a 10-byte file) into the C library, causing intermittent segfaults on Linux x86_64 CI runners. Crashes were probabilistic because the overrun only segfaults when the read crosses into an unmapped page, which depends on heap layout, ASLR, and allocator state. Locally on macOS the SIMD path differs and the bug stays latent. Fix: skip PAR2 entirely for files <128 B (SIMD-safe alignment), matching the existing skip-with-warning pattern. Files that small yield no meaningful recovery data anyway, the upload pipeline already tolerates a nil par2 result, and the existing 10-byte regression test was written assuming "skip" is a valid outcome. --- internal/par2/par2.go | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/internal/par2/par2.go b/internal/par2/par2.go index 5e5787c..ab6560b 100644 --- a/internal/par2/par2.go +++ b/internal/par2/par2.go @@ -218,18 +218,15 @@ func (p *NativeExecutor) createPar2ForFile(ctx context.Context, file fileinfo.Fi // clamping to prevent buffer overreads and segfaults. if file.Size > 0 && parBlockSize > file.Size { const simdSafeAlignment = uint64(128) - if file.Size >= simdSafeAlignment { - parBlockSize = (file.Size / simdSafeAlignment) * simdSafeAlignment - } else { - // File too small for 128-byte alignment; round to nearest multiple of 4 (PAR2 spec) - parBlockSize = (file.Size / 4) * 4 - } - if parBlockSize < 4 { - // File is smaller than minimum valid PAR2 slice size — skip creation - slog.WarnContext(ctx, "File too small for PAR2 creation, skipping", + if file.Size < simdSafeAlignment { + // File smaller than SIMD-safe alignment — par2go's C backend may read + // past the buffer end with sub-stride slice sizes, causing a segfault + // on AVX-512 hardware. Skip PAR2 creation for such tiny files. + slog.WarnContext(ctx, "File too small for SIMD-safe PAR2 creation, skipping", "path", file.Path, "size", file.Size) return nil, nil } + parBlockSize = (file.Size / simdSafeAlignment) * simdSafeAlignment } // PAR2 spec requires slice size to be a multiple of 4 parBlockSize = alignDown(parBlockSize, 4)