Rustonomicon: Understanding "subtle corner cases where someone reinterprets some array of `< isize::MAX` objects as bytes" causing indices overflow

I'm learning the Rustonomicon and I find this sentence on Implementing Vec -> Allocating confusing: (Note: zero-sized types are ignored below, and I'm not going to deal with them for the time being)

However in order to avoid subtle corner cases where someone reinterprets some array of < isize::MAX objects as bytes, std limits all allocations to isize::MAX bytes.

My understanding is that it says:

  • If a user of a type T<A> (where A has size a > 1) somehow reinterprets the type as T<B> (where B has size 1), then T<B> might think the number of elements it has is a times the number of elements T<A> has.
  • If std didn't limit all allocations to isize::MAX bytes, T<B> might think it has more than isize::MAX elements, which might cause index overflow when using ptr::offset.

Is this correct? Can someone show me an example?

Some of this may have been written before the isize::MAX bytes restriction was as clear.

See PRs like Enforce that layout size fits in isize in Layout by CAD97 · Pull Request #95295 · rust-lang/rust · GitHub and interpret: make isize::MAX the limit for dynamic value sizes by RalfJung · Pull Request #95388 · rust-lang/rust · GitHub that have solidified the "no, no matter what you can't have single values bigger than isize::MAX bytes".

So you mean my understanding is right?

By the current Rust rules, the first problem cannot happen in user code. Rust will not allow you to allocate more than isize::MAX bytes anywhere, so whatever you cast will already be small enough.

If you're implementing an allocator or a Vec-like data structure, then it's your responsibility to refuse creating objects with more than isize::MAX consecutive bytes.

1 Like