Skip to content

Commit c3172b4

Browse files
committed
Improve Miniscript robustness
1 parent b4e33e5 commit c3172b4

File tree

4 files changed

+41
-2
lines changed

4 files changed

+41
-2
lines changed

src/expression.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ use std::str::FromStr;
2020
use errstr;
2121
use Error;
2222

23+
use MAX_RECURSION_DEPTH;
24+
2325
#[derive(Debug)]
2426
/// A token of the form `x(...)` or `x`
2527
pub struct Tree<'a> {
@@ -34,7 +36,16 @@ pub trait FromTree: Sized {
3436
}
3537

3638
impl<'a> Tree<'a> {
37-
fn from_slice(mut sl: &'a str) -> Result<(Tree<'a>, &'a str), Error> {
39+
40+
fn from_slice(sl: &'a str) -> Result<(Tree<'a>, &'a str), Error>{
41+
Self::from_slice_helper(sl, 0u32)
42+
}
43+
44+
fn from_slice_helper(mut sl: &'a str, depth: u32) -> Result<(Tree<'a>, &'a str), Error> {
45+
46+
if depth >= MAX_RECURSION_DEPTH{
47+
return Err(Error::MaxRecursiveDepthExceeded);
48+
}
3849
enum Found {
3950
Nothing,
4051
Lparen(usize),
@@ -87,7 +98,7 @@ impl<'a> Tree<'a> {
8798

8899
sl = &sl[n + 1..];
89100
loop {
90-
let (arg, new_sl) = Tree::from_slice(sl)?;
101+
let (arg, new_sl) = Tree::from_slice_helper(sl, depth + 1)?;
91102
ret.args.push(arg);
92103

93104
if new_sl.is_empty() {

src/lib.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,10 @@ pub enum Error {
331331
///Incorrect Script pubkey Hash for the descriptor. This is used for both
332332
/// `Sh` and `Wsh` descriptors
333333
IncorrectScriptHash,
334+
/// Recursion depth exceeded when parsing policy/miniscript from string
335+
MaxRecursiveDepthExceeded,
336+
/// Recursion depth exceeded when parsing policy/miniscript from string
337+
ScriptSizeTooLarge,
334338
}
335339

336340
#[doc(hidden)]
@@ -361,6 +365,11 @@ impl error::Error for Error {
361365
}
362366
}
363367

368+
// https://github.com/sipa/miniscript/pull/5 for discussion on this number
369+
const MAX_RECURSION_DEPTH: u32 = 402;
370+
// https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki
371+
const MAX_SCRIPT_SIZE: u32 = 10000;
372+
364373
impl fmt::Display for Error {
365374
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
366375
match *self {
@@ -413,6 +422,12 @@ impl fmt::Display for Error {
413422
Error::IncorrectPubkeyHash => {
414423
f.write_str("Incorrect pubkey hash for given descriptor pkh/wpkh")
415424
}
425+
Error::MaxRecursiveDepthExceeded => {
426+
write!(f, "Recusive depth over {} not permitted", MAX_RECURSION_DEPTH)
427+
}
428+
Error::ScriptSizeTooLarge => {
429+
write!(f, "Standardness rules imply bitcoin than {} bytes", MAX_SCRIPT_SIZE)
430+
}
416431
}
417432
}
418433
}

src/miniscript/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@ impl<Pk: MiniscriptKey> Miniscript<Pk> {
128128
impl Miniscript<bitcoin::PublicKey> {
129129
/// Attempt to parse a script into a Miniscript representation
130130
pub fn parse(script: &script::Script) -> Result<Miniscript<bitcoin::PublicKey>, Error> {
131+
132+
// Transactions more than 100Kb are non-standard
133+
if script.len() > 10000 {
134+
135+
}
131136
let tokens = lex(script)?;
132137
let mut iter = TokenIter::new(tokens);
133138

0 commit comments

Comments
 (0)