Skip to content

Commit a432d15

Browse files
committed
Avoid String::from_utf8 for loads() bytes
1 parent 6928a37 commit a432d15

4 files changed

Lines changed: 18 additions & 8 deletions

File tree

Cargo.lock

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ classifier = [
3131
]
3232

3333
[dependencies]
34+
encoding_rs = { version = "0.8", default_features = false }
3435
itoa = { version = "0.4", default_features = false }
3536
pyo3 = { path = "./pyo3", features = ["extension-module", "python3"]}
3637
serde = { version = "1", default_features = false }

src/decode.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,11 @@ pub fn deserialize(py: Python, ptr: *mut pyo3::ffi::PyObject) -> PyResult<PyObje
2828
} else if unsafe { obj_type_ptr == typeref::BYTES_PTR } {
2929
let buffer = unsafe { pyo3::ffi::PyBytes_AsString(ptr) as *const u8 };
3030
let length = unsafe { pyo3::ffi::PyBytes_Size(ptr) as usize };
31-
match String::from_utf8(unsafe { std::slice::from_raw_parts(buffer, length).to_vec() }) {
32-
Ok(string) => {
33-
data = Cow::Owned(string);
34-
}
35-
Err(_) => {
36-
return Err(JSONDecodeError::py_err((INVALID_STR, "", 0)));
37-
}
31+
let slice = unsafe { std::slice::from_raw_parts(buffer, length) };
32+
if encoding_rs::Encoding::utf8_valid_up_to(slice) == length {
33+
data = Cow::Borrowed(unsafe { std::str::from_utf8_unchecked(slice) });
34+
} else {
35+
return Err(JSONDecodeError::py_err((INVALID_STR, "", 0)));
3836
}
3937
} else {
4038
return Err(JSONDecodeError::py_err((
@@ -44,7 +42,7 @@ pub fn deserialize(py: Python, ptr: *mut pyo3::ffi::PyObject) -> PyResult<PyObje
4442
)));
4543
}
4644

47-
let seed = JsonValue{};
45+
let seed = JsonValue {};
4846
let mut deserializer = serde_json::Deserializer::from_str(&data);
4947
match seed.deserialize(&mut deserializer) {
5048
Ok(py_ptr) => {

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#[macro_use]
77
extern crate pyo3;
88

9+
extern crate encoding_rs;
910
extern crate itoa;
1011
extern crate serde;
1112
extern crate serde_json;

0 commit comments

Comments
 (0)