From 80aec22623a86e2d726c0f9d01eb3acd694c7662 Mon Sep 17 00:00:00 2001 From: zhouyunding Date: Wed, 21 Oct 2026 19:25:11 +0800 Subject: [PATCH] Fix infinite loop in kiss_fft_next_fast_size for n<=0 (issue #121) kiss_fft_next_fast_size(0) never terminated because the factorization loop divides m by 2/3/5 forever when m stays 0. Per maintainer decision, return 1 for n<=0. Add regression test next_fast_size covering n=0, n<0 and positive inputs. --- kiss_fft.c | 2 ++ test/CMakeLists.txt | 2 ++ test/next_fast_size.c | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+) create mode 100644 test/next_fast_size.c diff --git a/kiss_fft.c b/kiss_fft.c index aba63e0..c97515f 100644 --- a/kiss_fft.c +++ b/kiss_fft.c @@ -411,6 +411,8 @@ void kiss_fft_cleanup(void) int kiss_fft_next_fast_size(int n) { + if (n <= 0) /* nothing to factor; avoid infinite loop for n<=0 */ + return 1; while(1) { int m=n; while ( (m%2) == 0 ) m/=2; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 0bd0938..505a748 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -49,6 +49,8 @@ target_compile_definitions(tkfc PRIVATE KFC_TEST) add_kissfft_test_executable(ffr twotonetest.c) add_kissfft_test_executable(tr test_real.c) +add_kissfft_test_executable(next_fast_size next_fast_size.c) + add_kissfft_test_executable(testcpp testcpp.cc) if(KISSFFT_DATATYPE MATCHES "^simd$") diff --git a/test/next_fast_size.c b/test/next_fast_size.c new file mode 100644 index 0000000..3d29109 --- /dev/null +++ b/test/next_fast_size.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2003-2010, Mark Borgerding. All rights reserved. + * This file is part of KISS FFT - https://github.com/mborgerding/kissfft + * + * SPDX-License-Identifier: BSD-3-Clause + * See COPYING file for more information. + * + * Regression test for github issue #121: kiss_fft_next_fast_size(0) + * used to hang forever in the factorization loop. + */ +#include "kiss_fft.h" +#include + +int main(void) +{ + int n; + /* n<=0 must return 1 per maintainer decision, not hang */ + if (kiss_fft_next_fast_size(0) != 1) { + fprintf(stderr, "FAIL: kiss_fft_next_fast_size(0) != 1\n"); + return 1; + } + if (kiss_fft_next_fast_size(-3) != 1) { + fprintf(stderr, "FAIL: kiss_fft_next_fast_size(-3) != 1\n"); + return 1; + } + /* positive inputs keep their pre-fix behavior */ + { + int expected[9] = { 0, 1, 2, 3, 4, 5, 6, 8, 8 }; + for (n = 1; n <= 8; ++n) { + if (kiss_fft_next_fast_size(n) != expected[n]) { + fprintf(stderr, "FAIL: kiss_fft_next_fast_size(%d) = %d, expected %d\n", + n, kiss_fft_next_fast_size(n), expected[n]); + return 1; + } + } + } + printf("kiss_fft_next_fast_size: all checks passed\n"); + return 0; +}