Skip to content

WaveFormat::parse reads a WAVEFORMATEXTENSIBLE through a &WAVEFORMATEX (safe fn, out-of-bounds read) #65

Description

@115dkk

WaveFormat::parse is a safe function that takes &WAVEFORMATEX (18 bytes), but when wFormatTag == WAVE_FORMAT_EXTENSIBLE and cbSize >= 22 it does

let waveformatextensible: WAVEFORMATEXTENSIBLE = unsafe {
    std::ptr::read(std::ptr::from_ref(waveformatex).cast::<WAVEFORMATEXTENSIBLE>())
};

i.e. it reads 40 bytes through a reference that only guarantees 18. The SAFETY comment holds for a header that really sits in front of a WAVEFORMATEXTENSIBLE buffer, but the function signature cannot express that, so safe code can trigger an out-of-bounds read:

use wasapi::WaveFormat;
use windows::Win32::Media::Audio::{WAVEFORMATEX, WAVE_FORMAT_EXTENSIBLE};

let header = WAVEFORMATEX {
    wFormatTag: WAVE_FORMAT_EXTENSIBLE as u16,
    nChannels: 2,
    nSamplesPerSec: 48000,
    nAvgBytesPerSec: 384000,
    nBlockAlign: 8,
    wBitsPerSample: 32,
    cbSize: 22,
};
// Reads 22 bytes past the end of `header` (UB in safe code).
let _ = WaveFormat::parse(&header);

(wasapi 0.24.0, src/waveformat.rs, parse.)

Possible fixes, in the order I would prefer them:

  1. Make it pub unsafe fn parse(waveformatex: *const WAVEFORMATEX) with the safety contract spelled out (the pointer must address a buffer of at least sizeof(WAVEFORMATEX) + cbSize bytes), and keep the safe entry points as parse_from_blob_bytes(&[u8]) (already there) plus perhaps From<WAVEFORMATEXTENSIBLE>.
  2. Or keep a safe parse that only reads the WAVEFORMATEX it was given and returns Err(UnsupportedFormat) for the extensible tag, pointing callers at the byte-slice parser.

For what it is worth, Device::from_raw already carries unsafe in 0.24, so this is the one remaining place where a safe signature hides a pointer-width assumption. I am not using parse in my own code (I go through the byte-slice path), so there is no urgency on my side. This report was drafted with AI assistance and checked against the 0.24.0 source by hand.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions