summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNugine <nugine@foxmail.com>2022-10-08 22:04:00 +0800
committerGitHub <noreply@github.com>2022-10-08 19:34:00 +0530
commita3432e54c7214dd37b7318ad03442b8415fb4f67 (patch)
treee570669bd9de5fcd02a5c34c2c9cdcaa4a34db50
parent206aa191371b9122719e5ed5a97801581f88562d (diff)
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.
-rw-r--r--serde_v8/de.rs37
1 files changed, 16 insertions, 21 deletions
diff --git a/serde_v8/de.rs b/serde_v8/de.rs
index 87e3fb1f6..554b2c366 100644
--- a/serde_v8/de.rs
+++ b/serde_v8/de.rs
@@ -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)
}
}