@@ -359,10 +359,12 @@ fn parse_parts<'a, R: Reader<'a>>(first_byte: u8, reader: &mut R) -> Result<(boo
359
359
return Ok ( ( constructed, TagNumber :: new ( first_number_part. into ( ) ) ) ) ;
360
360
}
361
361
362
- let mut multi_byte_tag_number = 0 ;
362
+ let mut multi_byte_tag_number: u16 = 0 ;
363
363
364
- for _ in 0 ..Tag :: MAX_SIZE - 2 {
365
- multi_byte_tag_number <<= 7 ;
364
+ for _ in 0 ..Tag :: MAX_SIZE - 1 {
365
+ multi_byte_tag_number = multi_byte_tag_number
366
+ . checked_mul ( 0x80 )
367
+ . ok_or_else ( || Error :: new ( ErrorKind :: TagNumberInvalid , reader. position ( ) ) ) ?;
366
368
367
369
let byte = reader. read_byte ( ) ?;
368
370
multi_byte_tag_number |= u16:: from ( byte & 0x7F ) ;
@@ -372,54 +374,59 @@ fn parse_parts<'a, R: Reader<'a>>(first_byte: u8, reader: &mut R) -> Result<(boo
372
374
}
373
375
}
374
376
375
- let byte = reader. read_byte ( ) ?;
376
- if multi_byte_tag_number > u16:: MAX >> 7 || byte & 0x80 != 0 {
377
- return Err ( ErrorKind :: TagNumberInvalid . into ( ) ) ;
377
+ Err ( Error :: new ( ErrorKind :: TagNumberInvalid , reader. position ( ) ) )
378
+ }
379
+
380
+ fn tag_length ( tag_number : u16 ) -> Length {
381
+ if tag_number <= 30 {
382
+ Length :: ONE
383
+ } else if tag_number < 0x80 {
384
+ Length :: new ( 2 )
385
+ } else if tag_number < 0x80 * 0x80 {
386
+ Length :: new ( 3 )
387
+ } else {
388
+ Length :: new ( 4 )
378
389
}
379
- multi_byte_tag_number |= u16 :: from ( byte & 0x7F ) ;
390
+ }
380
391
381
- Ok ( ( constructed, TagNumber :: new ( multi_byte_tag_number) ) )
392
+ #[ allow( clippy:: cast_possible_truncation) ]
393
+ fn tag_number_bytes ( first_byte : u8 , num : u16 , buf : & mut [ u8 ; Tag :: MAX_SIZE ] ) -> & [ u8 ] {
394
+ if num <= 30 {
395
+ buf[ 0 ] = first_byte | num as u8 ;
396
+ & buf[ ..1 ]
397
+ } else if num < 0x80 {
398
+ buf[ 0 ] = first_byte | 0x1F ;
399
+ buf[ 1 ] = num as u8 ;
400
+ & buf[ ..2 ]
401
+ } else if num < 0x80 * 0x80 {
402
+ buf[ 0 ] = first_byte | 0x1F ;
403
+ buf[ 1 ] = 0x80 | ( num >> 7 ) as u8 ;
404
+ buf[ 2 ] = ( num & 0x7F ) as u8 ;
405
+ & buf[ ..3 ]
406
+ } else {
407
+ buf[ 0 ] = first_byte | 0x1F ;
408
+ buf[ 1 ] = 0x80 | ( num >> 14 ) as u8 ;
409
+ buf[ 2 ] = 0x80 | ( num >> 7 ) as u8 ;
410
+ buf[ 3 ] = ( num & 0x7F ) as u8 ;
411
+ & buf[ ..4 ]
412
+ }
382
413
}
383
414
384
415
impl Encode for Tag {
385
416
fn encoded_len ( & self ) -> Result < Length > {
386
- let number = self . number ( ) . value ( ) ;
387
-
388
- let length = if number <= 30 {
389
- Length :: ONE
390
- } else {
391
- Length :: new ( number. ilog2 ( ) as u16 / 7 + 2 )
392
- } ;
393
-
394
- Ok ( length)
417
+ Ok ( tag_length ( self . number ( ) . value ( ) ) )
395
418
}
396
419
397
420
fn encode ( & self , writer : & mut impl Writer ) -> Result < ( ) > {
398
- let mut first_byte = self . class ( ) as u8 | u8:: from ( self . is_constructed ( ) ) << 5 ;
399
-
400
- let number = self . number ( ) . value ( ) ;
401
-
402
- if number <= 30 {
403
- first_byte |= number as u8 ;
404
- writer. write_byte ( first_byte) ?;
405
- } else {
406
- first_byte |= 0x1F ;
407
- writer. write_byte ( first_byte) ?;
408
-
409
- let extra_bytes = number. ilog2 ( ) as u16 / 7 + 1 ;
410
-
411
- for shift in ( 0 ..extra_bytes) . rev ( ) {
412
- let mut byte = ( number >> ( shift * 7 ) ) as u8 & 0x7f ;
413
-
414
- if shift != 0 {
415
- byte |= 0x80 ;
416
- }
417
-
418
- writer. write_byte ( byte) ?;
419
- }
421
+ let mut first_byte = self . class ( ) as u8 ;
422
+ if self . is_constructed ( ) {
423
+ first_byte |= CONSTRUCTED_FLAG ;
420
424
}
425
+ let num = self . number ( ) . value ( ) ;
421
426
422
- Ok ( ( ) )
427
+ let mut buf = [ 0u8 ; Tag :: MAX_SIZE ] ;
428
+ let tag_bytes = tag_number_bytes ( first_byte, num, & mut buf) ;
429
+ writer. write ( tag_bytes)
423
430
}
424
431
}
425
432
@@ -499,7 +506,7 @@ impl fmt::Debug for Tag {
499
506
#[ cfg( test) ]
500
507
mod tests {
501
508
use super :: { Class , Tag , TagNumber } ;
502
- use crate :: { Length , Reader , SliceReader } ;
509
+ use crate :: { Decode , Encode , Length , Reader , SliceReader } ;
503
510
504
511
#[ test]
505
512
fn tag_class ( ) {
@@ -564,4 +571,51 @@ mod tests {
564
571
assert_eq ! ( Tag :: peek( & reader) . unwrap( ) , Tag :: Integer ) ;
565
572
assert_eq ! ( reader. position( ) , Length :: ZERO ) ; // Position unchanged
566
573
}
574
+
575
+ #[ test]
576
+ fn decode_application ( ) {
577
+ const TAG_APPLICATION : [ u8 ; 2 ] = [ 0x7F , 0x21 ] ;
578
+ let mut reader = SliceReader :: new ( & TAG_APPLICATION ) . unwrap ( ) ;
579
+ let tag = Tag :: decode ( & mut reader) . unwrap ( ) ;
580
+
581
+ assert_eq ! (
582
+ tag,
583
+ Tag :: Application {
584
+ constructed: true ,
585
+ number: TagNumber ( 33 )
586
+ }
587
+ ) ;
588
+
589
+ let mut buf = [ 0u8 ; 8 ] ;
590
+ let encoded = tag. encode_to_slice ( & mut buf) . unwrap ( ) ;
591
+
592
+ assert_eq ! ( TAG_APPLICATION , encoded) ;
593
+ }
594
+
595
+ #[ test]
596
+ fn decode_private_out_of_range ( ) {
597
+ const TAG_PRIVATE : [ u8 ; 4 ] = [ 0xFF , 0xFF , 0xFF , 0x7f ] ;
598
+ let mut reader = SliceReader :: new ( & TAG_PRIVATE ) . unwrap ( ) ;
599
+ let result = Tag :: decode ( & mut reader) ;
600
+ assert ! ( result. is_err( ) ) ;
601
+ }
602
+ #[ test]
603
+ fn decode_private ( ) {
604
+ const TAG_PRIVATE : [ u8 ; 4 ] = [ 0xFF , 0x83 , 0xFF , 0x70 ] ;
605
+ let mut reader = SliceReader :: new ( & TAG_PRIVATE ) . unwrap ( ) ;
606
+ let tag = Tag :: decode ( & mut reader) . unwrap ( ) ;
607
+
608
+ assert_eq ! (
609
+ tag,
610
+ Tag :: Private {
611
+ constructed: true ,
612
+ number: TagNumber ( 0xfff0 )
613
+ }
614
+ ) ;
615
+
616
+ let mut buf = [ 0u8 ; 8 ] ;
617
+ let encoded = tag. encode_to_slice ( & mut buf) . unwrap ( ) ;
618
+
619
+ assert_eq ! ( TAG_PRIVATE , encoded) ;
620
+ }
567
621
}
0 commit comments