From f6fd170c403325df22402966a280c2ad5fe90875 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Sun, 22 Jul 2018 11:24:30 -0700 Subject: [PATCH] Enforce limit on header range length in light client logs request. --- rpc/src/v1/helpers/errors.rs | 8 ++++++++ rpc/src/v1/helpers/light_fetch.rs | 13 +++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/rpc/src/v1/helpers/errors.rs b/rpc/src/v1/helpers/errors.rs index 710f7d7497a..32caff77e0a 100644 --- a/rpc/src/v1/helpers/errors.rs +++ b/rpc/src/v1/helpers/errors.rs @@ -100,6 +100,14 @@ pub fn request_rejected_limit() -> Error { } } +pub fn request_rejected_param_limit() -> Error { + Error { + code: ErrorCode::ServerError(codes::REQUEST_REJECTED_LIMIT), + message: "Request has been rejected because requested data size exceeds limit.".into(), + data: None, + } +} + pub fn account(error: &str, details: T) -> Error { Error { code: ErrorCode::ServerError(codes::ACCOUNT_ERROR), diff --git a/rpc/src/v1/helpers/light_fetch.rs b/rpc/src/v1/helpers/light_fetch.rs index 56370f23256..0cb5f80d901 100644 --- a/rpc/src/v1/helpers/light_fetch.rs +++ b/rpc/src/v1/helpers/light_fetch.rs @@ -314,8 +314,10 @@ impl LightFetch { use std::collections::BTreeMap; use jsonrpc_core::futures::stream::{self, Stream}; + const MAX_BLOCK_RANGE: u64 = 1000; + let fetcher: Self = self.clone(); - self.headers_range_by_block_id(filter.from_block, filter.to_block) + self.headers_range_by_block_id(filter.from_block, filter.to_block, MAX_BLOCK_RANGE) .and_then(move |mut headers| { if headers.is_empty() { return Either::A(future::ok(Vec::new())); @@ -434,7 +436,12 @@ impl LightFetch { } } - fn headers_range_by_block_id(&self, from_block: BlockId, to_block: BlockId) -> impl Future, Error = Error> { + fn headers_range_by_block_id( + &self, + from_block: BlockId, + to_block: BlockId, + max: u64 + ) -> impl Future, Error = Error> { let fetch_hashes = [from_block, to_block].iter() .filter_map(|block_id| match block_id { BlockId::Hash(hash) => Some(hash.clone()), @@ -461,6 +468,8 @@ impl LightFetch { if to_block_num < from_block_num { // early exit for "to" block before "from" block. return Either::A(future::ok(Vec::new())); + } else if to_block_num - from_block_num >= max { + return Either::A(future::err(errors::request_rejected_param_limit())); } let to_header_hint = match to_block {