@@ -215,6 +215,9 @@ impl<'a> ExactSizeIterator for Decode<'a> {
215
215
/// This is a convenience wrapper around `encode`.
216
216
#[ inline]
217
217
pub fn encode_str ( input : & str ) -> Option < String > {
218
+ if input. len ( ) > u32:: MAX as usize {
219
+ return None ;
220
+ }
218
221
let mut buf = String :: with_capacity ( input. len ( ) ) ;
219
222
encode_into ( input. chars ( ) , & mut buf) . ok ( ) . map ( |( ) | buf)
220
223
}
@@ -224,6 +227,9 @@ pub fn encode_str(input: &str) -> Option<String> {
224
227
/// Return None on overflow, which can only happen on inputs that would take more than
225
228
/// 63 encoded bytes, the DNS limit on domain name labels.
226
229
pub fn encode ( input : & [ char ] ) -> Option < String > {
230
+ if input. len ( ) > u32:: MAX as usize {
231
+ return None ;
232
+ }
227
233
let mut buf = String :: with_capacity ( input. len ( ) ) ;
228
234
encode_into ( input. iter ( ) . copied ( ) , & mut buf)
229
235
. ok ( )
@@ -235,9 +241,9 @@ where
235
241
I : Iterator < Item = char > + Clone ,
236
242
{
237
243
// Handle "basic" (ASCII) code points. They are encoded as-is.
238
- let ( mut input_length, mut basic_length) = ( 0 , 0 ) ;
244
+ let ( mut input_length, mut basic_length) = ( 0u32 , 0 ) ;
239
245
for c in input. clone ( ) {
240
- input_length += 1 ;
246
+ input_length = input_length . checked_add ( 1 ) . ok_or ( ( ) ) ? ;
241
247
if c. is_ascii ( ) {
242
248
output. push ( c) ;
243
249
basic_length += 1 ;
@@ -311,3 +317,12 @@ fn value_to_digit(value: u32) -> char {
311
317
_ => panic ! ( ) ,
312
318
}
313
319
}
320
+
321
+ #[ test]
322
+ #[ ignore = "slow" ]
323
+ #[ cfg( target_pointer_width = "64" ) ]
324
+ fn huge_encode ( ) {
325
+ let mut buf = String :: new ( ) ;
326
+ assert ! ( encode_into( std:: iter:: repeat( 'ß' ) . take( u32 :: MAX as usize + 1 ) , & mut buf) . is_err( ) ) ;
327
+ assert_eq ! ( buf. len( ) , 0 ) ;
328
+ }
0 commit comments