Skip to content

Commit 407a3e1

Browse files
committed
Fix crash when slicing strings by slicing at non-char boundaries
1 parent 5540126 commit 407a3e1

File tree

1 file changed

+8
-13
lines changed

1 file changed

+8
-13
lines changed

src/lib.rs

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -524,13 +524,10 @@ fn parse_resolved_instructions(
524524
instructions: &str, network: Network, supports_proof_of_payment_callbacks: bool,
525525
hrn: Option<HumanReadableName>, hrn_proof: Option<Vec<u8>>,
526526
) -> Result<PaymentInstructions, ParseError> {
527-
const BTC_URI_PFX_LEN: usize = "bitcoin:".len();
528-
const LN_URI_PFX_LEN: usize = "lightning:".len();
527+
let (uri_proto, uri_suffix) = split_once(instructions, ':');
529528

530-
if instructions.len() >= BTC_URI_PFX_LEN
531-
&& instructions[..BTC_URI_PFX_LEN].eq_ignore_ascii_case("bitcoin:")
532-
{
533-
let (body, params) = split_once(&instructions[BTC_URI_PFX_LEN..], '?');
529+
if uri_proto.eq_ignore_ascii_case("bitcoin") {
530+
let (body, params) = split_once(uri_suffix.unwrap_or(""), '?');
534531
let mut methods = Vec::new();
535532
let mut description = None;
536533
let mut pop_callback = None;
@@ -546,7 +543,7 @@ fn parse_resolved_instructions(
546543

547544
let mut parse_segwit = |pfx| {
548545
if let Some(address_string) = v {
549-
if address_string.len() < 3
546+
if address_string.is_char_boundary(3)
550547
|| !address_string[..3].eq_ignore_ascii_case(pfx)
551548
{
552549
// `bc`/`tb` key-values must only include bech32/bech32m strings with
@@ -651,7 +648,7 @@ fn parse_resolved_instructions(
651648
let err = "Missing value for a Proof of Payment instruction in a BIP 321 bitcoin: URI";
652649
return Err(ParseError::InvalidInstructions(err));
653650
}
654-
} else if k.len() >= 4 && k[..4].eq_ignore_ascii_case("req-") {
651+
} else if k.is_char_boundary(4) && k[..4].eq_ignore_ascii_case("req-") {
655652
return Err(ParseError::UnknownRequiredParameter);
656653
}
657654
}
@@ -796,13 +793,11 @@ fn parse_resolved_instructions(
796793
}))
797794
}
798795
}
799-
} else if instructions.len() >= LN_URI_PFX_LEN
800-
&& instructions[..LN_URI_PFX_LEN].eq_ignore_ascii_case("lightning:")
801-
{
796+
} else if uri_proto.eq_ignore_ascii_case("lightning") {
802797
// Though there is no specification, lightning: URIs generally only include BOLT 11
803798
// invoices.
804-
let invoice = Bolt11Invoice::from_str(&instructions[LN_URI_PFX_LEN..])
805-
.map_err(ParseError::InvalidBolt11)?;
799+
let invoice =
800+
Bolt11Invoice::from_str(uri_suffix.unwrap_or("")).map_err(ParseError::InvalidBolt11)?;
806801
let ln_amt = invoice.amount_milli_satoshis().map(Amount::from_milli_sats);
807802
let (description, onchain_amt, method_iter) = instructions_from_bolt11(invoice, network)?;
808803
let inner = PaymentInstructionsImpl {

0 commit comments

Comments
 (0)