Skip to content

Commit

Permalink
Merge pull request #309 from elichai/2019-08-amount-precision
Browse files Browse the repository at this point in the history
Check that the amount precision isn't more than the size of the amount
  • Loading branch information
apoelstra committed Aug 12, 2019
2 parents fb27216 + a9e65f3 commit cc0f114
Showing 1 changed file with 18 additions and 4 deletions.
22 changes: 18 additions & 4 deletions src/util/amount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,11 @@ impl error::Error for ParseAmountError {
}
}


fn is_too_precise(s: &str, precision: usize) -> bool {
s.contains(".") || precision >= s.len() || s.chars().rev().take(precision).any(|d| d != '0')
}

/// Parse decimal string in the given denomination into a satoshi value and a
/// bool indicator for a negative amount.
fn parse_signed_to_satoshi(
Expand All @@ -142,8 +147,8 @@ fn parse_signed_to_satoshi(
return Err(ParseAmountError::InputTooLarge);
}

let negative = s.chars().next().unwrap() == '-';
if negative {
let is_negative = s.chars().next().unwrap() == '-';
if is_negative {
if s.len() == 1 {
return Err(ParseAmountError::InvalidFormat);
}
Expand All @@ -160,7 +165,7 @@ fn parse_signed_to_satoshi(
// there are no decimals and the last digits are zeroes as
// many as the difference in precision.
let last_n = precision_diff.abs() as usize;
if s.contains(".") || s.chars().rev().take(last_n).any(|d| d != '0') {
if is_too_precise(s, last_n) {
return Err(ParseAmountError::TooPrecise);
}
s = &s[0..s.len() - last_n];
Expand Down Expand Up @@ -208,7 +213,7 @@ fn parse_signed_to_satoshi(
};
}

Ok((negative, value))
Ok((is_negative, value))
}

/// Format the given satoshi amount in the given denomination.
Expand Down Expand Up @@ -1208,6 +1213,15 @@ mod tests {
assert_eq!(sp("-200000000000 BTC"), Err(E::TooBig));
assert_eq!(p("18446744073709551616 sat"), Err(E::TooBig));

assert_eq!(sp("0 msat"), Err(E::TooPrecise));
assert_eq!(sp("-0 msat"), Err(E::TooPrecise));
assert_eq!(sp("000 msat"), Err(E::TooPrecise));
assert_eq!(sp("-000 msat"), Err(E::TooPrecise));
assert_eq!(p("0 msat"), Err(E::TooPrecise));
assert_eq!(p("-0 msat"), Err(E::TooPrecise));
assert_eq!(p("000 msat"), Err(E::TooPrecise));
assert_eq!(p("-000 msat"), Err(E::TooPrecise));

assert_eq!(p(".5 bits"), Ok(Amount::from_sat(50)));
assert_eq!(sp("-.5 bits"), Ok(SignedAmount::from_sat(-50)));
assert_eq!(p("0.00253583 BTC"), Ok(Amount::from_sat(253583)));
Expand Down

0 comments on commit cc0f114

Please sign in to comment.