Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bounce through SDL2 heap in AudioCVT::convert #1098

Merged
merged 5 commits into from
Apr 22, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 21 additions & 11 deletions src/sdl2/audio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1010,29 +1010,39 @@ impl AudioCVT {
//! Certain conversions may cause buffer overflows. See AngryLawyer/rust-sdl2 issue #270.
unsafe {
if self.raw.needed != 0 {
use std::convert::TryInto;
use std::slice::from_raw_parts_mut;

let mut raw = self.raw;

// calculate the size of the dst buffer
use std::convert::TryInto;
raw.len = src.len().try_into().expect("Buffer length overflow");
// Calculate the size of the buffer we're handing to SDL.
// This is more a suggestion, and not really a guarantee...
let dst_size = self.capacity(src.len());
let needed = dst_size - src.len();
src.reserve_exact(needed);

// perform the conversion in place
raw.buf = src.as_mut_ptr();
// Bounce into SDL2 heap allocation as SDL_ConvertAudio may rewrite the pointer.
raw.len = src.len().try_into().expect("Buffer length overflow");
raw.buf = sys::SDL_malloc(dst_size as _) as *mut _;
if raw.buf.is_null() {
panic!("Failed SDL_malloc needed for SDL_ConvertAudio");
}
// raw.buf is dst_size long, but we want to copy into only the first src.len bytes.
assert!(src.len() <= dst_size);
from_raw_parts_mut(raw.buf, src.len()).copy_from_slice(src.as_ref());

let ret = sys::SDL_ConvertAudio(&mut raw);
// There's no reason for SDL_ConvertAudio to fail.
// The only time it can fail is if buf is NULL, which it never is.
if ret != 0 {
panic!("{}", get_error())
}

// return original buffer back to caller
debug_assert!(raw.len_cvt > 0);
debug_assert!(raw.len_cvt as usize <= src.capacity());
// Bounce back into src, trying to re-use the same buffer.
let outlen: usize = raw.len_cvt.try_into().expect("Buffer size rollover");
debug_assert!(outlen <= dst_size);
src.resize(outlen, 0);
src.copy_from_slice(from_raw_parts_mut(raw.buf, outlen));
sys::SDL_free(raw.buf as *mut _);

src.set_len(raw.len_cvt as usize);
src
} else {
// The buffer remains unmodified
Expand Down