You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
bugSomething isn't workingbuiltinsPRs and Issues related to builtins/intrinsicsexecutionIssues or PRs related to code executionmemoryPRs and Issues related to the memory management or memory footprint.
unsafe fn alloc(&self, layout: Layout) -> *mut u8
Allocate memory as described by the given layout.
Returns a pointer to newly-allocated memory, or null to indicate allocation failure.
If the allocation fails, then there will be a write on a null pointer on L223, which is considered UB:
A null pointer is never valid, not even for accesses of size zero.
This also leads to violating the NonNull::new_unchecked invariant:
use boa::JsString;fnmain(){// choose a string length that's large enough to cause an allocation error when concatenated later but// not too large so the initial allocation still succeedslet string = "a".repeat(1000*1000*1000);let ve = vec![&string as &str; 1000];// this is almost certainly going to cause an allocation error unless you've got lots of RAM// if it does, then this will write to a null pointer 💥let _ = JsString::concat_array(&ve);}
Alternatively, one can override the global allocator and return null for that specific allocation: link.
Implementing GlobalAlloc requires unsafe due to the nature of allocators being unsafe, but I'm fairly certain it's totally valid (albeit weird) for a crate to expose a safe API for an allocator like that.
Running the code under valgrind sums it up:
==22393== Process terminating with default action of signal 11 (SIGSEGV)
==22393== Access not within mapped region at address 0x0
==22393== at 0x110477: boa::string::JsString::concat_array
==22393== by 0x11019F: boatest::main
[1] 22393 segmentation fault (core dumped) valgrind ./target/release/boatest
Expected behavior
Handling null pointers, e.g. assert!(!inner.is_null()). Or better yet, calling std::alloc:handle_alloc_error as suggested in the docs
Razican
added
builtins
PRs and Issues related to builtins/intrinsics
execution
Issues or PRs related to code execution
memory
PRs and Issues related to the memory management or memory footprint.
labels
Feb 19, 2022
Fixes#1847 by wrapping the `std::alloc::alloc()` call in `try_alloc()`, which checks that the returned pointer is non-null and handles allocation errors that way. It will now abort the process instead of executing UB in the error path
bugSomething isn't workingbuiltinsPRs and Issues related to builtins/intrinsicsexecutionIssues or PRs related to code executionmemoryPRs and Issues related to the memory management or memory footprint.
Boa assumes that
std::alloc::alloc
never fails (returning a null pointer) even though it can.boa/boa/src/string.rs
Lines 219 to 223 in 29cd909
Quoting the docs:
If the allocation fails, then there will be a write on a null pointer on L223, which is considered UB:
This also leads to violating the
NonNull::new_unchecked
invariant:boa/boa/src/string.rs
Line 241 in 29cd909
To Reproduce
Alternatively, one can override the global allocator and return null for that specific allocation: link.
Implementing
GlobalAlloc
requires unsafe due to the nature of allocators being unsafe, but I'm fairly certain it's totally valid (albeit weird) for a crate to expose a safe API for an allocator like that.Running the code under valgrind sums it up:
Expected behavior
Handling null pointers, e.g.
assert!(!inner.is_null())
. Or better yet, callingstd::alloc:handle_alloc_error
as suggested in the docsBuild environment
The text was updated successfully, but these errors were encountered: