Skip to content

Commit

Permalink
Bugfix: Missing CPR arguments causes panic (#39)
Browse files Browse the repository at this point in the history
- Added `CSI::Invalid` and return that if CPR is missing arguments No
- No need for `CSI::new()` to return `Option` as `None` value is never
  created.
- Added test
  • Loading branch information
eivindbergem authored Jan 16, 2025
1 parent 08825e1 commit 3bfe51d
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 5 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

- Bugfix: Missing CPR arguments causes panic

## [0.5.0 - 2024-12-12]

- Removed initializer. Probe terminal size before prompt for every line.
Expand Down
1 change: 1 addition & 0 deletions noline/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ where
CSI::DSR => self.generate_output(RingBell),
CSI::SU(_) => self.generate_output(RingBell),
CSI::SD(_) => self.generate_output(RingBell),
CSI::Invalid => self.generate_output(RingBell),
},
Action::EscapeSequence(_) => self.generate_output(RingBell),
Action::Ignore => self.generate_output(Nothing),
Expand Down
35 changes: 30 additions & 5 deletions noline/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,20 +67,27 @@ pub enum CSI {
Delete,
End,
Unknown(u8),
Invalid,
}

impl CSI {
fn new(byte: u8, arg1: Option<usize>, arg2: Option<usize>) -> Option<Self> {
fn new(byte: u8, arg1: Option<usize>, arg2: Option<usize>) -> Self {
let c = byte as char;

Some(match c {
match c {
'A' => Self::CUU(arg1.unwrap_or(1)),
'B' => Self::CUD(arg1.unwrap_or(1)),
'C' => Self::CUF(arg1.unwrap_or(1)),
'D' => Self::CUB(arg1.unwrap_or(1)),
'H' => Self::CUP(arg1.unwrap_or(1), arg2.unwrap_or(1)),
'J' => Self::ED(arg1.unwrap_or(0)),
'R' => Self::CPR(arg1.unwrap(), arg2.unwrap()),
'R' => {
if let (Some(arg1), Some(arg2)) = (arg1, arg2) {
Self::CPR(arg1, arg2)
} else {
Self::Invalid
}
}
'S' => Self::SU(arg1.unwrap_or(1)),
'T' => Self::SD(arg1.unwrap_or(1)),
'n' => Self::DSR,
Expand All @@ -97,7 +104,7 @@ impl CSI {
}
}
_ => Self::Unknown(byte),
})
}
}
}

Expand All @@ -122,7 +129,7 @@ impl Action {
}

fn csi(byte: u8, arg1: Option<usize>, arg2: Option<usize>) -> Self {
Action::ControlSequenceIntroducer(CSI::new(byte, arg1, arg2).unwrap())
Action::ControlSequenceIntroducer(CSI::new(byte, arg1, arg2))
}
}

Expand Down Expand Up @@ -283,6 +290,24 @@ pub(crate) mod tests {
assert_eq!(action, Action::Ignore);
}

let mut actions = input_sequence(&mut parser, "\x1b[R");
assert_eq!(
actions.pop().unwrap(),
Action::ControlSequenceIntroducer(CSI::Invalid)
);

let mut actions = input_sequence(&mut parser, "\x1b[32R");
assert_eq!(
actions.pop().unwrap(),
Action::ControlSequenceIntroducer(CSI::Invalid)
);

let mut actions = input_sequence(&mut parser, "\x1b[32;R");
assert_eq!(
actions.pop().unwrap(),
Action::ControlSequenceIntroducer(CSI::Invalid)
);

let mut actions = input_sequence(&mut parser, "\x1b[A");

assert_eq!(
Expand Down
1 change: 1 addition & 0 deletions noline/src/testlib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ impl MockTerminal {
CSI::Home => unimplemented!(),
CSI::Delete => unimplemented!(),
CSI::End => unimplemented!(),
CSI::Invalid => unimplemented!(),
},
Action::InvalidUtf8 => unreachable!(),
Action::ControlCharacter(ctrl) => {
Expand Down

0 comments on commit 3bfe51d

Please sign in to comment.