0
0
Fork 0
mirror of https://github.com/denoland/rusty_v8.git synced 2024-12-26 00:59:28 -05:00

fix: better fix for empty Uint8Array (#1329)

This commit is contained in:
Matt Mastracci 2023-09-22 11:34:30 -06:00 committed by GitHub
parent 97fab5ce0f
commit bb5dadb418
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 64 additions and 6 deletions

View file

@ -267,13 +267,13 @@ impl<T: Default> FastApiTypedArray<T> {
/// Returns a slice pointing to the underlying data if safe to do so.
#[inline(always)]
pub fn get_storage_if_aligned(&self) -> Option<&mut [T]> {
// Ensure that we never create a null-ptr slice (even a zero-length null-ptr slice
// is invalid because of Rust's niche packing).
if self.data.is_null() {
// V8 may provide an invalid or null pointer when length is zero, so we just
// ignore that value completely and create an empty slice in this case.
if self.length == 0 {
return Some(&mut []);
}
// Ensure that we never return an unaligned buffer
if (self.data as usize) % align_of::<T>() != 0 {
// Ensure that we never return an unaligned or null buffer
if self.data.is_null() || (self.data as usize) % align_of::<T>() != 0 {
return None;
}
Some(unsafe { std::slice::from_raw_parts_mut(self.data, self.length) })

View file

@ -15,8 +15,8 @@ use std::ptr::{addr_of, NonNull};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use std::sync::Mutex;
use v8::fast_api::CType;
use v8::fast_api::Type::*;
use v8::fast_api::{CType, FastApiTypedArray};
use v8::inspector::ChannelBase;
use v8::{fast_api, AccessorConfiguration};
@ -9566,6 +9566,64 @@ fn test_fast_calls() {
assert_eq!("fast", unsafe { WHO });
}
#[test]
fn test_fast_calls_empty_buffer() {
static mut WHO: &str = "none";
unsafe fn fast_fn(
_recv: v8::Local<v8::Object>,
buffer: *mut FastApiTypedArray<u8>,
) {
assert_eq!(WHO, "slow");
WHO = "fast";
assert_eq!(
0,
FastApiTypedArray::get_storage_from_pointer_if_aligned(buffer)
.unwrap()
.len()
);
}
fn slow_fn(
_scope: &mut v8::HandleScope,
_args: v8::FunctionCallbackArguments,
_rv: v8::ReturnValue,
) {
unsafe {
WHO = "slow";
}
}
const FAST_TEST: fast_api::FastFunction = fast_api::FastFunction::new(
&[V8Value, TypedArray(CType::Uint8)],
fast_api::CType::Void,
fast_fn as _,
);
let _setup_guard = setup::parallel_test();
let isolate = &mut v8::Isolate::new(Default::default());
let scope = &mut v8::HandleScope::new(isolate);
let context = v8::Context::new(scope);
let scope = &mut v8::ContextScope::new(scope, context);
let global = context.global(scope);
let template = v8::FunctionTemplate::builder(slow_fn)
.build_fast(scope, &FAST_TEST, None, None, None);
let name = v8::String::new(scope, "func").unwrap();
let value = template.get_function(scope).unwrap();
global.set(scope, name.into(), value.into()).unwrap();
let source = r#"
function f(arr) { func(arr); }
%PrepareFunctionForOptimization(f);
f(new Uint8Array(0));
%OptimizeFunctionOnNextCall(f);
f(new Uint8Array(0));
"#;
eval(scope, source).unwrap();
assert_eq!(unsafe { WHO }, "fast");
}
#[test]
fn test_fast_calls_sequence() {
static mut WHO: &str = "none";