Skip to content

Commit f644cab

Browse files
committed
Bounce through SDL2 heap in AudioCVT::convert
This commit rewrites AudioCVT::convert to bounce the audio buffer into a an SDL2 heap allocation, rather than trying to reuse the rust heap buffer. This is critical, as the underlying library warns internally that the buffer may be reallocated, breaking configurations where the library is not using the same heap as rust. The underlying implementation also notes that the underlying buffer may be transparently resized to larger than the output as part of the transformations, so relying on the buffer being capacity() bytes long to ensure the buffer is not re-allocated is a broken assumption. Closes Rust-SDL2#1096
1 parent 8bae639 commit f644cab

File tree

1 file changed

+17
-9
lines changed

1 file changed

+17
-9
lines changed

src/sdl2/audio.rs

+17-9
Original file line numberDiff line numberDiff line change
@@ -1012,27 +1012,35 @@ impl AudioCVT {
10121012
if self.raw.needed != 0 {
10131013
let mut raw = self.raw;
10141014

1015-
// calculate the size of the dst buffer
1015+
// calculate the size of the dst buffer.
10161016
use std::convert::TryInto;
10171017
raw.len = src.len().try_into().expect("Buffer length overflow");
1018+
1019+
// This is more a suggestion, and not really a guarantee...
10181020
let dst_size = self.capacity(src.len());
1019-
let needed = dst_size - src.len();
1020-
src.reserve_exact(needed);
10211021

1022-
// perform the conversion in place
1023-
raw.buf = src.as_mut_ptr();
1022+
// Bounce into SDL2 heap allocation as SDL_ConvertAudio may rewrite the pointer.
1023+
raw.buf = sys::SDL_malloc(dst_size as u32) as *mut _;
1024+
if raw.buf.is_null() {
1025+
panic!("Failed SDL_malloc needed for SDL_ConvertAudio");
1026+
}
1027+
// raw.buf is dst_size long, but we want to copy into only the first src.len bytes.
1028+
std::slice::from_raw_parts_mut(raw.buf, src.len()).copy_from_slice(src.as_ref());
1029+
10241030
let ret = sys::SDL_ConvertAudio(&mut raw);
10251031
// There's no reason for SDL_ConvertAudio to fail.
10261032
// The only time it can fail is if buf is NULL, which it never is.
10271033
if ret != 0 {
10281034
panic!("{}", get_error())
10291035
}
10301036

1031-
// return original buffer back to caller
1032-
debug_assert!(raw.len_cvt > 0);
1033-
debug_assert!(raw.len_cvt as usize <= src.capacity());
1037+
// Bounce back into src, trying to re-use the same buffer.
1038+
let outlen: usize = raw.len_cvt.try_into().expect("Buffer size rollover");
1039+
debug_assert!(outlen <= dst_size);
1040+
src.resize(outlen, 0);
1041+
src.copy_from_slice(std::slice::from_raw_parts_mut(raw.buf, outlen));
1042+
sys::SDL_free(raw.buf as *mut _);
10341043

1035-
src.set_len(raw.len_cvt as usize);
10361044
src
10371045
} else {
10381046
// The buffer remains unmodified

0 commit comments

Comments
 (0)