Last active
February 19, 2022 21:43
-
-
Save y21/64d8f2ebb9635b3e4fa95ca0a87bc497 to your computer and use it in GitHub Desktop.
Boa
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::{ | |
alloc::{GlobalAlloc, Layout}, | |
ptr::{self}, | |
}; | |
use boa::JsString; | |
struct BadAllocator<A: GlobalAlloc>(A); | |
// Implementing the GlobalAlloc trait is unsafe by nature because one could "just" return any invalid pointer | |
// and cause memory unsafety that way, but all this is doing is delegate to the underlying allocator | |
// (and returning null for the JsString::new allocation, which is totally valid to do) | |
// This could have been exposed by a crate with a safe interface | |
unsafe impl<A: GlobalAlloc> GlobalAlloc for BadAllocator<A> { | |
unsafe fn alloc(&self, layout: Layout) -> *mut u8 { | |
// I chose a reasonably large size so we can uniquely identify the JsString allocation | |
// in the real world, we can't assume anything about the system allocator and it could return null at any time | |
if layout.size() >= 5000 { | |
// The first allocation happens in "a".repeat(5000), so I'm using a counter to skip the first one | |
// (Horrible idea but it "works" for this example) | |
static mut ALLOCATIONS: usize = 0; | |
if ALLOCATIONS == 1 { | |
// If this is the second allocation, return null to indicate an allocation error | |
return ptr::null_mut(); | |
} | |
ALLOCATIONS += 1; | |
} | |
// Otherwise just delegate to the normal allocator | |
self.0.alloc(layout) | |
} | |
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { | |
// Nothing special to do here | |
self.0.dealloc(ptr, layout) | |
} | |
} | |
// Wrap the system allocator | |
#[global_allocator] | |
static ALLOC: BadAllocator<std::alloc::System> = BadAllocator(std::alloc::System); | |
fn main() { | |
// some special number that's "unlikely to be used somewhere else" in unrelated places | |
let _ = JsString::new(&"a".repeat(5000)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment