@@ -1010,29 +1010,39 @@ impl AudioCVT {
10101010 //! Certain conversions may cause buffer overflows. See AngryLawyer/rust-sdl2 issue #270.
10111011 unsafe {
10121012 if self . raw . needed != 0 {
1013+ use std:: convert:: TryInto ;
1014+ use std:: slice:: from_raw_parts_mut;
1015+
10131016 let mut raw = self . raw ;
10141017
1015- // calculate the size of the dst buffer
1016- use std:: convert:: TryInto ;
1017- raw. len = src. len ( ) . try_into ( ) . expect ( "Buffer length overflow" ) ;
1018+ // Calculate the size of the buffer we're handing to SDL.
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. len = src. len ( ) . try_into ( ) . expect ( "Buffer length overflow" ) ;
1024+ raw. buf = sys:: SDL_malloc ( dst_size as _ ) as * mut _ ;
1025+ if raw. buf . is_null ( ) {
1026+ panic ! ( "Failed SDL_malloc needed for SDL_ConvertAudio" ) ;
1027+ }
1028+ // raw.buf is dst_size long, but we want to copy into only the first src.len bytes.
1029+ assert ! ( src. len( ) <= dst_size) ;
1030+ from_raw_parts_mut ( raw. buf , src. len ( ) ) . copy_from_slice ( src. as_ref ( ) ) ;
1031+
10241032 let ret = sys:: SDL_ConvertAudio ( & mut raw) ;
10251033 // There's no reason for SDL_ConvertAudio to fail.
10261034 // The only time it can fail is if buf is NULL, which it never is.
10271035 if ret != 0 {
10281036 panic ! ( "{}" , get_error( ) )
10291037 }
10301038
1031- // return original buffer back to caller
1032- debug_assert ! ( raw. len_cvt > 0 ) ;
1033- debug_assert ! ( raw. len_cvt as usize <= src. capacity( ) ) ;
1039+ // Bounce back into src, trying to re-use the same buffer.
1040+ let outlen: usize = raw. len_cvt . try_into ( ) . expect ( "Buffer size rollover" ) ;
1041+ debug_assert ! ( outlen <= dst_size) ;
1042+ src. resize ( outlen, 0 ) ;
1043+ src. copy_from_slice ( from_raw_parts_mut ( raw. buf , outlen) ) ;
1044+ sys:: SDL_free ( raw. buf as * mut _ ) ;
10341045
1035- src. set_len ( raw. len_cvt as usize ) ;
10361046 src
10371047 } else {
10381048 // The buffer remains unmodified
0 commit comments