Currently, c2rust translates functions that call alloca to set up and read from a [c2rust_]alloca_allocations: Vec<Vec<u8>> variable:
|
// If `alloca` was used in the function body, include a variable to hold the |
|
// allocations. |
|
if let Some(alloca_allocations_name) = self |
|
.function_context |
|
.borrow_mut() |
|
.alloca_allocations_name |
|
.take() |
|
{ |
|
// let mut c2rust_alloca_allocations: Vec<Vec<u8>> = Vec::new(); |
|
let inner_vec = mk().path_ty(vec![mk().path_segment_with_args( |
|
"Vec", |
|
mk().angle_bracketed_args(vec![mk().ident_ty("u8")]), |
|
)]); |
|
let outer_vec = mk().path_ty(vec![mk().path_segment_with_args( |
|
"Vec", |
|
mk().angle_bracketed_args(vec![inner_vec]), |
|
)]); |
|
let alloca_allocations_stmt = mk().local_stmt(Box::new(mk().local( |
|
mk().mutbl().ident_pat(alloca_allocations_name), |
|
Some(outer_vec), |
|
Some(mk().call_expr(mk().path_expr(vec!["Vec", "new"]), vec![])), |
|
))); |
|
|
|
body_stmts.push(alloca_allocations_stmt); |
|
} |
However, when the Vec<u8> backing buffer of an allocation is used to access types with stricter alignment requirements than u8, such as f32, undefined behavior can occur.
I ran into this while experimenting with transpiling libvorbis to Rust for use by my vorbis_rs library, where Miri correctly reported the following in the place where an alloca buffer was used:
error: Undefined Behavior: accessing memory based on pointer with alignment 1, but alignment 4 is required
--> packages/vorbis_c2rust_sys/src/lib/psy.rs:573:4
|
= note: Undefined Behavior occurred here
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: this is on thread `issue_17`
= note: stack backtrace:
0: vorbis_c2rust_sys::lib::psy::setup_tone_curves
at packages/vorbis_c2rust_sys/src/lib/psy.rs:573:5: 573:48
1: vorbis_c2rust_sys::lib::psy::_vp_psy_init
at packages/vorbis_c2rust_sys/src/lib/psy.rs:902:20: 909:3
2: vorbis_c2rust_sys::lib::block::_vds_shared_init
at packages/vorbis_c2rust_sys/src/lib/block.rs:728:4: 735:5
3: vorbis_c2rust_sys::lib::block::vorbis_analysis_init
at packages/vorbis_c2rust_sys/src/lib/block.rs:836:5: 836:53
4: vorbis_rs::encoder::encoder_util::VorbisEncodingState::new
at packages/vorbis_rs/src/common/error.rs:258:22: 258:38
5: vorbis_rs::VorbisEncoderBuilder::<&mut std::vec::Vec<u8>>::build
at packages/vorbis_rs/src/encoder/encoder_impl.rs:241:35: 241:72
6: issue_17
at packages/vorbis_rs/tests/regression_tests.rs:11:20: 17:10
7: issue_17::{closure#0}
at packages/vorbis_rs/tests/regression_tests.rs:9:14: 9:14
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
I have a hunch that the most appropriate fix would be to use unaligned read methods when reading from an alloca buffer.
Currently, c2rust translates functions that call
allocato set up and read from a[c2rust_]alloca_allocations: Vec<Vec<u8>>variable:c2rust/c2rust-transpile/src/translator/functions.rs
Lines 217 to 241 in 90b216e
However, when the
Vec<u8>backing buffer of an allocation is used to access types with stricter alignment requirements thanu8, such asf32, undefined behavior can occur.I ran into this while experimenting with transpiling
libvorbisto Rust for use by myvorbis_rslibrary, where Miri correctly reported the following in the place where anallocabuffer was used:I have a hunch that the most appropriate fix would be to use unaligned read methods when reading from an
allocabuffer.