@@ -104,6 +104,11 @@ enum Device {
104
104
Stdout ( Stdout ) ,
105
105
}
106
106
107
+ enum ControlCharMappingError {
108
+ IntOutOfRange ,
109
+ MultipleChars ,
110
+ }
111
+
107
112
impl AsFd for Device {
108
113
fn as_fd ( & self ) -> BorrowedFd < ' _ > {
109
114
match self {
@@ -213,13 +218,22 @@ fn stty(opts: &Options) -> UResult<()> {
213
218
format ! ( "missing argument to '{setting}'" ) ,
214
219
) ) ;
215
220
} ;
216
- if let ControlFlow :: Break ( false ) =
217
- apply_char_mapping ( & mut termios, char_index, new_cc)
218
- {
219
- return Err ( USimpleError :: new (
220
- 1 ,
221
- format ! ( "invalid mapping '{setting}' => '{new_cc}'" ) ,
222
- ) ) ;
221
+ match apply_char_mapping ( & mut termios, char_index, new_cc) {
222
+ Ok ( _) => { }
223
+ Err ( e) => match e {
224
+ ControlCharMappingError :: IntOutOfRange => {
225
+ return Err ( USimpleError :: new (
226
+ 1 ,
227
+ format ! ( "invalid integer argument: '{new_cc}': Numerical result out of range" ) ,
228
+ ) ) ;
229
+ }
230
+ ControlCharMappingError :: MultipleChars => {
231
+ return Err ( USimpleError :: new (
232
+ 1 ,
233
+ format ! ( "invalid integer argument: '{new_cc}'" ) ,
234
+ ) ) ;
235
+ }
236
+ } ,
223
237
}
224
238
} else if let ControlFlow :: Break ( false ) = apply_setting ( & mut termios, setting) {
225
239
return Err ( USimpleError :: new (
@@ -492,12 +506,14 @@ fn apply_char_mapping(
492
506
termios : & mut Termios ,
493
507
control_char_index : SpecialCharacterIndices ,
494
508
new_val : & str ,
495
- ) -> ControlFlow < bool > {
496
- if let Some ( val) = string_to_control_char ( new_val) {
497
- termios. control_chars [ control_char_index as usize ] = val;
498
- return ControlFlow :: Break ( true ) ;
509
+ ) -> Result < ( ) , ControlCharMappingError > {
510
+ match string_to_control_char ( new_val) {
511
+ Ok ( val) => {
512
+ termios. control_chars [ control_char_index as usize ] = val;
513
+ Ok ( ( ) )
514
+ }
515
+ Err ( e) => Err ( e) ,
499
516
}
500
- ControlFlow :: Break ( false )
501
517
}
502
518
503
519
// GNU stty defines some valid values for the control character mappings
@@ -509,33 +525,43 @@ fn apply_char_mapping(
509
525
// 3. Disabling the control character: '^-' or 'undef'
510
526
//
511
527
// This function returns the ascii value of valid control chars, or None if the input is invalid
512
- fn string_to_control_char ( s : & str ) -> Option < u8 > {
528
+ fn string_to_control_char ( s : & str ) -> Result < u8 , ControlCharMappingError > {
513
529
if s == "undef" || s == "^-" {
514
- return Some ( 0 ) ;
530
+ return Ok ( 0 ) ;
515
531
}
516
532
533
+ // check if the number is greater than 255, return ControlCharMappingError::IntOutOfRange
517
534
// try to parse integer (hex, octal, or decimal)
535
+ let mut ascii_num: Option < u32 > = None ;
518
536
if let Some ( hex) = s. strip_prefix ( "0x" ) {
519
- return u8 :: from_str_radix ( hex, 16 ) . ok ( ) ;
537
+ ascii_num = u32 :: from_str_radix ( hex, 16 ) . ok ( ) ;
520
538
} else if let Some ( octal) = s. strip_prefix ( "0" ) {
521
- return u8 :: from_str_radix ( octal, 8 ) . ok ( ) ;
522
- } else if let Ok ( decimal) = s. parse :: < u8 > ( ) {
523
- return Some ( decimal) ;
539
+ ascii_num = u32 :: from_str_radix ( octal, 8 ) . ok ( ) ;
540
+ } else if let Ok ( decimal) = s. parse :: < u32 > ( ) {
541
+ ascii_num = Some ( decimal) ;
524
542
}
525
543
544
+ if let Some ( val) = ascii_num {
545
+ if val > 255 {
546
+ return Err ( ControlCharMappingError :: IntOutOfRange ) ;
547
+ } else {
548
+ return Ok ( val as u8 ) ;
549
+ }
550
+ }
526
551
// try to parse ^<char> or just <char>
527
552
let mut chars = s. chars ( ) ;
528
553
match ( chars. next ( ) , chars. next ( ) ) {
529
554
( Some ( '^' ) , Some ( c) ) => {
530
555
// special case: ascii value of '^?' is greater than '?'
531
556
if c == '?' {
532
- return Some ( ASCII_DEL ) ;
557
+ return Ok ( ASCII_DEL ) ;
533
558
}
534
559
// subract by '@' to turn the char into the ascii value of '^<char>'
535
- Some ( ( c. to_ascii_uppercase ( ) as u8 ) . wrapping_sub ( b'@' ) )
560
+ Ok ( ( c. to_ascii_uppercase ( ) as u8 ) . wrapping_sub ( b'@' ) )
536
561
}
537
- ( Some ( c) , _) => Some ( c as u8 ) ,
538
- _ => None ,
562
+ ( Some ( c) , None ) => Ok ( c as u8 ) ,
563
+ ( Some ( _) , Some ( _) ) => Err ( ControlCharMappingError :: MultipleChars ) ,
564
+ _ => unreachable ! ( "No arguments provided: must have been caught earlier" ) ,
539
565
}
540
566
}
541
567
0 commit comments