-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
if huge requested align, alloc_system heap::allocate on OS X returns unaligned values #30170
Comments
Another possible course of action could be just saying that alignment over some reasonably high value is not guaranteed to be respected and part of the |
@alexcrichton I would place that into the "Requirements should be checkable" bucket. I don't mind it personally, as long as someone would specify the "reasonably high value" in question. |
The Windows system allocator has no way to specify alignment so the Rust code that invokes it is responsible for over-allocating and aligning. Therefore any concerns about whether it handles silly huge alignments can easily be resolved by just fixing the Rust code if any problems turn up. |
This precondition takes the form of a behavorial change in `Layout::from_size_align` (so it returns `None` if the `align` is too large) and a new requirement for safe usage of `Layout::from_size_align_unchecked`. Fix rust-lang#30170.
…xcrichton Add precondition to `Layout` that the `align` fit in a u32. Add precondition to `Layout` that the `align` not exceed 2^31. This precondition takes the form of a behavorial change in `Layout::from_size_align` (so it returns `None` if the input `align` is too large) and a new requirement for safe usage of `Layout::from_size_align_unchecked`. Fix #30170.
ef8804b addressed rust-lang#30170 by rejecting huge alignments at the allocator API level, transforming a specific platform bug/limitation into an enforced API limitation on all platforms. This change essentially reverts that commit, and instead makes alloc() itself return AllocErr::Unsupported when receiving huge alignments. This was discussed in rust-lang#32838 (comment) and following.
Reject huge alignments on macos with system allocator only ef8804b addressed #30170 by rejecting huge alignments at the allocator API level, transforming a specific platform bug/limitation into an enforced API limitation on all platforms. This change essentially reverts that commit, and instead makes alloc() itself return AllocErr::Unsupported when receiving huge alignments. This was discussed in #32838 (comment) and following.
ef8804b addressed rust-lang#30170 by rejecting huge alignments at the allocator API level, transforming a specific platform bug/limitation into an enforced API limitation on all platforms. This change essentially reverts that commit, and instead makes alloc() itself return AllocErr::Unsupported when receiving huge alignments. This was discussed in rust-lang#32838 (comment) and following.
ef8804b addressed rust-lang#30170 by rejecting huge alignments at the allocator API level, transforming a specific platform bug/limitation into an enforced API limitation on all platforms. This change essentially reverts that commit, and instead makes alloc() itself return AllocErr::Unsupported when receiving huge alignments.
While trying to isolate what kinds of preconditions the
Allocator
trait is going to require and post-conditions it ensures, I made a test program to explore what happens with our current pair of low-level allocators.As far as I can tell so far, jemalloc always ensures that it never gives back an unaligned address.
but on OS X, the system allocator (linked via
extern crate alloc_system;
) can produce addresses that do not meet the alignment request, namely if you ask for values with starting addresses of alignment greater than or equal to1 << 32
. (Like i said, we're talking about huge alignments here.)(on Linux, for both jemalloc and the system allocator, I never observed either returning non-null addresses that did not meet the alignment request. In other words, they handled absurdly large alignments "properly")
What to do about this?
I talk a little about this further in my Digression section below, but in summary, I think we should do something about this.
It seems like an easy short term solution is this: We should be able to pre-determine which allocator + platform combinations fall victim to this problem, and for those cases, make the
allocate
(andreallocate
, etc) methods validate their results. If validation fails, then we can just free the original address and return null.%
(aka divide) and branch doesn't seem like much in the context of an allocation, but still...)Anyway, if you're interested in alternative ideas, see the Digression/Discussion section below
Digression and/or Discussion
When Rust originally merged the jemalloc support PR, it stated the following requirement on the
allocate
method:... so arguably there has always been a precondition to not feed in ridiculously large values for alignment.
However, even if that is the case, here are some things to consider
Requirements should be checkable
if we want to continue to impose this precondition, then we must provide the programmer with a way to query what the value of "the largest supported page size on the platform" actually is.
(I didn't see a way to do this via a couple of greps of the code base, but it doesn't help that I don't understand what is actually meant by the above phrase.)
::std::sys::os::page_size
; so I don't think that would be a way to query the actual value, though certainly it would provide a bound that a programmer can use in the meantime...)Post-validation is not absurd
Given that at least some alloc-crate + target combinations are not imposing the above requirement (in the sense that they return null when the given alignment is unsatisfiable), it seems somewhat reasonable to me to add the post-allocation check that I described above, as long as we do it in a conditionalized manner.
align <= 0x1000
, working under the assumptions that all allocators will behave properly with such an input.Also, the man page for
posix_memalign
on my version of OS X says nothing about an upper bound on the value foralignment
. This to me indicates that this is a bug in OS X itself, which we can report and workaround via post-validation in the short term.#[allocator]
crate linking could choose between the two variants depending on which version of OS X is targetted.)The Sample Program
Here is that sample program (you can toggle the different allocates with
--cfg alloc_system
or--cfg alloc_jemalloc
). When you run it, the thing to look for is when there is an output line that hasrem: <value>
on the end, which is only printed for non-zero remainder (when one divides the address by the alignment).(Also, here's a playpen, though I repeat that the problematic behavior does not exhibit itself on versions of Linux that I have tried.) ((Updated to fit new global allocator API))
Output on Mac OS X showing the erroneous value(s)
See following gist: https://gist.github.com/pnkfelix/535e8d4e810025331c77
The text was updated successfully, but these errors were encountered: