Skip to content

Commit 469f3c7

Browse files
committed
Fix panic on non UTF-8 string
1 parent a3b2a64 commit 469f3c7

2 files changed

Lines changed: 14 additions & 4 deletions

File tree

pytests/test_dag_cbor.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,11 @@ def test_recursion_limit_exceed_on_nested_maps() -> None:
135135
libipld.decode_dag_cbor(dag_cbor)
136136

137137
assert 'in DAG-CBOR decoding' in str(exc_info.value)
138+
139+
140+
def test_dag_cbor_decode_invalid_utf8() -> None:
141+
with pytest.raises(ValueError) as exc_info:
142+
libipld.decode_dag_cbor(bytes.fromhex('62c328'))
143+
144+
145+
assert 'Invalid UTF-8 string' in str(exc_info.value)

src/lib.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,13 @@ fn get_bytes_from_py_any<'py>(obj: &'py Bound<'py, PyAny>) -> PyResult<&'py [u8]
9696
}
9797
}
9898

99-
fn string_new_bound<'py>(py: Python<'py>, s: &[u8]) -> Bound<'py, PyString> {
99+
fn string_new_bound<'py>(py: Python<'py>, s: &[u8]) -> Result<Bound<'py, PyString>> {
100+
std::str::from_utf8(s).map_err(|e| anyhow!("Invalid UTF-8 string: {}", e))?;
101+
100102
let ptr = s.as_ptr() as *const c_char;
101103
let len = s.len() as ffi::Py_ssize_t;
102104
unsafe {
103-
Bound::from_owned_ptr(py, ffi::PyUnicode_FromStringAndSize(ptr, len)).downcast_into_unchecked()
105+
Ok(Bound::from_owned_ptr(py, ffi::PyUnicode_FromStringAndSize(ptr, len)).downcast_into_unchecked())
104106
}
105107
}
106108

@@ -129,7 +131,7 @@ fn decode_dag_cbor_to_pyobject<R: Read + Seek>(
129131
}
130132
MajorKind::TextString => {
131133
let len = decode::read_uint(r, major)?;
132-
string_new_bound(py, &decode::read_bytes(r, len)?).into_pyobject(py)?.into()
134+
string_new_bound(py, &decode::read_bytes(r, len)?)?.into_pyobject(py)?.into()
133135
}
134136
MajorKind::Array => {
135137
let len: ffi::Py_ssize_t = decode_len(decode::read_uint(r, major)?)?.try_into()?;
@@ -167,7 +169,7 @@ fn decode_dag_cbor_to_pyobject<R: Read + Seek>(
167169
}
168170
}
169171

170-
let key_py = string_new_bound(py, key.as_slice()).into_pyobject(py)?;
172+
let key_py = string_new_bound(py, key.as_slice())?.into_pyobject(py)?;
171173
prev_key = Some(key);
172174

173175
let value_py = decode_dag_cbor_to_pyobject(py, r, depth + 1)?;

0 commit comments

Comments
 (0)