mirror of
https://github.com/denoland/rusty_v8.git
synced 2024-12-25 16:49:29 -05:00
Explicit panic instead of silent memory corruption (#1377)
Due to the automatic entry and exit behavior of Isolate upon creation and drop, it is crucial to ensure that v8::OwnedIsolate instances are dropped in the reverse order of their creation. Dropping them in the incorrect order can result in the corruption of the thread-local stack managed by v8, leading to memory corruption and potential segfaults. This introduces a check to verify the `this == Isolate::GetCurrent()` requirement before invoking the exit function. If the requirement is not met, a clean panic is triggered to provide explicit error handling instead of allowing silent memory corruption.
This commit is contained in:
parent
811cce27c0
commit
60e0859514
3 changed files with 21 additions and 1 deletions
|
@ -161,6 +161,8 @@ void v8__Isolate__Enter(v8::Isolate* isolate) { isolate->Enter(); }
|
||||||
|
|
||||||
void v8__Isolate__Exit(v8::Isolate* isolate) { isolate->Exit(); }
|
void v8__Isolate__Exit(v8::Isolate* isolate) { isolate->Exit(); }
|
||||||
|
|
||||||
|
v8::Isolate* v8__Isolate__GetCurrent() { return v8::Isolate::GetCurrent(); }
|
||||||
|
|
||||||
void v8__Isolate__MemoryPressureNotification(v8::Isolate* isolate,
|
void v8__Isolate__MemoryPressureNotification(v8::Isolate* isolate,
|
||||||
v8::MemoryPressureLevel level) {
|
v8::MemoryPressureLevel level) {
|
||||||
isolate->MemoryPressureNotification(level);
|
isolate->MemoryPressureNotification(level);
|
||||||
|
|
|
@ -379,6 +379,7 @@ extern "C" {
|
||||||
fn v8__Isolate__GetNumberOfDataSlots(this: *const Isolate) -> u32;
|
fn v8__Isolate__GetNumberOfDataSlots(this: *const Isolate) -> u32;
|
||||||
fn v8__Isolate__Enter(this: *mut Isolate);
|
fn v8__Isolate__Enter(this: *mut Isolate);
|
||||||
fn v8__Isolate__Exit(this: *mut Isolate);
|
fn v8__Isolate__Exit(this: *mut Isolate);
|
||||||
|
fn v8__Isolate__GetCurrent() -> *mut Isolate;
|
||||||
fn v8__Isolate__MemoryPressureNotification(this: *mut Isolate, level: u8);
|
fn v8__Isolate__MemoryPressureNotification(this: *mut Isolate, level: u8);
|
||||||
fn v8__Isolate__ClearKeptObjects(isolate: *mut Isolate);
|
fn v8__Isolate__ClearKeptObjects(isolate: *mut Isolate);
|
||||||
fn v8__Isolate__LowMemoryNotification(isolate: *mut Isolate);
|
fn v8__Isolate__LowMemoryNotification(isolate: *mut Isolate);
|
||||||
|
@ -534,7 +535,8 @@ extern "C" {
|
||||||
/// synchronize.
|
/// synchronize.
|
||||||
///
|
///
|
||||||
/// rusty_v8 note: Unlike in the C++ API, the Isolate is entered when it is
|
/// rusty_v8 note: Unlike in the C++ API, the Isolate is entered when it is
|
||||||
/// constructed and exited when dropped.
|
/// constructed and exited when dropped. Because of that v8::OwnedIsolate
|
||||||
|
/// instances must be dropped in the reverse order of creation
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Isolate(Opaque);
|
pub struct Isolate(Opaque);
|
||||||
|
@ -1518,6 +1520,11 @@ impl Drop for OwnedIsolate {
|
||||||
snapshot_creator.is_none(),
|
snapshot_creator.is_none(),
|
||||||
"If isolate was created using v8::Isolate::snapshot_creator, you should use v8::OwnedIsolate::create_blob before dropping an isolate."
|
"If isolate was created using v8::Isolate::snapshot_creator, you should use v8::OwnedIsolate::create_blob before dropping an isolate."
|
||||||
);
|
);
|
||||||
|
// Safety: We need to check `this == Isolate::GetCurrent()` before calling exit()
|
||||||
|
assert!(
|
||||||
|
self.cxx_isolate.as_mut() as *mut Isolate == v8__Isolate__GetCurrent(),
|
||||||
|
"v8::OwnedIsolate instances must be dropped in the reverse order of creation. They are entered upon creation and exited upon being dropped."
|
||||||
|
);
|
||||||
self.exit();
|
self.exit();
|
||||||
self.cxx_isolate.as_mut().clear_scope_and_annex();
|
self.cxx_isolate.as_mut().clear_scope_and_annex();
|
||||||
self.cxx_isolate.as_mut().dispose();
|
self.cxx_isolate.as_mut().dispose();
|
||||||
|
|
|
@ -636,6 +636,17 @@ fn microtasks() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic(
|
||||||
|
expected = "v8::OwnedIsolate instances must be dropped in the reverse order of creation. They are entered upon creation and exited upon being dropped."
|
||||||
|
)]
|
||||||
|
fn isolate_drop_order() {
|
||||||
|
let isolate1 = v8::Isolate::new(Default::default());
|
||||||
|
let isolate2 = v8::Isolate::new(Default::default());
|
||||||
|
drop(isolate1);
|
||||||
|
drop(isolate2);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn get_isolate_from_handle() {
|
fn get_isolate_from_handle() {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
Loading…
Reference in a new issue