-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Potential RefCell unsafety due to mem::forget #25841
Comments
Good catch! (I wonder if this applies to cc https://internals.rust-lang.org/t/rc-is-unsafe-mostly-on-32-bit-targets-due-to-overflow/2120 |
This case seems relatively easy to fix, since there are no threading complications -- saturating add (and checking for max before decrementing) is certainly one option. |
AFAICT you don't need to check on decrement, assuming you don't allow for compressed storage. After all, you can't run 2^32-1 destructors without 2^32-1 objects, which is infeasible. |
On unix, it's not a direct problem with the underlying API:
However, it is a problem with how we use it at the moment: #[inline]
pub unsafe fn read(&self) {
let r = ffi::pthread_rwlock_rdlock(self.inner.get());
debug_assert_eq!(r, 0);
} In particular, creating too many readers will only be detected and "handled" (panic) in debug builds. (cc @alexcrichton) I can't find any info about this for the windows APIs.
|
const WRITING: BorrowFlag = !0; Doesn't this means that if you ever get to the stage where you will overflow, you'll just trigger an "already mutably borrowed" error, no matter how you try to borrow? I modified the example (because I'm on 64 bit) and ran it (it was optimised out and it ran instantly, whoop): use std::cell::RefCell;
fn main() {
let overflower = RefCell::new(());
loop {
std::mem::forget(overflower.borrow());
}
} Output:
I guess that the error message is technically wrong but I think it's safe at least? |
@whataloadofwhat I can agree with that. Alternatively you can hit a |
On 32-bit upon reaching exactly 0x10000000 readers, attempts to lock it using the try version will return a failure, while the non-try version will simply deadlock. |
@Stebalien noted the possibility of a wider-than-address-space collection on the internals discussion about overflows in |
Was this fixed by #33960? |
Indeed fixed! |
I don't have a 32-bit computer to test on, but I suspect that this will overflow
RefCell
's counter on 32 bit builds:This can allow shared mutable pointers. I imagine similar problems hold for
Rc
and co. and I imagine the problem also happens on 64 bit builds if you have it running for a few hundred years.This is what made me think of the problem:
But this isn't true if memory can be reclaimed without the destructors running (I think).
To fix it you just need to use saturating addition since only leaks can allow this to happen, and once you've leaked in this way you can't ever hope to run all the destructors anyway. (Actually, this isn't strictly true if you allow for compressed storage.)
The text was updated successfully, but these errors were encountered: