mirror of
https://github.com/denoland/deno.git
synced 2025-03-03 09:31:22 -05:00
fix(serde_v8): avoid creating unsound slice reference (#16189)
This commit fixes one ocurrence of unsoundness by using the newly added API (`v8::String::write_utf8_uninit`). See also [`clippy:uninit_vec`](https://rust-lang.github.io/rust-clippy/master/index.html#uninit_vec). Note that it is not actually a bug. Avoiding unsoundness improves our code quality.
This commit is contained in:
parent
206aa19137
commit
a3432e54c7
1 changed files with 16 additions and 21 deletions
|
@ -733,28 +733,26 @@ fn to_utf8_fast(
|
|||
scope: &mut v8::HandleScope,
|
||||
) -> Option<String> {
|
||||
// Over-allocate by 20% to avoid checking string twice
|
||||
let len = s.length();
|
||||
let capacity = (len as f64 * 1.2) as usize;
|
||||
let str_chars = s.length();
|
||||
let capacity = (str_chars as f64 * 1.2) as usize;
|
||||
let mut buf = Vec::with_capacity(capacity);
|
||||
|
||||
let mut nchars = 0;
|
||||
let data = buf.as_mut_ptr();
|
||||
let length = s.write_utf8(
|
||||
let bytes_len = s.write_utf8_uninit(
|
||||
scope,
|
||||
// SAFETY: we're essentially providing the raw internal slice/buffer owned by the Vec
|
||||
// which fulfills all of from_raw_parts_mut's safety requirements besides "initialization"
|
||||
// and since we're operating on a [u8] not [T] we can safely assume the slice's values
|
||||
// are sufficiently "initialized" for writes
|
||||
unsafe { std::slice::from_raw_parts_mut(data, capacity) },
|
||||
buf.spare_capacity_mut(),
|
||||
Some(&mut nchars),
|
||||
v8::WriteOptions::NO_NULL_TERMINATION
|
||||
| v8::WriteOptions::REPLACE_INVALID_UTF8,
|
||||
);
|
||||
if nchars < len {
|
||||
|
||||
if nchars < str_chars {
|
||||
return None;
|
||||
}
|
||||
// SAFETY: write_utf8 guarantees `length` bytes are initialized & valid utf8
|
||||
|
||||
// SAFETY: write_utf8_uninit guarantees `bytes_len` bytes are initialized & valid utf8
|
||||
unsafe {
|
||||
buf.set_len(length);
|
||||
buf.set_len(bytes_len);
|
||||
Some(String::from_utf8_unchecked(buf))
|
||||
}
|
||||
}
|
||||
|
@ -765,21 +763,18 @@ fn to_utf8_slow(
|
|||
) -> String {
|
||||
let capacity = s.utf8_length(scope);
|
||||
let mut buf = Vec::with_capacity(capacity);
|
||||
let data = buf.as_mut_ptr();
|
||||
let length = s.write_utf8(
|
||||
|
||||
let bytes_len = s.write_utf8_uninit(
|
||||
scope,
|
||||
// SAFETY: we're essentially providing the raw internal slice/buffer owned by the Vec
|
||||
// which fulfills all of from_raw_parts_mut's safety requirements besides "initialization"
|
||||
// and since we're operating on a [u8] not [T] we can safely assume the slice's values
|
||||
// are sufficiently "initialized" for writes
|
||||
unsafe { std::slice::from_raw_parts_mut(data, capacity) },
|
||||
buf.spare_capacity_mut(),
|
||||
None,
|
||||
v8::WriteOptions::NO_NULL_TERMINATION
|
||||
| v8::WriteOptions::REPLACE_INVALID_UTF8,
|
||||
);
|
||||
// SAFETY: write_utf8 guarantees `length` bytes are initialized & valid utf8
|
||||
|
||||
// SAFETY: write_utf8_uninit guarantees `bytes_len` bytes are initialized & valid utf8
|
||||
unsafe {
|
||||
buf.set_len(length);
|
||||
buf.set_len(bytes_len);
|
||||
String::from_utf8_unchecked(buf)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue