Skip to content

Validate sample with audiosample_check() in all audio play paths - #11138

Merged
tannewt merged 1 commit into
adafruit:mainfrom
dhalbert:audiosample-check-all-play-paths
Jul 24, 2026
Merged

tannewt merged 1 commit into
adafruit:mainfrom
dhalbert:audiosample-check-all-play-paths

Conversation

@dhalbert

@dhalbert dhalbert commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator

Add missing calls to audiosample_check() in places that needed to validate the incoming object was an audiosample.

I found the original bug in the RP2040 I2SOut play logic (#11067), and then asked Claude to see if there were other missing arg validations for audiosample-protocol objects. It found a bunch.

Rest is written by Claude and slightly edited.

Most play() entry points passed the user-supplied object straight to the non-validating audiosample getters (audiosample_get_sample_rate(), audiosample_get_bits_per_sample(), audiosample_get_channel_count(), audiosample_get_buffer_structure()), which cast the object to audiosample_base_t * without checking it implements the audiosample protocol. Passing a non-sample object dereferenced arbitrary memory instead of raising an error.

Paths fixed:

  • espressif & mimxrt10xx port_i2s_play() (mimxrt covers both I2SOut and PWMAudioOut)
  • atmel-samd AudioOut & I2SOut
  • nordic I2SOut & PWMAudioOut
  • raspberrypi I2SOut, PWMAudioOut, mcp4822
  • stm PWMAudioOut
  • zephyr-cp I2SOut
  • espressif AudioOut (was safe only by call ordering; made explicit for consistency)

Already-correct paths (unchanged): stm AudioOut, all shared-module effects and audiomixer.Mixer/MixerVoice (via audiosample_must_match()), and audiospeed/audiofilewriter/usb_audio (explicit checks). play() was the only entry point with the missing check.

The various play() entry points passed the user-supplied object straight
to the non-validating audiosample getters (audiosample_get_sample_rate(),
audiosample_get_bits_per_sample(), etc.), which cast the object without
checking it implements the audiosample protocol. Passing a non-sample
object dereferenced arbitrary memory instead of raising.

Add audiosample_check() as the first statement in each affected common-hal
play path so a bad object raises cleanly, matching the existing RP2040
audiobusio.I2SOut fix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@dhalbert
dhalbert requested a review from tannewt July 23, 2026 23:59

@tannewt tannewt 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.

Great! Thank you!

@tannewt
tannewt merged commit 5dc657c into adafruit:main Jul 24, 2026
573 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.

Safe mode crash when None passed to I2SOut .play()

2 participants