Skip to content

Commit 3a80f71

Browse files
authored
Fix panic on encoding map with integer keys (#60)
1 parent a3b2a64 commit 3a80f71

2 files changed

Lines changed: 29 additions & 7 deletions

File tree

pytests/test_dag_cbor.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,19 @@ 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_dab_cbor_decode_map_int_key() -> None:
141+
dag_cbor = bytes.fromhex('a10000')
142+
with pytest.raises(ValueError) as exc_info:
143+
libipld.decode_dag_cbor(dag_cbor)
144+
145+
assert 'Map keys must be strings' in str(exc_info.value)
146+
147+
148+
def test_dab_cbor_encode_map_int_key() -> None:
149+
obj = {0: 'value'}
150+
with pytest.raises(ValueError) as exc_info:
151+
libipld.encode_dag_cbor(obj)
152+
153+
assert 'Map keys must be strings' in str(exc_info.value)

src/lib.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,18 +51,24 @@ fn map_key_cmp(a: &Vec<u8>, b: &Vec<u8>) -> std::cmp::Ordering {
5151
}
5252
}
5353

54-
fn sort_map_keys(keys: &Bound<PyList>, len: usize) -> Vec<(PyBackedStr, usize)> {
54+
fn sort_map_keys(keys: &Bound<PyList>, len: usize) -> Result<Vec<(PyBackedStr, usize)>> {
5555
// Returns key and index.
5656
let mut keys_str = Vec::with_capacity(len);
5757
for i in 0..len {
58-
let item = keys.get_item(i).unwrap();
59-
let key = item.downcast::<PyString>().unwrap().to_owned();
60-
let backed_str = PyBackedStr::try_from(key).unwrap();
58+
let item = keys.get_item(i)?;
59+
let key = match item.downcast::<PyString>() {
60+
Ok(k) => k.to_owned(),
61+
Err(_) => return Err(anyhow!("Map keys must be strings")),
62+
};
63+
let backed_str = match PyBackedStr::try_from(key) {
64+
Ok(bs) => bs,
65+
Err(_) => return Err(anyhow!("Failed to convert PyString to PyBackedStr")),
66+
};
6167
keys_str.push((backed_str, i));
6268
}
6369

6470
if keys_str.len() < 2 {
65-
return keys_str;
71+
return Ok(keys_str);
6672
}
6773

6874
keys_str.sort_by(|a, b| {
@@ -78,7 +84,7 @@ fn sort_map_keys(keys: &Bound<PyList>, len: usize) -> Vec<(PyBackedStr, usize)>
7884
}
7985
});
8086

81-
keys_str
87+
Ok(keys_str)
8288
}
8389

8490
fn get_bytes_from_py_any<'py>(obj: &'py Bound<'py, PyAny>) -> PyResult<&'py [u8]> {
@@ -252,7 +258,7 @@ fn encode_dag_cbor_from_pyobject<'py, W: Write>(
252258
Ok(())
253259
} else if let Ok(map) = obj.downcast::<PyDict>() {
254260
let len = map.len();
255-
let keys = sort_map_keys(&map.keys(), len);
261+
let keys = sort_map_keys(&map.keys(), len)?;
256262
let values = map.values();
257263

258264
encode::write_u64(w, MajorKind::Map, len as u64)?;

0 commit comments

Comments
 (0)