From 9af53aeecb38656eb47fe08199c5d0571f8beff3 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Tue, 21 Mar 2023 20:35:48 +0100 Subject: [PATCH] fix(rpc): treat number without 0x prefix as errors (#1895) --- crates/primitives/src/block.rs | 38 +++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/crates/primitives/src/block.rs b/crates/primitives/src/block.rs index d5b7a77bda..500e8b5748 100644 --- a/crates/primitives/src/block.rs +++ b/crates/primitives/src/block.rs @@ -6,7 +6,7 @@ use serde::{ ser::SerializeStruct, Deserialize, Deserializer, Serialize, Serializer, }; -use std::{fmt, fmt::Formatter, ops::Deref, str::FromStr}; +use std::{fmt, fmt::Formatter, num::ParseIntError, ops::Deref, str::FromStr}; /// Ethereum full block. /// @@ -500,7 +500,7 @@ impl<'de> Deserialize<'de> for BlockNumberOrTag { } impl FromStr for BlockNumberOrTag { - type Err = String; + type Err = ParseBlockNumberError; fn from_str(s: &str) -> Result { let block = match s { @@ -510,14 +510,18 @@ impl FromStr for BlockNumberOrTag { "earliest" => Self::Earliest, "pending" => Self::Pending, _number => { - let hex_string = s.trim_start_matches("0x"); - let number = u64::from_str_radix(hex_string, 16).map_err(|err| err.to_string()); - BlockNumberOrTag::Number(number?) + if let Some(hex_val) = s.strip_prefix("0x") { + let number = u64::from_str_radix(hex_val, 16); + BlockNumberOrTag::Number(number?) + } else { + return Err(HexStringMissingPrefixError::default().into()) + } } }; Ok(block) } } + impl fmt::Display for BlockNumberOrTag { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { @@ -531,6 +535,23 @@ impl fmt::Display for BlockNumberOrTag { } } +/// Error variants when parsing a [BlockNumberOrTag] +#[derive(Debug, thiserror::Error)] +pub enum ParseBlockNumberError { + /// Failed to parse hex value + #[error(transparent)] + ParseIntErr(#[from] ParseIntError), + /// Block numbers should be 0x-prefixed + #[error(transparent)] + MissingPrefix(#[from] HexStringMissingPrefixError), +} + +/// Thrown when a 0x-prefixed hex string was expected +#[derive(Debug, Default, thiserror::Error)] +#[non_exhaustive] +#[error("hex string without 0x prefix")] +pub struct HexStringMissingPrefixError; + /// A block hash which may have /// a boolean requireCanonical field. /// If false, an RPC call should raise if a block @@ -725,4 +746,11 @@ mod test { ); assert_eq!(parsed, expected); } + + #[test] + fn serde_blocknumber_non_0xprefix() { + let s = "\"2\""; + let err = serde_json::from_str::(s).unwrap_err(); + assert_eq!(err.to_string(), HexStringMissingPrefixError::default().to_string()); + } }