rust-lang / rust-lang/rust

`Box` and `Vec` don't properly document their behavior with zero-sized allocations for custom allocators

Open
#162,799 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

A-allocators A-docs needs-triage requires-nightly T-libs
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

Location (URL)

For each of these, also see the NonNull variant.

Summary

Box, Vec, and VecDeque all have special handling for zero-sized allocations, in that they do not go through the allocator. While this is fine to ignore for Global, as that allocator always returns NonNull::dangling for zero-sized allocations, this does not generalize to arbitrary allocators, as they may actually allocate (potentially overprovisioning), even for size = 0.

This poses a documentation problem for Box::from_raw_in and Vec::from_raw_parts_in, because they state that the memory will be freed on drop. However, this is incorrect if:

  • For Box<T, A>, the size of the value, as reported by size_of_val_raw, is 0 (note that this applies to ?Sized types too)
  • For Vec<T, A>, the capacity is 0 or T a ZST

Note that this also means their safety requirements are incorrect (overly strict), as they require passing a pointer to a memory block allocated with alloc. However, this incorrect and even inappropriate: as explained above, the memory will be leaked in certain cases.

Box::into_raw_with_allocator correctly links to the memory layout section, which describes the edge case (although for some reason it only talks about Global; needs rewrite too). However, I think this is not worded strongly enough. This is evidenced by me accidentally introducing an unsound deallocate call in Box::map in https://github.com/rust-lang/rust/pull/161617, which went undetected initially, and was fixed in https://github.com/rust-lang/rust/pull/162285.

Note that Vec::into_raw_parts_with_allocator is unaffected, as it states the only legal way to get rid of the memory is using from_raw_parts_in.

cc #156882
@rustbot label A-allocators requires-nightly

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the linked documentation for Box::from_raw_in, Vec::from_raw_parts_in, Box::into_raw_with_allocator, and their NonNull variants, then read the linked memory-layout section. Check how the text describes zero-sized values, zero capacity, ZSTs, and custom allocators. Done means the affected APIs and memory-layout documentation accurately describe allocation and deallocation behavior and their safety requirements.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
documentation
Issue type
Documentation
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.