Skip to content

math: iir: reject series count that does not divide num_sections - #11318

Merged
kv2019i merged 1 commit into
thesofproject:mainfrom
Shrusti-pk:iir-series-divisor
Oct 22, 2026
Merged

kv2019i merged 1 commit into
thesofproject:mainfrom
Shrusti-pk:iir-series-divisor

Conversation

@Shrusti-pk

Copy link
Copy Markdown
Contributor

iir_delay_size_df1() range-checks num_sections_in_series (added in #10892) but never requires it to divide num_sections:

  • iir_df1() runs ceil(num_sections / nseries) * nseries biquads, so 11 sections with a series count of 10 runs 20 against coefficients and delay lines sized for 11
  • both fields come from the bytes control blob; eq_iir, sound_dose and the tdfb direction emphasis filter all size their state through this validator
  • ASan with iir_df1_generic.c: heap read past the 332 byte blob copy and heap write past the 352 byte two channel delay allocation
  • iir_delay_size_df2t() has the identical check and gets the same fix

The tuning scripts always emit num_sections_in_series == num_sections, so generated blobs still load. sof-testbench4 output for the eqiir16/24/32, gain32 and drc32 benchmark topologies is byte-identical before and after, test-all-defconfigs.sh is green, and the new cmocka case fails without the fix.

@sofci

sofci commented Oct 16, 2026

Copy link
Copy Markdown
Collaborator

Can one of the admins verify this patch?

reply test this please to run this test once

Copilot AI left a comment

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.

🟢 Approval recommended

The checks safely enforce the processing loops’ requirements, and no blocking issues remain.

No open issues 🎉

What changed in this PR

Extends IIR configuration validation to reject series counts that do not divide the section count, preventing out-of-bounds filter processing.

Changes:

  • Adds divisibility checks to both DF1 and DF2T validators.
  • Adds a DF1 regression test covering valid and invalid series counts.
File Description
test/​cmocka/​src/​audio/​eq_iir/​eq_iir_process.c Tests series-count validation.
src/​math/​iir_df2t.c Rejects non-divisible DF2T configurations.
src/​math/​iir_df1.c Rejects non-divisible DF1 configurations.

Review effort: Balanced

@kv2019i kv2019i left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

thanks @Shrusti-pk . @singalsu please check before merge

@lgirdwood lgirdwood left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@singalsu we have a few more %, lets make sure not in hot paths.

int i;

struct CMUnitTest tests[ARRAY_SIZE(parameters)];
struct CMUnitTest tests[ARRAY_SIZE(parameters) + 1];

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks like we need to fix the array loop and not pad the array ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Agreed, padding it was the wrong shape. The parameter loop now fills exactly ARRAY_SIZE(parameters) entries again, and the validator case runs as its own cmocka group via cmocka_unit_test(), with main() adding up the failures from both groups. Checked that the new group still fails against the unpatched iir_delay_size_df1().

iir_delay_size_df1() is the only check an IIR response header gets
before eq_iir, sound_dose and the tdfb direction emphasis filter size
the delay lines (4 * num_sections words per channel) and point
iir->coef at the blob biquads. It accepts any num_sections_in_series
in [1, num_sections].

iir_df1() and its HiFi, ARM and RISC-V variants step the outer loop by
num_sections_in_series until it reaches num_sections, so they run
ceil(num_sections / nseries) * nseries biquads. When the series count
does not divide num_sections the filter reads coefficients past the
end of the blob and writes filter state past the delay line.

Both values come from the bytes control blob. With num_sections = 11
and num_sections_in_series = 10, 20 biquads run: ASan reports a heap
read past the 332 byte blob copy and a heap write past the 352 byte
two channel delay allocation in iir_df1().

Require num_sections to be a multiple of num_sections_in_series. Do
the same in iir_delay_size_df2t(), which has the identical check. The
tuning scripts always set num_sections_in_series to num_sections, so
generated blobs are not affected. Add a cmocka case for the validator.

Signed-off-by: Shrushti P K <shrusthi@labs.digiscrypt.com>
@Shrusti-pk

Copy link
Copy Markdown
Contributor Author

On the % question, the two added here aren't in a hot path. iir_delay_size_df1() and iir_delay_size_df2t() only run when the filter is configured: from eq_iir_init_coef(), sound_dose_filters_init() and tdfb_direction_init(), i.e. at init or when a new blob is applied. The per-sample iir_df1()/iir_df2t() loops are untouched, so there's no divide on the processing path.

@intel-sofci

intel-sofci commented Oct 22, 2026 •

Copy link
Copy Markdown

PR 11318: test results

Run date: 2026-10-22 11:39 UTC

Tested commit: ac9f06c37d679d0225a7e0c2995dd4d28e5632fa

mtl pass rate lnl pass rate ptl pass rate wcl pass rate nvl pass rate

@kv2019i
kv2019i merged commit 7ea6847 into thesofproject:main Oct 22, 2026
45 of 46 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants