@@ -1308,8 +1308,11 @@ impl Device {
13081308
13091309 // SAFETY: AudioUnitRender is called with valid parameters:
13101310 // - raw_audio_unit is valid for the callback duration
1311- // - input_buffer_list is created just above on the stack
1312- // - All other parameters come from Core Audio itself
1311+ // - input_buffer_list is created just above on the stack with a pointer to
1312+ // input_buffer, which is properly aligned (Rust's standard allocators return
1313+ // pointers aligned to at least 8 bytes, exceeding f32/i16 requirements)
1314+ // - input_buffer has been bounds-checked above to ensure sufficient capacity
1315+ // - All other parameters (timestamps, flags, etc.) come from CoreAudio itself
13131316 let status = unsafe {
13141317 AudioUnitRender (
13151318 raw_audio_unit,
@@ -1338,6 +1341,18 @@ impl Device {
13381341 input_buffer[ ..input_bytes] . fill ( 0 ) ;
13391342 }
13401343
1344+ // SAFETY: Creating Data from input_buffer is safe because:
1345+ // - input_buffer is a valid Vec<u8> owned by this closure
1346+ // - input_samples (num_frames * input_channels) was bounds-checked above to ensure
1347+ // input_samples * sample_bytes <= input_buffer.len()
1348+ // - AudioUnitRender just filled the buffer with valid audio data (or we filled
1349+ // it with silence on error)
1350+ // - The Data lifetime is scoped to this callback and doesn't outlive input_buffer
1351+ // - The pointer is suitably aligned: We successfully passed this buffer to
1352+ // AudioUnitRender (line 1314), which requires properly aligned buffers and would
1353+ // have failed if alignment were incorrect. Additionally, in practice, Rust's
1354+ // standard allocators (System, jemalloc, etc.) return pointers aligned to at
1355+ // least 8 bytes, which exceeds the requirements for f32 (4 bytes) and i16 (2 bytes).
13411356 let input_data = unsafe {
13421357 Data :: from_parts (
13431358 input_buffer. as_mut_ptr ( ) as * mut ( ) ,
0 commit comments