From 10e190df27802364e0ad77c47991f6a20633b845 Mon Sep 17 00:00:00 2001 From: Ilya Siamionau Date: Fri, 1 Mar 2024 18:29:44 +0100 Subject: [PATCH] Fix non-string map keys check in decode_dag_cbor (#17) --- pytests/test_dag_cbor.py | 10 +++++++++- src/lib.rs | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/pytests/test_dag_cbor.py b/pytests/test_dag_cbor.py index 1edfc43..ce4a021 100644 --- a/pytests/test_dag_cbor.py +++ b/pytests/test_dag_cbor.py @@ -26,7 +26,7 @@ def _dag_cbor_roundtrip(benchmark, data) -> None: assert obj == decoded, f'{obj} != {decoded}' -def test_dag_cbor_decode_duplicate_keys() -> None: +def test_dag_cbor_decode_duplicate_keys_error() -> None: with pytest.raises(ValueError) as exc_info: # {"abc": 1, "abc": 2} libipld.decode_dag_cbor(bytes.fromhex('a263616263016361626302')) @@ -34,6 +34,14 @@ def test_dag_cbor_decode_duplicate_keys() -> None: assert 'Duplicate keys are not allowed' in str(exc_info.value) +def test_dag_cbor_decode_non_string_key_error() -> None: + with pytest.raises(ValueError) as exc_info: + # {1:2} + libipld.decode_dag_cbor(bytes.fromhex('A10102')) + + assert 'Map keys must be strings' in str(exc_info.value) + + @pytest.mark.parametrize('data', load_data_fixtures(_ROUNDTRIP_DATA_DIR), ids=lambda data: data[0]) def test_dag_cbor_encode(benchmark, data) -> None: _dag_cbor_encode(benchmark, data) diff --git a/src/lib.rs b/src/lib.rs index c98846e..4453b5c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -79,7 +79,15 @@ fn decode_dag_cbor_to_pyobject(py: Python, r: &mut R, deep: usiz let len = decode_len(decode::read_uint(r, major)?)?; let dict = PyDict::new(py); for _ in 0..len { - let key = decode_dag_cbor_to_pyobject(py, r, deep + 1)?; + // DAG-CBOR keys are always strings + let key_major = decode::read_major(r)?; + if key_major.kind() != MajorKind::TextString { + return Err(anyhow::anyhow!("Map keys must be strings")); + } + + let key_len = decode::read_uint(r, key_major)?; + let key = decode::read_str(r, key_len)?.to_object(py); + let value = decode_dag_cbor_to_pyobject(py, r, deep + 1)?; if dict.get_item(&key)?.is_some() {