Skip to content

Commit c41ba4d

Browse files
committed
Fix amount overflow in Offer parsing and building
An overflow can occur when multiplying the offer amount by the requested quantity when checking if the given amount is enough. Return an error instead of overflowing.
1 parent 2c566c6 commit c41ba4d

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

lightning/src/offers/invoice_request.rs

+29
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,18 @@ mod tests {
828828
Ok(_) => panic!("expected error"),
829829
Err(e) => assert_eq!(e, SemanticError::MissingAmount),
830830
}
831+
832+
match OfferBuilder::new("foo".into(), recipient_pubkey())
833+
.amount_msats(1000)
834+
.supported_quantity(Quantity::Unbounded)
835+
.build().unwrap()
836+
.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
837+
.quantity(u64::max_value()).unwrap()
838+
.build()
839+
{
840+
Ok(_) => panic!("expected error"),
841+
Err(e) => assert_eq!(e, SemanticError::InvalidAmount),
842+
}
831843
}
832844

833845
#[test]
@@ -1123,6 +1135,23 @@ mod tests {
11231135
assert_eq!(e, ParseError::InvalidSemantics(SemanticError::UnsupportedCurrency));
11241136
},
11251137
}
1138+
1139+
let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
1140+
.amount_msats(1000)
1141+
.supported_quantity(Quantity::Unbounded)
1142+
.build().unwrap()
1143+
.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
1144+
.quantity(u64::max_value()).unwrap()
1145+
.build_unchecked()
1146+
.sign(payer_sign).unwrap();
1147+
1148+
let mut buffer = Vec::new();
1149+
invoice_request.write(&mut buffer).unwrap();
1150+
1151+
match InvoiceRequest::try_from(buffer) {
1152+
Ok(_) => panic!("expected error"),
1153+
Err(e) => assert_eq!(e, ParseError::InvalidSemantics(SemanticError::InvalidAmount)),
1154+
}
11261155
}
11271156

11281157
#[test]

lightning/src/offers/offer.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,8 @@ impl OfferContents {
431431
};
432432

433433
if !self.expects_quantity() || quantity.is_some() {
434-
let expected_amount_msats = offer_amount_msats * quantity.unwrap_or(1);
434+
let expected_amount_msats = offer_amount_msats.checked_mul(quantity.unwrap_or(1))
435+
.ok_or(SemanticError::InvalidAmount)?;
435436
let amount_msats = amount_msats.unwrap_or(expected_amount_msats);
436437

437438
if amount_msats < expected_amount_msats {

0 commit comments

Comments
 (0)