From 6f2831fbdbc3e37d85ce23a5d1e51c1e663efede Mon Sep 17 00:00:00 2001 From: javi11 Date: Tue, 28 Apr 2026 14:57:37 +0200 Subject: [PATCH] fix(par2): fall back to article-size block when SliceSize exceeds file size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the configured SliceSize is larger than the file being processed, the previous code clamped it to (file.Size/128)*128, which produces a block size ≈ file.Size. This creates only 1-2 input slices with a nearly-zero last slice — a pathological configuration that triggers undefined behavior in the ParPar C SIMD backend (AVX-512) on Linux x86_64, causing a segfault in CI. Instead, fall back to calculateParBlockSize() which yields a sensible number of equal slices (same as par2go's own test suite uses), and is known-safe on all platforms. --- internal/par2/par2.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/internal/par2/par2.go b/internal/par2/par2.go index ab6560b..353fd08 100644 --- a/internal/par2/par2.go +++ b/internal/par2/par2.go @@ -206,9 +206,13 @@ func (p *NativeExecutor) CreateInDirectory(ctx context.Context, files []fileinfo // createPar2ForFile creates PAR2 files for a single input file in the given directory. func (p *NativeExecutor) createPar2ForFile(ctx context.Context, file fileinfo.FileInfo, dirPath string) ([]string, error) { var parBlockSize uint64 - if p.cfg.SliceSize > 0 { + if p.cfg.SliceSize > 0 && uint64(p.cfg.SliceSize) <= file.Size { parBlockSize = uint64(p.cfg.SliceSize) } else { + // Configured SliceSize exceeds file size (or is unset): fall back to + // article-size-based calculation. Clamping SliceSize to ≈file.Size + // creates only 1-2 slices with a nearly-zero last slice, which triggers + // undefined behavior in the ParPar C SIMD backend on Linux x86_64 (AVX-512). parBlockSize = calculateParBlockSize(file.Size, p.articleSize) } // Guard: block size must not exceed file size AND must be SIMD-aligned.