Fix perform_fft ignoring get_window failure and transforming uninitialized memory - #852
Fix perform_fft ignoring get_window failure and transforming uninitialized memory#852adityasingh2400 wants to merge 3 commits into
Conversation
…itialized memory perform_fft allocates windowed_data with new double[data_len] and then calls get_window to fill it. It discards the return code. get_window returns INVALID_ARGUMENTS_ERROR without writing anything when window_function is not a valid WindowOperations value, so the very next loop multiplies the caller data into a buffer that was never initialized, and kiss_fftr transforms whatever bytes the allocator handed back. perform_fft then returns STATUS_OK, so the caller has no way to tell that the result is heap noise. This checks the code from get_window, frees windowed_data and returns the error. get_psd already checks the perform_fft return value, so the error now propagates the whole way up through get_psd_welch to get_band_power and get_custom_band_powers, and the language bindings raise instead of handing back a garbage spectrum. Valid window functions are unaffected.
|
The error propagation and cleanup look correct: the temporary allocation is released, the error is returned before the FFT runs, and valid window types keep the existing path. Please add a small error-path regression test asserting that an invalid window enum returns |
|
Sorry, that was codex and autoreview, change looks fine, thanks |
Asserts an invalid window enum returns INVALID_ARGUMENTS_ERROR and leaves both output buffers and the input untouched, and that a valid window still round-trips through fft and ifft.
|
Added For the untouched-buffers part I call the native On master it fails with |
|
I missed your follow-up before posting that, sorry. I had started on the tests when the first comment came in and did not re-check the thread before pushing. The test and the CI line are a separate commit, so if you would rather merge this as the one-line fix you already reviewed, say so and I will drop it. If you want to keep it, nothing further is needed. |
perform_fftallocateswindowed_datawithnew double[data_len]and callsget_windowto fill it, then discards the return code. Whenwindow_functionis not a validWindowOperationsvalue,get_windowreturnsINVALID_ARGUMENTS_ERRORwithout writing a single element. The very next loop doeswindowed_data[i] *= data[i]on that never initialized buffer,kiss_fftrtransforms the result, andperform_fftreturnsSTATUS_OK. The caller receives a spectrum computed from whatever bytes the allocator happened to hand back, with no indication anything went wrong.The fix checks the code from
get_window, freeswindowed_dataand returns the error.get_psdalready checks theperform_fftreturn value, so the error now propagates the whole way up throughget_psd_welchtoget_band_powerandget_custom_band_powers, and the language bindings raise instead of returning a garbage spectrum.Verified by building
libDataHandler.dylibon macOS arm64 and callingperform_fftwithwindow_function = 99. To make the uninitialized read observable rather than merely arguable, the harness supplies a global replacementoperator new[]that pre-fills every heap block with a chosen value. That is a standard C++ replacement function, so it covers thenew double[data_len]inside the library. Input is a pure 5 cycle sine over 64 samples, so all energy lands in bin 5.get_window(99)called directlyperform_fft(99)return codeThe reported spectrum was exactly
|heap contents| * FFT(data). Change the heap, the spectrum changes proportionally, and the function still reported success. After the fix the output buffers still hold the caller's-12345.0sentinel, so nothing is written on the error path.All four valid window functions are unaffected.
NO_WINDOW,HANNING,HAMMINGandBLACKMAN_HARRISall return 0 and round trip throughperform_ifftback towindow[i] * data[i]with maximum error between 2.371e-16 and 3.908e-16, identical before and after.All 9 signal processing examples that CI runs pass on this branch, and
clang-formatreports no changes on the touched file.One note for anyone reproducing this: valgrind and MemorySanitizer are both unavailable on macOS arm64, and an attempt using
MallocScribbleplus heap priming produces all zeros and proves nothing. Theoperator new[]replacement is what makes the read observable.Disclosure: this change was prepared with AI assistance. I have reviewed and tested it.