Skip to content
This repository was archived by the owner on Nov 6, 2020. It is now read-only.

Handle socket address parsing errors #8545

Merged
merged 7 commits into from
May 9, 2018
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions util/network-devp2p/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ error-chain = { version = "0.11", default-features = false }

[dev-dependencies]
tempdir = "0.3"
assert_matches = "1.2"

[features]
default = []
2 changes: 2 additions & 0 deletions util/network-devp2p/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ extern crate serde_derive;

#[cfg(test)]
extern crate tempdir;
#[cfg(test)] #[macro_use]
extern crate assert_matches;

mod host;
mod connection;
Expand Down
55 changes: 45 additions & 10 deletions util/network-devp2p/src/node_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,19 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

use discovery::{TableUpdates, NodeEntry};
use ethereum_types::H512;
use ip_utils::*;
use network::{Error, ErrorKind, AllowIP, IpFilter};
use rlp::{Rlp, RlpStream, DecoderError};
use serde_json;
use std::collections::{HashMap, HashSet};
use std::fmt::{self, Display, Formatter};
use std::hash::{Hash, Hasher};
use std::net::{SocketAddr, ToSocketAddrs, SocketAddrV4, SocketAddrV6, Ipv4Addr, Ipv6Addr};
use std::path::PathBuf;
use std::str::FromStr;
use std::{fs, mem, slice};
use ethereum_types::H512;
use rlp::{Rlp, RlpStream, DecoderError};
use network::{Error, ErrorKind, AllowIP, IpFilter};
use discovery::{TableUpdates, NodeEntry};
use ip_utils::*;
use serde_json;

/// Node public key
pub type NodeId = H512;
Expand Down Expand Up @@ -122,18 +122,19 @@ impl FromStr for NodeEndpoint {
address: a,
udp_port: a.port()
}),
Ok(_) => Err(ErrorKind::AddressResolve(None).into()),
Err(e) => Err(ErrorKind::AddressResolve(Some(e)).into())
Ok(None) => bail!(ErrorKind::AddressResolve(None)),
Err(_) => Err(ErrorKind::AddressParse.into()) // always an io::Error of InvalidInput kind
}
}
}

#[derive(PartialEq, Eq, Copy, Clone)]
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum PeerType {
_Required,
Optional
}

#[derive(Debug)]
pub struct Node {
pub id: NodeId,
pub endpoint: NodeEndpoint,
Expand Down Expand Up @@ -442,11 +443,34 @@ mod tests {
assert!(endpoint.is_ok());
let v4 = match endpoint.unwrap().address {
SocketAddr::V4(v4address) => v4address,
_ => panic!("should ve v4 address")
_ => panic!("should be v4 address")
};
assert_eq!(SocketAddrV4::new(Ipv4Addr::new(123, 99, 55, 44), 7770), v4);
}

#[test]
fn endpoint_parse_empty_ip_string_returns_error() {
let endpoint = NodeEndpoint::from_str("");
assert!(endpoint.is_err());
assert_matches!(endpoint.unwrap_err().kind(), &ErrorKind::AddressParse);
}

#[test]
fn endpoint_parse_invalid_ip_string_returns_error() {
let endpoint = NodeEndpoint::from_str("beef");
assert!(endpoint.is_err());
assert_matches!(endpoint.unwrap_err().kind(), &ErrorKind::AddressParse);
}

#[test]
fn endpoint_parse_valid_ip_without_port_returns_error() {
let endpoint = NodeEndpoint::from_str("123.123.123.123");
assert!(endpoint.is_err());
assert_matches!(endpoint.unwrap_err().kind(), &ErrorKind::AddressParse);
let endpoint = NodeEndpoint::from_str("123.123.123.123:123");
assert!(endpoint.is_ok())
}

#[test]
fn node_parse() {
assert!(validate_node_url("enode://a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@22.99.55.44:7770").is_none());
Expand All @@ -463,6 +487,17 @@ mod tests {
node.id);
}

#[test]
fn node_parse_fails_for_invalid_urls() {
let node = Node::from_str("foo");
assert!(node.is_err());
assert_matches!(node.unwrap_err().kind(), &ErrorKind::AddressParse);

let node = Node::from_str("enode://foo@bar");
assert!(node.is_err());
assert_matches!(node.unwrap_err().kind(), &ErrorKind::AddressParse);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe assert_matches is no longer required :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

meh, sadly it seems like that's still up in the air: rust-lang-deprecated/error-chain#95

assert_matches is used elsewhere, so at least it's not a new-new dependency. :/

}

#[test]
fn table_failure_percentage_order() {
let node1 = Node::from_str("enode://a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@22.99.55.44:7770").unwrap();
Expand Down
11 changes: 10 additions & 1 deletion util/network/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,16 @@ error_chain! {
foreign_links {
SocketIo(IoError) #[doc = "Socket IO error."];
Io(io::Error) #[doc = "Error concerning the Rust standard library's IO subsystem."];
AddressParse(net::AddrParseError) #[doc = "Error concerning the network address parsing subsystem."];
Decompression(snappy::InvalidInput) #[doc = "Decompression error."];
}

errors {
#[doc = "Error concerning the network address parsing subsystem."]
AddressParse {
description("Failed to parse network address"),
display("Failed to parse network address"),
}

#[doc = "Error concerning the network address resolution subsystem."]
AddressResolve(err: Option<io::Error>) {
description("Failed to resolve network address"),
Expand Down Expand Up @@ -163,6 +168,10 @@ impl From<crypto::error::SymmError> for Error {
}
}

impl From<net::AddrParseError> for Error {
fn from(_err: net::AddrParseError) -> Self { ErrorKind::AddressParse.into() }
}

#[test]
fn test_errors() {
assert_eq!(DisconnectReason::ClientQuit, DisconnectReason::from_u8(8));
Expand Down