Skip to content

Fix AudioResampler crash on empty buffer input#8364

Open
struktured wants to merge 1 commit into
LMMS:masterfrom
struktured-labs:fix-audioresampler-empty-span
Open

Fix AudioResampler crash on empty buffer input#8364
struktured wants to merge 1 commit into
LMMS:masterfrom
struktured-labs:fix-audioresampler-empty-span

Conversation

@struktured
Copy link
Copy Markdown

Summary

AudioResampler::process() aborts the application when handed an empty buffer view. libsamplerate's src_process() throws when SRC_DATA->data_in or data_out is null, and an empty std::span yields data() == nullptr.

Crash report

Reproduced during long playback with an SF2 instrument track on LMMS 1.3.0-alpha (commit ab0ed11):

terminate called after throwing an instance of 'std::runtime_error'
  what():  SRC_DATA->data_out or SRC_DATA->data_in is NULL.

The resampler's sample-rate conversion path (used when the plugin's internal rate differs from the engine's output rate) can present a zero-frame slice of Sf2Instrument::m_bufferView to process() between refill checks. libsamplerate then aborts.

Root cause

AudioResampler::process() populates SRC_DATA from InterleavedBufferView::data() without checking whether the view has any frames. An empty span has no underlying storage, so data() == nullptr. libsamplerate's documented behavior on null pointers is SRC_ERR_BAD_DATA, which process() rethrows as std::runtime_error.

Fix

Early-return {0, 0} when either buffer has zero frames. The zero/zero pair is already the documented "no progress" signal existing callers handle — e.g. Sf2Instrument::renderFrames breaks the inner loop when both inputFramesUsed and outputFramesGenerated are zero.

Test plan

  • Build clean, no new warnings introduced.
  • Long playback with an SF2 instrument at a non-default internal rate no longer aborts with SRC_DATA NULL.
  • Regression: tracks where the internal rate matches the engine rate go through the early fluid_synth_write_float path and never call AudioResampler::process() — unaffected.

libsamplerate's src_process() throws when SRC_DATA->data_in or data_out
is null. An empty std::span yields data() == nullptr, so any caller
that hands process() a zero-frame view (e.g. a fully-consumed buffer
slice in Sf2Instrument::renderFrames before the refill check fires)
crashes the app with:

    terminate called after throwing 'std::runtime_error'
      what():  SRC_DATA->data_out or SRC_DATA->data_in is NULL.

Early-return {0, 0} when either buffer has zero frames so the resampler
never touches libsamplerate with empty input. Fixes the crash without
requiring every caller to pre-check.
@rubiefawn rubiefawn added the bug label May 2, 2026
@messmerd
Copy link
Copy Markdown
Member

messmerd commented May 2, 2026

@sakertooth might be interested in this

@rubiefawn rubiefawn requested a review from sakertooth May 2, 2026 05:39
}

// libsamplerate throws on empty buffers; bail before touching it.
if (input.frames() == 0 || output.frames() == 0) { return {0, 0}; }
Copy link
Copy Markdown
Contributor

@sakertooth sakertooth May 2, 2026

Choose a reason for hiding this comment

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

I would use the empty member function provided within the buffer views. Using these is more robust than just the frame count check because it checks if the data pointer is nullptr as well as if the channel and frame count are 0.

Suggested change
if (input.frames() == 0 || output.frames() == 0) { return {0, 0}; }
if (input.empty() || output.empty()) { return {0, 0}; }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Also, this check should come before the mismatching channel count one right above it: we dont want to throw an exception when the input channel count is 0 and the output channel count is 2 for example.

@rubiefawn rubiefawn added the needs testing This pull request needs more testing label May 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug needs testing This pull request needs more testing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants