-
Notifications
You must be signed in to change notification settings - Fork 13.5k
Report allocation errors as panics, second attempt #112331
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
base: master
Are you sure you want to change the base?
Conversation
r? @jackh726 (rustbot has picked a reviewer for you, use r? to override) |
This comment has been minimized.
This comment has been minimized.
77ba90f
to
d4f1f6a
Compare
☔ The latest upstream changes (presumably #112671) made this pull request unmergeable. Please resolve the merge conflicts. |
Should this be assigned to someone on libs team? I guess it's mostly compiler work? |
Yes, most of the compiler changes are just removing r? libs |
d4f1f6a
to
bacf25d
Compare
@Amanieu could you say if some updates on it planned? Why not merging into master? |
It's waiting on review. |
☔ The latest upstream changes (presumably #113014) made this pull request unmergeable. Please resolve the merge conflicts. |
bacf25d
to
5196f92
Compare
r? libs-api |
☔ The latest upstream changes (presumably #113162) made this pull request unmergeable. Please resolve the merge conflicts. |
#[lang = "eh_personality"] | ||
fn eh_personality() -> ! { | ||
loop {} | ||
} | ||
|
||
#[start] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one is still necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, that was a mistake.
238d017
to
35d75e3
Compare
☔ The latest upstream changes (presumably #113391) made this pull request unmergeable. Please resolve the merge conflicts. |
35d75e3
to
3a6ff98
Compare
3a6ff98
to
8a24112
Compare
☔ The latest upstream changes (presumably #116578) made this pull request unmergeable. Please resolve the merge conflicts. |
The issue at swc-project/swc#8362 and following discussion on Zulip uncovered some subtle concerns around allocation-fail-handlers -- and this here is the first time user-defined code gets run on allocation failure. (Specifically, that user-defined code is the panic hook.) The problem in that issue is that the library assumes there is no reentrancy, but it does cause an allocation, and so if that allocation fails and then the panic handler calls back into the library, we have an unsoundness due to aliasing references (or due to any of the other problems that reentrancy can cause). We have to globally decide that either libraries must generally assume that calling the allocator will run arbitrary safe code (and add safeguards against reentrancy where needed), or the code that runs on allocation failure needs to be "careful" to not touch state that might be invalid since the library governing that state is in the middle of something. |
This has conflicts to be resolved before getting reviewed |
directly call handle_alloc_error Also test more codepaths. There's like 5 different things that can happen on allocation failure! Between `-Zoom`, `#[alloc_error_handler]`, and `set_alloc_error_hook`, we have 3 layers of behavior overrides. It's all a bit messy. rust-lang/rust#112331 seems intended to clean this up, but has not yet reached consensus.
directly call handle_alloc_error Also test more codepaths. There's like 5 different things that can happen on allocation failure! Between `-Zoom`, `#[alloc_error_handler]`, and `set_alloc_error_hook`, we have 3 layers of behavior overrides. It's all a bit messy. rust-lang#112331 seems intended to clean this up, but has not yet reached consensus.
Most of the unstable features are not required for building. For panics, the only remaining detail is having an implementation of the panic handler (`panic_handler`) itself. - `eh_personality`: Not required with `panic=abort` - `_Unwind_Resume`: Symbol not present with `panic=abort` - `alloc_error_handler`: OOM triggers a panic; feature will be removed [1] [1]: rust-lang/rust#112331 Signed-off-by: Tim Crawford <[email protected]>
We already have |
Global allocators are unsafe, so if that code does anything funky, we can blame that code.
swc-project/swc#8362 is an example of that. It seems entirely reasonable to say that the allocator must not call back into an |
Actually, turns out for no_std applications we already invoke the panic handler when rust/library/alloc/src/alloc.rs Lines 438 to 441 in 8f21a5c
For example #![no_std]
#![no_main]
extern crate alloc;
use core::alloc::{GlobalAlloc, Layout};
struct MyAlloc;
unsafe impl GlobalAlloc for MyAlloc {
unsafe fn alloc(&self, _: Layout) -> *mut u8 { core::ptr::null_mut() }
unsafe fn dealloc(&self, _: *mut u8, _: Layout) { todo!() }
}
#[global_allocator]
static ALLOC: MyAlloc = MyAlloc;
#[link(name = "c")]
extern "C" {}
#[panic_handler]
fn panic_handler(_: &core::panic::PanicInfo) -> ! { loop {} }
// This depends on an internal implementation detail, but is only necessary because I'm compiling
// for a target which defaults to panic=unwind.
#[unsafe(no_mangle)]
fn rust_eh_personality() -> ! { panic!() }
#[unsafe(no_mangle)]
fn main() {
alloc::boxed::Box::new(1);
} when compiled with panic=abort works just fine on stable and hangs inside the panic handler with the following backtrace:
In other words this PR doesn't open any soundness holes that don't already exist. |
Yeah, no_std already has a problem. (Also see rust-lang/unsafe-code-guidelines#506.) But no_std binaries are subject to all sorts of subtle issues, so I don't think this is sufficient justification for making this a much bigger soundness problem that applies to all binaries. |
I don't see any reason why we should handle the std and no_std differently here.
Like what? |
You need to set up the entry point, and the unwinding personality, and generally you're (unsafely) interfacing with the OS loader (or whatever else loads your binary).
A soundness bug that affects only a small amount of users is not the same as one that affects a much bigger set of users. no_std binaries are pretty niche. I also just fundamentally, and very strongly, disagree with arguments of the sort "this is already unsound so it doesn't matter if we have more of it". By that standard we can just stop caring about soundness entirely. So, a hard no from my side for exposing these kinds of soundness issues any further until we have made a decision for who's responsibility it is to deal with this reentrancy. |
The personality only applies when the standard library itself is compiled with panic=unwind. For a proper panic=abort target you don't need that, nor when you use
I would argue that it isn't unsound to run user code in the alloc error handler, but rather that it is unsound to depend on the alloc error handler not running user code. Simply because there is no way to fix the no_std case to not run user code in the alloc error handler without either breaking literally every no_std (which would IMO be completely unacceptable) + alloc project in existence or to replace it with an abort without running the panic handler (which is unacceptable for a non-trivial amount of use cases and isn't possible on every architecture anyway) And having us say that no_std is permanently unsound wouldn't be great either. As I see it, the stabilization in #102318 forced our hand in deciding who is responsible for this reentrancy. |
It seems quite bad to say that it is impossible to make crates like https://github.com/swc-project/swc sound -- that'd permanently close the door for useful APIs that we should enable people to use. In particular, having that crate be sound seems a lot more useful than allowing the allocation failure handler to re-enter the crate it was invoked by. One can imagine various transition strategies to achieve that, for instance:
I don't think we have reached the point yet where we should just give up. |
Attempt to re-land #109507 now that #110771 is fixed.
OOM is now reported as a panic but with a custom payload type (
AllocErrorPanicPayload
) which holds the layout that was passed tohandle_alloc_error
.This should be reviewed one commit at a time:
AllocErrorPanicPayload
and changes allocation errors to always be reported as panics.#[alloc_error_handler]
and thealloc_error_hook
API.ACP: rust-lang/libs-team#192
Closes #51540
Closes #51245