1
0
Fork 0

Fix in-place checks in buffer management

The previous implementation didn't work correctly, and would thus result
in soundness issues. Rust 1.78 finally fixes debug assertions in the
standard library so this was caught immediately.
This commit is contained in:
Robbert van der Helm 2024-05-04 20:55:50 +02:00
parent 10aabe3a38
commit d270d1221f
2 changed files with 25 additions and 14 deletions

View file

@ -10,6 +10,13 @@ Since there is no stable release yet, the changes are organized per day in
reverse chronological order. The main purpose of this document in its current reverse chronological order. The main purpose of this document in its current
state is to list breaking changes. state is to list breaking changes.
## [2024-05-04]
### Fixed
- Fixed a soundness issue in the buffer management where in-place input/output
buffers may not have been recognized properly before.
## [2024-03-23] ## [2024-03-23]
### Added ### Added

View file

@ -51,6 +51,7 @@ unsafe impl Sync for BufferManager {}
/// Host data that the plugin's [`Buffer`]s should be created from. Leave these fields as `None` /// Host data that the plugin's [`Buffer`]s should be created from. Leave these fields as `None`
/// values /// values
#[derive(Debug)]
pub struct BufferSource<'a> { pub struct BufferSource<'a> {
pub main_input_channel_pointers: &'a mut Option<ChannelPointers>, pub main_input_channel_pointers: &'a mut Option<ChannelPointers>,
pub main_output_channel_pointers: &'a mut Option<ChannelPointers>, pub main_output_channel_pointers: &'a mut Option<ChannelPointers>,
@ -219,9 +220,6 @@ impl BufferManager {
self.main_input_channel_pointers, self.main_input_channel_pointers,
self.main_output_channel_pointers, self.main_output_channel_pointers,
) { ) {
// If the host processes the main IO out of place then the inputs need to be copied to
// the output buffers. Otherwise the input should already be there.
if input_channel_pointers.ptrs != output_channel_pointers.ptrs {
self.main_buffer.set_slices(num_samples, |output_slices| { self.main_buffer.set_slices(num_samples, |output_slices| {
for (channel_idx, output_slice) in output_slices for (channel_idx, output_slice) in output_slices
.iter_mut() .iter_mut()
@ -229,15 +227,21 @@ impl BufferManager {
.take(input_channel_pointers.num_channels) .take(input_channel_pointers.num_channels)
{ {
let input_channel_pointer = let input_channel_pointer =
input_channel_pointers.ptrs.as_ptr().add(channel_idx); *input_channel_pointers.ptrs.as_ptr().add(channel_idx);
debug_assert!(channel_idx < output_channel_pointers.num_channels);
let output_channel_pointer =
*output_channel_pointers.ptrs.as_ptr().add(channel_idx);
// If the host processes the main IO out of place then the inputs need to be
// copied to the output buffers. Otherwise the input should already be there.
if input_channel_pointer != output_channel_pointer {
output_slice.copy_from_slice(std::slice::from_raw_parts_mut( output_slice.copy_from_slice(std::slice::from_raw_parts_mut(
(*input_channel_pointer).add(sample_offset), input_channel_pointer.add(sample_offset),
num_samples, num_samples,
)) ))
} }
});
} }
});
// Any excess channels will need to be filled with zeroes since they'd otherwise point // Any excess channels will need to be filled with zeroes since they'd otherwise point
// to whatever was left in the buffer // to whatever was left in the buffer