Skip to content

Commit c372854

Browse files
committed
Use consistent byte/char offsets when parsing invoice HRPs
When parsing lightning-invoice HRPs we want to read them char-by-char, tracking at which offset different fields were. Prior to this commit this was done first by reading char-by-char and then by indexing using the byte offset which works for ASCII strings but fails on multi-byte characters. This commit fixes this issue by simply always walking byte-by-byte and rejecting multi-byte characters which don't belong in HRPs.
1 parent 4c2d3d8 commit c372854

File tree

1 file changed

+7
-3
lines changed
  • lightning-invoice/src

1 file changed

+7
-3
lines changed

lightning-invoice/src/de.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,11 @@ mod hrp_sm {
4343
}
4444

4545
impl States {
46-
fn next_state(&self, read_symbol: char) -> Result<States, super::Bolt11ParseError> {
46+
fn next_state(&self, read_byte: u8) -> Result<States, super::Bolt11ParseError> {
47+
let read_symbol = match char::from_u32(read_byte.into()) {
48+
Some(symb) if symb.is_ascii() => symb,
49+
_ => return Err(super::Bolt11ParseError::MalformedHRP),
50+
};
4751
match *self {
4852
States::Start => {
4953
if read_symbol == 'l' {
@@ -119,7 +123,7 @@ mod hrp_sm {
119123
*range = Some(new_range);
120124
}
121125

122-
fn step(&mut self, c: char) -> Result<(), super::Bolt11ParseError> {
126+
fn step(&mut self, c: u8) -> Result<(), super::Bolt11ParseError> {
123127
let next_state = self.state.next_state(c)?;
124128
match next_state {
125129
States::ParseCurrencyPrefix => {
@@ -158,7 +162,7 @@ mod hrp_sm {
158162

159163
pub fn parse_hrp(input: &str) -> Result<(&str, &str, &str), super::Bolt11ParseError> {
160164
let mut sm = StateMachine::new();
161-
for c in input.chars() {
165+
for c in input.bytes() {
162166
sm.step(c)?;
163167
}
164168

0 commit comments

Comments
 (0)