@@ -557,6 +557,17 @@ pub mod context {
557
557
let ts = Timestamp :: from_unix ( & context, seconds, subsec_nanos) ;
558
558
assert_eq ! ( 1 , ts. counter) ;
559
559
}
560
+
561
+ #[ test]
562
+ fn context_overflow ( ) {
563
+ let seconds = u64:: MAX ;
564
+ let subsec_nanos = u32:: MAX ;
565
+
566
+ let context = Context :: new ( u16:: MAX ) ;
567
+
568
+ // Ensure we don't panic
569
+ Timestamp :: from_unix ( & context, seconds, subsec_nanos) ;
570
+ }
560
571
}
561
572
}
562
573
@@ -812,14 +823,14 @@ pub mod context {
812
823
813
824
#[ derive( Debug ) ]
814
825
struct Adjust {
815
- by_ns : u32 ,
826
+ by_ns : u128 ,
816
827
}
817
828
818
829
impl Adjust {
819
830
#[ inline]
820
831
fn by_millis ( millis : u32 ) -> Self {
821
832
Adjust {
822
- by_ns : millis. saturating_mul ( 1_000_000 ) ,
833
+ by_ns : ( millis as u128 ) . saturating_mul ( 1_000_000 ) ,
823
834
}
824
835
}
825
836
@@ -830,23 +841,12 @@ pub mod context {
830
841
return ( seconds, subsec_nanos) ;
831
842
}
832
843
833
- let mut shifted_subsec_nanos =
834
- subsec_nanos. checked_add ( self . by_ns ) . unwrap_or ( subsec_nanos) ;
844
+ let ts = ( seconds as u128 )
845
+ . saturating_mul ( 1_000_000_000 )
846
+ . saturating_add ( subsec_nanos as u128 )
847
+ . saturating_add ( self . by_ns as u128 ) ;
835
848
836
- if shifted_subsec_nanos < 1_000_000_000 {
837
- // The shift hasn't overflowed into the next second
838
- ( seconds, shifted_subsec_nanos)
839
- } else {
840
- // The shift has overflowed into the next second
841
- shifted_subsec_nanos -= 1_000_000_000 ;
842
-
843
- if seconds < u64:: MAX {
844
- ( seconds + 1 , shifted_subsec_nanos)
845
- } else {
846
- // The next second would overflow a `u64`
847
- ( seconds, subsec_nanos)
848
- }
849
- }
849
+ ( ( ts / 1_000_000_000 ) as u64 , ( ts % 1_000_000_000 ) as u32 )
850
850
}
851
851
}
852
852
@@ -878,7 +878,9 @@ pub mod context {
878
878
#[ inline]
879
879
fn from_ts ( seconds : u64 , subsec_nanos : u32 ) -> Self {
880
880
// Reseed when the millisecond advances
881
- let last_seed = ( seconds * 1_000 ) + ( subsec_nanos as u64 / 1_000_000 ) ;
881
+ let last_seed = seconds
882
+ . saturating_mul ( 1_000 )
883
+ . saturating_add ( ( subsec_nanos / 1_000_000 ) as u64 ) ;
882
884
883
885
ReseedingTimestamp {
884
886
last_seed,
@@ -918,7 +920,7 @@ pub mod context {
918
920
919
921
// The factor reduces the size of the sub-millisecond precision to
920
922
// fit into the specified number of bits
921
- let factor = ( 999_999u64 / 2u64 . pow ( bits as u32 ) ) + 1 ;
923
+ let factor = ( 999_999 / u64 :: pow ( 2 , bits as u32 ) ) + 1 ;
922
924
923
925
Precision {
924
926
bits,
@@ -1113,6 +1115,21 @@ pub mod context {
1113
1115
1114
1116
assert ! ( Uuid :: new_v7( ts3) > Uuid :: new_v7( ts2) ) ;
1115
1117
}
1118
+
1119
+ #[ test]
1120
+ fn context_overflow ( ) {
1121
+ let seconds = u64:: MAX ;
1122
+ let subsec_nanos = u32:: MAX ;
1123
+
1124
+ // Ensure we don't panic
1125
+ for context in [
1126
+ ContextV7 :: new ( ) ,
1127
+ ContextV7 :: new ( ) . with_additional_precision ( ) ,
1128
+ ContextV7 :: new ( ) . with_adjust_by_millis ( u32:: MAX ) ,
1129
+ ] {
1130
+ Timestamp :: from_unix ( & context, seconds, subsec_nanos) ;
1131
+ }
1132
+ }
1116
1133
}
1117
1134
}
1118
1135
0 commit comments