Hello, and thank you for maintaining this crate.
I found a sanitizer/Miri failure reachable through public crate APIs using safe Rust code. I may be missing crate-specific preconditions, but the behavior looks worth checking because safe callers should not be able to trigger undefined behavior.
Summary
- Crate:
ffi-convert
- Version tested:
0.7.0
- API paths with similar failures observed:
CStringArray::c_repr_of
CStringArray::do_drop
CStringArray::drop
Observed diagnostics
MemorySanitizer use of uninitialized value: WARNING: MemorySanitizer: use-of-uninitialized-value
Miri undefined behavior: error: Undefined Behavior: constructing invalid value of type std::boxed::Box<[*mut i8]>: encountered a dangling box (use-after-free)
Reproduction
The snippets below are minimal readable reproducers. Each PoC also includes the source location most relevant to the reported failure.
PoC 1: test_ffi_convert0::generated_test_0
Relevant source location:
src/types.rs:68-77: do_drop reconstructs and frees the boxed raw pointer slice.
src/types.rs:82-84: Drop calls do_drop again if the value is later dropped normally.
Readable equivalent PoC:
use ffi_convert::{CDrop, CReprOf};
#[test]
fn poc() {
let strings = vec![String::from("a")];
let mut c_array = ffi_convert::CStringArray::c_repr_of(strings).unwrap();
c_array.do_drop().unwrap();
// `c_array` is dropped again at the end of the scope.
}
Observed diagnostic:
WARNING: MemorySanitizer: use-of-uninitialized-value
PoC 2: test_ffi_convert0::generated_test_0
Relevant source location:
src/types.rs:68-77: do_drop reconstructs and frees the boxed raw pointer slice.
src/types.rs:82-84: Drop calls do_drop again if the value is later dropped normally.
Readable equivalent PoC:
use ffi_convert::{CDrop, CReprOf};
#[test]
fn poc() {
let strings = vec![String::from("a")];
let mut c_array = ffi_convert::CStringArray::c_repr_of(strings).unwrap();
c_array.do_drop().unwrap();
// `c_array` is dropped again at the end of the scope.
}
Observed diagnostic:
error: Undefined Behavior: constructing invalid value of type std::boxed::Box<[*mut i8]>: encountered a dangling box (use-after-free)
Source review and suggested fix
Brief reasoning:
do_drop frees the owned pointers but leaves the struct fields intact.
- A later
Drop then frees the same allocation again.
Suggested fix:
- Make the drop helper idempotent by nulling the pointer and zeroing the length after freeing, or consume
self for explicit destruction.
Thanks again for taking a look.
Hello, and thank you for maintaining this crate.
I found a sanitizer/Miri failure reachable through public crate APIs using safe Rust code. I may be missing crate-specific preconditions, but the behavior looks worth checking because safe callers should not be able to trigger undefined behavior.
Summary
ffi-convert0.7.0CStringArray::c_repr_ofCStringArray::do_dropCStringArray::dropObserved diagnostics
Reproduction
The snippets below are minimal readable reproducers. Each PoC also includes the source location most relevant to the reported failure.
PoC 1:
test_ffi_convert0::generated_test_0Relevant source location:
src/types.rs:68-77:do_dropreconstructs and frees the boxed raw pointer slice.src/types.rs:82-84:Dropcallsdo_dropagain if the value is later dropped normally.Readable equivalent PoC:
Observed diagnostic:
PoC 2:
test_ffi_convert0::generated_test_0Relevant source location:
src/types.rs:68-77:do_dropreconstructs and frees the boxed raw pointer slice.src/types.rs:82-84:Dropcallsdo_dropagain if the value is later dropped normally.Readable equivalent PoC:
Observed diagnostic:
Source review and suggested fix
Brief reasoning:
do_dropfrees the owned pointers but leaves the struct fields intact.Dropthen frees the same allocation again.Suggested fix:
selffor explicit destruction.Thanks again for taking a look.