From b98a49d18d66d8a693c699fdec14ae2627d81ab1 Mon Sep 17 00:00:00 2001 From: "Ilya (Marshal)" Date: Sat, 21 Jun 2025 00:50:27 +0200 Subject: [PATCH 1/3] Fix handling of concatenated objects / CBOR sequence --- pytests/test_dag_cbor.py | 19 +++++++++++++++++++ src/lib.rs | 14 ++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/pytests/test_dag_cbor.py b/pytests/test_dag_cbor.py index d0f7ee5..6c2d1ef 100644 --- a/pytests/test_dag_cbor.py +++ b/pytests/test_dag_cbor.py @@ -227,3 +227,22 @@ def test_dag_cbor_decode_negative_infinity_f32_error() -> None: libipld.decode_dag_cbor(bytes.fromhex('faff800000')) assert 'number out of range for f32' in str(exc_info.value).lower() + + +def test_dag_cbor_decode_cbor_sequence_error() -> None: + # 0000 - two CBOR zeros (CBOR sequence), invalid in DAG-CBOR + with pytest.raises(ValueError) as exc_info: + libipld.decode_dag_cbor(bytes.fromhex('0000')) + + assert 'multiple objects' in str(exc_info.value).lower() + + +def test_decode_dag_cbor_multi() -> None: + # 0001 - two CBOR zeros (CBOR sequence), valid in DAG-CBOR + dag_cbor = bytes.fromhex('0000') + decoded = libipld.decode_dag_cbor_multi(dag_cbor) + + assert isinstance(decoded, list) + assert len(decoded) == 2 + assert decoded[0] == 0 + assert decoded[1] == 0 diff --git a/src/lib.rs b/src/lib.rs index 32248ae..1d90a91 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -481,9 +481,19 @@ pub fn decode_car<'py>(py: Python<'py>, data: &[u8]) -> PyResult<(PyObject, Boun #[pyfunction] pub fn decode_dag_cbor(py: Python, data: &[u8]) -> PyResult { - let py_object = decode_dag_cbor_to_pyobject(py, &mut BufReader::new(Cursor::new(data)), 0); + let mut reader = BufReader::new(Cursor::new(data)); + let py_object = decode_dag_cbor_to_pyobject(py, &mut reader, 0); if let Ok(py_object) = py_object { - Ok(py_object) + // check for any remaining data in the reader + let mut buf = [0u8; 1]; + match reader.read(&mut buf) { + Ok(0) => Ok(py_object), // EOF + Err(_) => Ok(py_object), // EOF + Ok(_) => Err(get_err( + "Failed to decode DAG-CBOR", + "Invalid DAG-CBOR: contains multiple objects (CBOR sequence)".to_string() + )), + } } else { let err = get_err( "Failed to decode DAG-CBOR", From 06383ca7847266c48de692ade7e0aabb5926c3a0 Mon Sep 17 00:00:00 2001 From: "Ilya (Marshal)" Date: Sat, 21 Jun 2025 00:56:41 +0200 Subject: [PATCH 2/3] fix comment --- pytests/test_dag_cbor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytests/test_dag_cbor.py b/pytests/test_dag_cbor.py index 6c2d1ef..b5053bf 100644 --- a/pytests/test_dag_cbor.py +++ b/pytests/test_dag_cbor.py @@ -238,7 +238,7 @@ def test_dag_cbor_decode_cbor_sequence_error() -> None: def test_decode_dag_cbor_multi() -> None: - # 0001 - two CBOR zeros (CBOR sequence), valid in DAG-CBOR + # 0000 - two CBOR zeros (CBOR sequence), valid in DAG-CBOR dag_cbor = bytes.fromhex('0000') decoded = libipld.decode_dag_cbor_multi(dag_cbor) From 930561c44f153578993695f7e99428b4de80cd3c Mon Sep 17 00:00:00 2001 From: "Ilya (Marshal)" Date: Sat, 21 Jun 2025 00:58:46 +0200 Subject: [PATCH 3/3] fix comment --- pytests/test_dag_cbor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytests/test_dag_cbor.py b/pytests/test_dag_cbor.py index b5053bf..e8a73d7 100644 --- a/pytests/test_dag_cbor.py +++ b/pytests/test_dag_cbor.py @@ -238,7 +238,7 @@ def test_dag_cbor_decode_cbor_sequence_error() -> None: def test_decode_dag_cbor_multi() -> None: - # 0000 - two CBOR zeros (CBOR sequence), valid in DAG-CBOR + # 0000 - two CBOR zeros (CBOR sequence), valid only for decode_dag_cbor_multi dag_cbor = bytes.fromhex('0000') decoded = libipld.decode_dag_cbor_multi(dag_cbor)