Detect too large packets in snapshot sync. (#7977)
This commit is contained in:
parent
f8a2e53f3e
commit
d90ab40a78
@ -57,6 +57,8 @@ pub enum Error {
|
|||||||
VersionNotSupported(u64),
|
VersionNotSupported(u64),
|
||||||
/// Max chunk size is to small to fit basic account data.
|
/// Max chunk size is to small to fit basic account data.
|
||||||
ChunkTooSmall,
|
ChunkTooSmall,
|
||||||
|
/// Oversized chunk
|
||||||
|
ChunkTooLarge,
|
||||||
/// Snapshots not supported by the consensus engine.
|
/// Snapshots not supported by the consensus engine.
|
||||||
SnapshotsUnsupported,
|
SnapshotsUnsupported,
|
||||||
/// Bad epoch transition.
|
/// Bad epoch transition.
|
||||||
@ -85,6 +87,7 @@ impl fmt::Display for Error {
|
|||||||
Error::Trie(ref err) => err.fmt(f),
|
Error::Trie(ref err) => err.fmt(f),
|
||||||
Error::VersionNotSupported(ref ver) => write!(f, "Snapshot version {} is not supprted.", ver),
|
Error::VersionNotSupported(ref ver) => write!(f, "Snapshot version {} is not supprted.", ver),
|
||||||
Error::ChunkTooSmall => write!(f, "Chunk size is too small."),
|
Error::ChunkTooSmall => write!(f, "Chunk size is too small."),
|
||||||
|
Error::ChunkTooLarge => write!(f, "Chunk size is too large."),
|
||||||
Error::SnapshotsUnsupported => write!(f, "Snapshots unsupported by consensus engine."),
|
Error::SnapshotsUnsupported => write!(f, "Snapshots unsupported by consensus engine."),
|
||||||
Error::BadEpochProof(i) => write!(f, "Bad epoch proof for transition to epoch {}", i),
|
Error::BadEpochProof(i) => write!(f, "Bad epoch proof for transition to epoch {}", i),
|
||||||
Error::WrongChunkFormat(ref msg) => write!(f, "Wrong chunk format: {}", msg),
|
Error::WrongChunkFormat(ref msg) => write!(f, "Wrong chunk format: {}", msg),
|
||||||
|
@ -77,6 +77,11 @@ mod traits;
|
|||||||
// Try to have chunks be around 4MB (before compression)
|
// Try to have chunks be around 4MB (before compression)
|
||||||
const PREFERRED_CHUNK_SIZE: usize = 4 * 1024 * 1024;
|
const PREFERRED_CHUNK_SIZE: usize = 4 * 1024 * 1024;
|
||||||
|
|
||||||
|
// Maximal chunk size (decompressed)
|
||||||
|
// Snappy::decompressed_len estimation may sometimes yield results greater
|
||||||
|
// than PREFERRED_CHUNK_SIZE so allow some threshold here.
|
||||||
|
const MAX_CHUNK_SIZE: usize = PREFERRED_CHUNK_SIZE / 4 * 5;
|
||||||
|
|
||||||
// Minimum supported state chunk version.
|
// Minimum supported state chunk version.
|
||||||
const MIN_SUPPORTED_STATE_CHUNK_VERSION: u64 = 1;
|
const MIN_SUPPORTED_STATE_CHUNK_VERSION: u64 = 1;
|
||||||
// current state chunk version.
|
// current state chunk version.
|
||||||
|
@ -23,7 +23,7 @@ use std::path::PathBuf;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||||
|
|
||||||
use super::{ManifestData, StateRebuilder, Rebuilder, RestorationStatus, SnapshotService};
|
use super::{ManifestData, StateRebuilder, Rebuilder, RestorationStatus, SnapshotService, MAX_CHUNK_SIZE};
|
||||||
use super::io::{SnapshotReader, LooseReader, SnapshotWriter, LooseWriter};
|
use super::io::{SnapshotReader, LooseReader, SnapshotWriter, LooseWriter};
|
||||||
|
|
||||||
use blockchain::BlockChain;
|
use blockchain::BlockChain;
|
||||||
@ -130,6 +130,11 @@ impl Restoration {
|
|||||||
// feeds a state chunk, aborts early if `flag` becomes false.
|
// feeds a state chunk, aborts early if `flag` becomes false.
|
||||||
fn feed_state(&mut self, hash: H256, chunk: &[u8], flag: &AtomicBool) -> Result<(), Error> {
|
fn feed_state(&mut self, hash: H256, chunk: &[u8], flag: &AtomicBool) -> Result<(), Error> {
|
||||||
if self.state_chunks_left.contains(&hash) {
|
if self.state_chunks_left.contains(&hash) {
|
||||||
|
let expected_len = snappy::decompressed_len(chunk)?;
|
||||||
|
if expected_len > MAX_CHUNK_SIZE {
|
||||||
|
trace!(target: "snapshot", "Discarding large chunk: {} vs {}", expected_len, MAX_CHUNK_SIZE);
|
||||||
|
return Err(::snapshot::Error::ChunkTooLarge.into());
|
||||||
|
}
|
||||||
let len = snappy::decompress_into(chunk, &mut self.snappy_buffer)?;
|
let len = snappy::decompress_into(chunk, &mut self.snappy_buffer)?;
|
||||||
|
|
||||||
self.state.feed(&self.snappy_buffer[..len], flag)?;
|
self.state.feed(&self.snappy_buffer[..len], flag)?;
|
||||||
@ -147,6 +152,11 @@ impl Restoration {
|
|||||||
// feeds a block chunk
|
// feeds a block chunk
|
||||||
fn feed_blocks(&mut self, hash: H256, chunk: &[u8], engine: &EthEngine, flag: &AtomicBool) -> Result<(), Error> {
|
fn feed_blocks(&mut self, hash: H256, chunk: &[u8], engine: &EthEngine, flag: &AtomicBool) -> Result<(), Error> {
|
||||||
if self.block_chunks_left.contains(&hash) {
|
if self.block_chunks_left.contains(&hash) {
|
||||||
|
let expected_len = snappy::decompressed_len(chunk)?;
|
||||||
|
if expected_len > MAX_CHUNK_SIZE {
|
||||||
|
trace!(target: "snapshot", "Discarding large chunk: {} vs {}", expected_len, MAX_CHUNK_SIZE);
|
||||||
|
return Err(::snapshot::Error::ChunkTooLarge.into());
|
||||||
|
}
|
||||||
let len = snappy::decompress_into(chunk, &mut self.snappy_buffer)?;
|
let len = snappy::decompress_into(chunk, &mut self.snappy_buffer)?;
|
||||||
|
|
||||||
self.secondary.feed(&self.snappy_buffer[..len], engine, flag)?;
|
self.secondary.feed(&self.snappy_buffer[..len], engine, flag)?;
|
||||||
|
Loading…
Reference in New Issue
Block a user