Add regression test for CString::clone_into unwind safety#158807
Add regression test for CString::clone_into unwind safety#158807Vastargazing wants to merge 1 commit into
Conversation
CString::clone_into reuses the target's allocation by moving the buffer into a Vec and growing it. If that growth's allocation fails and the alloc error hook unwinds, the target has to be left as a valid CString, but nothing covered that path. Add a test in library/alloctests that fails the reallocation under a panicking alloc error hook and checks the target stays valid. The failing allocator is only honored under Miri - a global allocator in a library test doesn't intercept libstd's allocation in a normal build - so the unwind assertion is gated on cfg!(miri); the test still runs and passes as a regular test.
|
|
|
LGTM, thanks :) @bors r+ rollup |
…-alloc-error, r=RalfJung Add regression test for CString::clone_into unwind safety Regression test for the panic-safety fix in rust-lang#155707 rust-lang#70201 gave `<CStr as ToOwned>::clone_into` a path that moved the target `CString`'s buffer out (leaving it empty) before growing a `Vec`; if that growth's allocation failed and unwound, the target was left without its nul terminator, which is UB. rust-lang#155707 fixed this but didn't add a test. The failing allocator here is only honored under Miri - in a normal build a `#[global_allocator]` in a library test doesn't intercept the reallocation inside `CString::clone_into` (it lives in libstd, linked `-C prefer-dynamic`). So the test passes as a regular test and does the real check under Miri, with the unwind assertion gated on `cfg!(miri)`; it runs under Miri in CI via the library-tests-under-Miri job. This started as rust-lang/miri#5157, but per @RalfJung a std regression test belongs with the standard library. r? @RalfJung
…-alloc-error, r=RalfJung Add regression test for CString::clone_into unwind safety Regression test for the panic-safety fix in rust-lang#155707 rust-lang#70201 gave `<CStr as ToOwned>::clone_into` a path that moved the target `CString`'s buffer out (leaving it empty) before growing a `Vec`; if that growth's allocation failed and unwound, the target was left without its nul terminator, which is UB. rust-lang#155707 fixed this but didn't add a test. The failing allocator here is only honored under Miri - in a normal build a `#[global_allocator]` in a library test doesn't intercept the reallocation inside `CString::clone_into` (it lives in libstd, linked `-C prefer-dynamic`). So the test passes as a regular test and does the real check under Miri, with the unwind assertion gated on `cfg!(miri)`; it runs under Miri in CI via the library-tests-under-Miri job. This started as rust-lang/miri#5157, but per @RalfJung a std regression test belongs with the standard library. r? @RalfJung
Rollup of 20 pull requests Successful merges: - #158377 (add `-Zforce-intrinsic-fallback` flag) - #158642 (Clarify some interning details) - #158743 (Look for cdb location in the registry first) - #158775 (bootstrap: only encode RUSTFLAGS when a flag contains a space) - #158782 (Add and use cfg(target_has_threads) to enforce no_thread impl usage) - #158785 (hook intrinsic-test into aarch64-gnu) - #157734 (Stabilize `local_key_cell_update`) - #158183 (std: allocate less memory in `current_exe` for OpenBSD) - #158671 (Move tests batch 17) - #158730 (Update `FIXME(static_mut_refs)` comments) - #158752 (Reorganize `tests/ui/issues` [18/N]) - #158755 (Use `ThinVec` more in the AST) - #158757 (Fix incorrect tracking issue for `read_le`/`read_be`) - #158765 (Fix ICE on non-ident path in `doc(auto_cfg values)`) - #158771 (library: expand HashSet::extract_if coverage) - #158772 (rustc-dev-guide subtree update) - #158776 (fix: emit diagnostic for AVR target without target-cpu) - #158786 (Add regression test for builtin attr macro values) - #158807 (Add regression test for CString::clone_into unwind safety) - #158825 (Fix typo)
|
Look like you've got some UB in the test. |
|
This pull request was unapproved. |
|
Thanks. The UB is in libtest's own teardown, not the test body: with a #[global_allocator] installed, libtest frees its internal allocations (the mpmc results channel) through it, and on Windows System::dealloc reads the allocation header just before the pointer, which trips Stacked Borrows since the freed Box's provenance doesn't cover the header. It fires even with 0 tests run - it's inherent to wrapping System in a global allocator under Miri on Windows, independent of the test itself. Two ways to resolve it, whichever you'd prefer:
Happy to do either - which do you prefer? |
Regression test for the panic-safety fix in #155707
#70201 gave
<CStr as ToOwned>::clone_intoa path that moved the targetCString's buffer out (leaving it empty) before growing aVec; if that growth's allocation failed and unwound, the target was left without its nul terminator, which is UB. #155707 fixed this but didn't add a test.The failing allocator here is only honored under Miri - in a normal build a
#[global_allocator]in a library test doesn't intercept the reallocation insideCString::clone_into(it lives in libstd, linked-C prefer-dynamic). So the test passes as a regular test and does the real check under Miri, with the unwind assertion gated oncfg!(miri); it runs under Miri in CI via the library-tests-under-Miri job.This started as rust-lang/miri#5157, but per @RalfJung a std regression test belongs with the standard library.
r? @RalfJung