@@ -64,29 +64,24 @@ impl<'de> dec::Read<'de> for SliceReader<'de> {
6464 }
6565}
6666
67- fn cid_hash_to_pydict < ' py > ( py : Python < ' py > , cid : & Cid ) -> Bound < ' py , PyDict > {
67+ fn cid_hash_to_pydict < ' py > ( py : Python < ' py > , cid : & Cid ) -> PyResult < Bound < ' py , PyDict > > {
6868 let hash = cid. hash ( ) ;
6969 let dict_obj = PyDict :: new ( py) ;
7070
71- dict_obj. set_item ( "code" , hash. code ( ) ) . unwrap ( ) ;
72- dict_obj. set_item ( "size" , hash. size ( ) ) . unwrap ( ) ;
73- dict_obj
74- . set_item ( "digest" , PyBytes :: new ( py, hash. digest ( ) ) )
75- . unwrap ( ) ;
71+ dict_obj. set_item ( "code" , hash. code ( ) ) ?;
72+ dict_obj. set_item ( "size" , hash. size ( ) ) ?;
73+ dict_obj. set_item ( "digest" , PyBytes :: new ( py, hash. digest ( ) ) ) ?;
7674
77- dict_obj
75+ Ok ( dict_obj)
7876}
7977
80- fn cid_to_pydict < ' py > ( py : Python < ' py > , cid : & Cid ) -> Bound < ' py , PyDict > {
78+ fn cid_to_pydict < ' py > ( py : Python < ' py > , cid : & Cid ) -> PyResult < Bound < ' py , PyDict > > {
8179 let dict_obj = PyDict :: new ( py) ;
8280
83- dict_obj. set_item ( "version" , cid. version ( ) as u64 ) . unwrap ( ) ;
84- dict_obj. set_item ( "codec" , cid. codec ( ) ) . unwrap ( ) ;
85- dict_obj
86- . set_item ( "hash" , cid_hash_to_pydict ( py, cid) )
87- . unwrap ( ) ;
88-
89- dict_obj
81+ dict_obj. set_item ( "version" , cid. version ( ) as u64 ) ?;
82+ dict_obj. set_item ( "codec" , cid. codec ( ) ) ?;
83+ dict_obj. set_item ( "hash" , cid_hash_to_pydict ( py, cid) ?) ?;
84+ Ok ( dict_obj)
9085}
9186
9287fn map_key_cmp ( a : & [ u8 ] , b : & [ u8 ] ) -> std:: cmp:: Ordering {
@@ -256,8 +251,10 @@ where
256251
257252 let cid = <types:: Bytes < & [ u8 ] > >:: decode ( r) ?. 0 ;
258253
259- // Parse the CID for validation. They have a zero byte at the front, strip it off.
260- if Cid :: try_from ( & cid[ 1 ..] ) . is_err ( ) {
254+ if cid. len ( ) <= 1 {
255+ return Err ( anyhow ! ( "CID is empty or too short" ) ) ;
256+ } else if Cid :: try_from ( & cid[ 1 ..] ) . is_err ( ) {
257+ // Parse the CID for validation. They have a zero byte at the front, strip it off.
261258 return Err ( anyhow ! ( "Invalid CID" ) ) ;
262259 }
263260
@@ -434,11 +431,23 @@ where
434431 peek_one ( r) . map_err ( |_| anyhow ! ( "Unexpected EOF while reading ULEB128 number." ) ) ?;
435432 r. advance ( 1 ) ;
436433
437- if ( byte & 0x80 ) == 0 {
438- result |= ( byte as u64 ) << shift;
434+ if shift == 63 && byte != 0x00 && byte != 0x01 {
435+ // consume remaining continuation bytes so reader stays in sync
436+ let mut b = byte;
437+ while b & 0x80 != 0 {
438+ b = peek_one ( r) . map_err ( |_| {
439+ anyhow ! ( "Unexpected EOF while skipping overflowing ULEB128 number." )
440+ } ) ?;
441+ r. advance ( 1 ) ;
442+ }
443+ return Err ( anyhow ! ( "ULEB128 overflow" ) ) ;
444+ }
445+
446+ let low_bits = ( byte & !0x80 ) as u64 ;
447+ result |= low_bits << shift;
448+
449+ if byte & 0x80 == 0 {
439450 return Ok ( result) ;
440- } else {
441- result |= ( byte as u64 & 0x7F ) << shift;
442451 }
443452
444453 shift += 7 ;
@@ -603,7 +612,7 @@ fn get_cid_from_py_any(data: &Bound<PyAny>) -> PyResult<Cid> {
603612
604613#[ pyfunction]
605614fn decode_cid < ' py > ( py : Python < ' py > , data : & Bound < PyAny > ) -> PyResult < Bound < ' py , PyDict > > {
606- Ok ( cid_to_pydict ( py, & get_cid_from_py_any ( data) ?) )
615+ cid_to_pydict ( py, & get_cid_from_py_any ( data) ?)
607616}
608617
609618#[ pyfunction]
0 commit comments