diff --git a/crates/ironrdp-rdpsnd-native/src/cpal.rs b/crates/ironrdp-rdpsnd-native/src/cpal.rs index ef338105d..e47157a20 100644 --- a/crates/ironrdp-rdpsnd-native/src/cpal.rs +++ b/crates/ironrdp-rdpsnd-native/src/cpal.rs @@ -164,11 +164,19 @@ impl DecodeStream { clippy::as_conversions, reason = "opus::Channels has no conversions to usize implemented" )] - let mut pcm = vec![0u8; nb_samples * chan as usize * size_of::()]; - if let Err(error) = dec.decode(&pkt, bytemuck::cast_slice_mut(pcm.as_mut_slice()), false) { + let mut pcm_i16 = vec![0i16; nb_samples * chan as usize]; + if let Err(error) = dec.decode(&pkt, &mut pcm_i16, false) { error!(?error, "Failed to decode an Opus packet"); continue; } + // Vec is what the channel carries downstream. Reinterpreting + // Vec -> Vec via cast_slice is safe (smaller alignment). + // Allocating as Vec in the first place avoids the alignment + // hazard of `bytemuck::cast_slice_mut::` panicking when + // the allocator hands back a u8 buffer that is not 2-byte aligned + // (which manifested as a hard crash in #1202 under the burst of + // malformed Opus packets generated by a server reboot). + let pcm = bytemuck::cast_slice(&pcm_i16).to_vec(); if dec_tx.send(pcm).is_err() { error!("Failed to send the decoded Opus packet over the channel");