@@ -53,14 +53,18 @@ impl<'de> dec::Read<'de> for SliceReader<'de> {
5353
5454 #[ inline]
5555 fn fill < ' b > ( & ' b mut self , want : usize ) -> Result < dec:: Reference < ' de , ' b > , Self :: Error > {
56- let len = core:: cmp:: min ( self . buf . len ( ) , want) ;
57- Ok ( dec:: Reference :: Long ( & self . buf [ ..len] ) )
56+ let buf = self . buf ;
57+ let buf_len = buf. len ( ) ;
58+ let len = if buf_len < want { buf_len } else { want } ;
59+ Ok ( dec:: Reference :: Long ( & buf[ ..len] ) )
5860 }
5961
6062 #[ inline]
6163 fn advance ( & mut self , n : usize ) {
62- let len = core:: cmp:: min ( self . buf . len ( ) , n) ;
63- self . buf = & self . buf [ len..] ;
64+ let buf = self . buf ;
65+ let buf_len = buf. len ( ) ;
66+ let len = if buf_len < n { buf_len } else { n } ;
67+ self . buf = & buf[ len..] ;
6468 }
6569}
6670
@@ -221,9 +225,9 @@ where
221225 }
222226 major:: MAP => {
223227 let len = types:: Map :: len ( r) ?. expect ( "contains length" ) ;
224- let dict = PyDict :: new ( py) ;
225-
226228 let mut prev_key: Option < & [ u8 ] > = None ;
229+
230+ let mut items: Vec < ( Py < PyAny > , Py < PyAny > ) > = Vec :: with_capacity ( len) ;
227231 for _ in 0 ..len {
228232 // DAG-CBOR keys are always strings. Python does the UTF-8 validation when creating
229233 // the string.
@@ -242,9 +246,17 @@ where
242246 prev_key = Some ( key) ;
243247
244248 let value_py = decode_dag_cbor_to_pyobject ( py, r, depth + 1 ) ?;
245- dict. set_item ( key_py, value_py) ?;
249+
250+ items. push ( ( key_py. unbind ( ) . into ( ) , value_py) ) ;
251+ }
252+
253+ let seq = PyList :: empty ( py) ;
254+ for ( key, value) in items {
255+ let pair = PyTuple :: new ( py, & [ key, value] ) ?;
256+ seq. append ( pair) ?;
246257 }
247258
259+ let dict = PyDict :: from_sequence ( & seq) ?;
248260 dict. into_pyobject ( py) ?. into ( )
249261 }
250262 major:: TAG => {
@@ -429,18 +441,35 @@ where
429441 let mut shift = 0 ;
430442
431443 loop {
432- let byte =
433- peek_one ( r) . map_err ( |_| anyhow ! ( "Unexpected EOF while reading ULEB128 number." ) ) ?;
434- r. advance ( 1 ) ;
444+ // Read up to 10 bytes at once (max length of u64 LEB128)
445+ let reference = r
446+ . fill ( 10 )
447+ . map_err ( |_| anyhow ! ( "Unexpected EOF while reading ULEB128 number." ) ) ?;
448+ let buf = reference. as_ref ( ) ;
449+
450+ if buf. is_empty ( ) {
451+ return Err ( anyhow ! ( "Unexpected EOF while reading ULEB128 number." ) ) ;
452+ }
435453
436- if ( byte & 0x80 ) == 0 {
437- result |= ( byte as u64 ) << shift;
438- return Ok ( result) ;
439- } else {
440- result |= ( byte as u64 & 0x7F ) << shift;
454+ let mut consumed = 0 ;
455+ for & byte in buf {
456+ consumed += 1 ;
457+
458+ if ( byte & 0x80 ) == 0 {
459+ result |= ( byte as u64 ) << shift;
460+ r. advance ( consumed) ;
461+ return Ok ( result) ;
462+ } else {
463+ result |= ( byte as u64 & 0x7F ) << shift;
464+ shift += 7 ;
465+ if shift >= 64 {
466+ return Err ( anyhow ! ( "ULEB128 is too large for u64" ) ) ;
467+ }
468+ }
441469 }
442470
443- shift += 7 ;
471+ // All bytes in this chunk had continuation bit set; advance and continue
472+ r. advance ( consumed) ;
444473 }
445474}
446475
0 commit comments