@@ -488,6 +488,87 @@ impl Deserialize for Int {
488488 }
489489}
490490
491+ const BOUNDED_BYTES_CHUNK_SIZE : usize = 64 ;
492+
493+ pub ( crate ) fn write_bounded_bytes < ' se , W : Write > ( serializer : & ' se mut Serializer < W > , bytes : & [ u8 ] ) -> cbor_event:: Result < & ' se mut Serializer < W > > {
494+ if bytes. len ( ) <= BOUNDED_BYTES_CHUNK_SIZE {
495+ serializer. write_bytes ( bytes)
496+ } else {
497+ // to get around not having access from outside the library we just write the raw CBOR indefinite byte string code here
498+ serializer. write_raw_bytes ( & [ 0x5f ] ) ?;
499+ for chunk in bytes. chunks ( BOUNDED_BYTES_CHUNK_SIZE ) {
500+ serializer. write_bytes ( chunk) ?;
501+ }
502+ serializer. write_special ( CBORSpecial :: Break )
503+ }
504+ }
505+
506+ pub ( crate ) fn read_bounded_bytes < R : BufRead + Seek > ( raw : & mut Deserializer < R > ) -> Result < Vec < u8 > , DeserializeError > {
507+ use std:: io:: Read ;
508+ let t = raw. cbor_type ( ) ?;
509+ if t != CBORType :: Bytes {
510+ return Err ( cbor_event:: Error :: Expected ( CBORType :: Bytes , t) . into ( ) ) ;
511+ }
512+ let ( len, len_sz) = raw. cbor_len ( ) ?;
513+ match len {
514+ cbor_event:: Len :: Len ( _) => {
515+ let bytes = raw. bytes ( ) ?;
516+ if bytes. len ( ) > BOUNDED_BYTES_CHUNK_SIZE {
517+ return Err ( DeserializeFailure :: OutOfRange {
518+ min : 0 ,
519+ max : BOUNDED_BYTES_CHUNK_SIZE ,
520+ found : bytes. len ( ) ,
521+ } . into ( ) ) ;
522+ }
523+ Ok ( bytes)
524+ } ,
525+ cbor_event:: Len :: Indefinite => {
526+ // this is CBOR indefinite encoding, but we must check that each chunk
527+ // is at most 64 big so we can't just use cbor_event's implementation
528+ // and check after the fact.
529+ // This is a slightly adopted version of what I made internally in cbor_event
530+ // but with the extra checks and not having access to non-pub methods.
531+ let mut bytes = Vec :: new ( ) ;
532+ raw. advance ( 1 + len_sz) ?;
533+ // TODO: also change this + check at end of loop to the following after we update cbor_event
534+ //while raw.cbor_type()? != CBORType::Special || !raw.special_break()? {
535+ while raw. cbor_type ( ) ? != CBORType :: Special {
536+ let chunk_t = raw. cbor_type ( ) ?;
537+ if chunk_t != CBORType :: Bytes {
538+ return Err ( cbor_event:: Error :: Expected ( CBORType :: Bytes , chunk_t) . into ( ) ) ;
539+ }
540+ let ( chunk_len, chunk_len_sz) = raw. cbor_len ( ) ?;
541+ match chunk_len {
542+ // TODO: use this error instead once that PR is merged into cbor_event
543+ //cbor_event::Len::Indefinite => return Err(cbor_event::Error::InvalidIndefiniteString.into()),
544+ cbor_event:: Len :: Indefinite => return Err ( cbor_event:: Error :: CustomError ( String :: from ( "Illegal CBOR: Indefinite string found inside indefinite string" ) ) . into ( ) ) ,
545+ cbor_event:: Len :: Len ( len) => {
546+ if chunk_len_sz > BOUNDED_BYTES_CHUNK_SIZE {
547+ return Err ( DeserializeFailure :: OutOfRange {
548+ min : 0 ,
549+ max : BOUNDED_BYTES_CHUNK_SIZE ,
550+ found : chunk_len_sz,
551+ } . into ( ) ) ;
552+ }
553+ raw. advance ( 1 + chunk_len_sz) ?;
554+ raw
555+ . as_mut_ref ( )
556+ . by_ref ( )
557+ . take ( len)
558+ . read_to_end ( & mut bytes)
559+ . map_err ( |e| cbor_event:: Error :: IoError ( e) ) ?;
560+ }
561+ }
562+ }
563+ if raw. special ( ) ? != CBORSpecial :: Break {
564+ return Err ( DeserializeFailure :: EndingBreakMissing . into ( ) ) ;
565+ }
566+ Ok ( bytes)
567+ } ,
568+ }
569+
570+ }
571+
491572#[ wasm_bindgen]
492573#[ derive( Clone , Debug , Eq , Ord , PartialEq , PartialOrd ) ]
493574pub struct BigInt ( num_bigint:: BigInt ) ;
@@ -538,15 +619,15 @@ impl cbor_event::se::Serialize for BigInt {
538619 num_bigint:: Sign :: Plus |
539620 num_bigint:: Sign :: NoSign => {
540621 serializer. write_tag ( 2u64 ) ?;
541- serializer . write_bytes ( bytes) ?;
622+ write_bounded_bytes ( serializer , & bytes) ?;
542623 } ,
543624 // negative bigint
544625 num_bigint:: Sign :: Minus => {
545626 serializer. write_tag ( 3u64 ) ?;
546627 use std:: ops:: Neg ;
547628 // CBOR RFC defines this as the bytes of -n -1
548629 let adjusted = self . 0 . clone ( ) . neg ( ) . checked_sub ( & num_bigint:: BigInt :: from ( 1u32 ) ) . unwrap ( ) . to_biguint ( ) . unwrap ( ) ;
549- serializer . write_bytes ( adjusted. to_bytes_be ( ) ) ?;
630+ write_bounded_bytes ( serializer , & adjusted. to_bytes_be ( ) ) ?;
550631 } ,
551632 }
552633 }
@@ -561,10 +642,7 @@ impl Deserialize for BigInt {
561642 // bigint
562643 CBORType :: Tag => {
563644 let tag = raw. tag ( ) ?;
564- let bytes = raw. bytes ( ) ?;
565- if bytes. len ( ) > 64 {
566- return Err ( DeserializeFailure :: OutOfRange { found : bytes. len ( ) , min : 0 , max : 64 } . into ( ) )
567- }
645+ let bytes = read_bounded_bytes ( raw) ?;
568646 match tag {
569647 // positive bigint
570648 2 => Ok ( Self ( num_bigint:: BigInt :: from_bytes_be ( num_bigint:: Sign :: Plus , & bytes) ) ) ,
@@ -1673,4 +1751,50 @@ mod tests {
16731751 let x_rt = BigInt :: from_bytes ( x. to_bytes ( ) ) . unwrap ( ) ;
16741752 assert_eq ! ( x. to_str( ) , x_rt. to_str( ) ) ;
16751753 }
1754+
1755+ #[ test]
1756+ fn bounded_bytes_read_chunked ( ) {
1757+ use std:: io:: Cursor ;
1758+ let chunks = vec ! [
1759+ vec![
1760+ 0x52 , 0x73 , 0x6F , 0x6D , 0x65 , 0x20 , 0x72 , 0x61 , 0x6E , 0x64 , 0x6F , 0x6D , 0x20 , 0x73 ,
1761+ 0x74 , 0x72 , 0x69 , 0x6E , 0x67 ,
1762+ ] ,
1763+ vec![ 0x44 , 0x01 , 0x02 , 0x03 , 0x04 ] ,
1764+ ] ;
1765+ let mut expected = Vec :: new ( ) ;
1766+ for chunk in chunks. iter ( ) {
1767+ expected. extend_from_slice ( & chunk[ 1 ..] ) ;
1768+ }
1769+ let mut vec = vec ! [ 0x5f ] ;
1770+ for mut chunk in chunks {
1771+ vec. append ( & mut chunk) ;
1772+ }
1773+ vec. push ( 0xff ) ;
1774+ let mut raw = Deserializer :: from ( Cursor :: new ( vec. clone ( ) ) ) ;
1775+ let found = read_bounded_bytes ( & mut raw) . unwrap ( ) ;
1776+ assert_eq ! ( found, expected) ;
1777+ }
1778+
1779+ #[ test]
1780+ fn bounded_bytes_write_chunked ( ) {
1781+ let mut chunk_64 = vec ! [ 0x58 , BOUNDED_BYTES_CHUNK_SIZE as u8 ] ;
1782+ chunk_64. extend ( std:: iter:: repeat ( 37 ) . take ( BOUNDED_BYTES_CHUNK_SIZE ) ) ;
1783+ let chunks = vec ! [
1784+ chunk_64,
1785+ vec![ 0x44 , 0x01 , 0x02 , 0x03 , 0x04 ] ,
1786+ ] ;
1787+ let mut input = Vec :: new ( ) ;
1788+ input. extend_from_slice ( & chunks[ 0 ] [ 2 ..] ) ;
1789+ input. extend_from_slice ( & chunks[ 1 ] [ 1 ..] ) ;
1790+ let mut serializer = cbor_event:: se:: Serializer :: new_vec ( ) ;
1791+ write_bounded_bytes ( & mut serializer, & input) . unwrap ( ) ;
1792+ let written = serializer. finalize ( ) ;
1793+ let mut expected = vec ! [ 0x5f ] ;
1794+ for mut chunk in chunks {
1795+ expected. append ( & mut chunk) ;
1796+ }
1797+ expected. push ( 0xff ) ;
1798+ assert_eq ! ( expected, written) ;
1799+ }
16761800}
0 commit comments