From 0a30d271b80c0bd1372ed41fcee7c6724fda8b63 Mon Sep 17 00:00:00 2001 From: Delweng Date: Tue, 24 Feb 2026 16:08:24 +0800 Subject: [PATCH] fix: validate request ID length in Message::decode() Message::decode() was constructing RequestId directly from decoded bytes without validating the length. The discv5 spec limits request IDs to a maximum of 8 bytes, and RequestId::decode() already enforces this, but it was not being called during message decoding. This caused the node to accept and echo back oversized request IDs (e.g. 9 bytes) in PONG responses, which violates the spec. The node should silently drop messages with invalid request IDs. Fixes the hive devp2p PingLargeRequestID conformance test. Signed-off-by: Delweng --- src/rpc.rs | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/rpc.rs b/src/rpc.rs index d745ee00..e32445ba 100644 --- a/src/rpc.rs +++ b/src/rpc.rs @@ -357,7 +357,7 @@ impl Message { } let id_bytes = Bytes::decode(payload)?; - let id = RequestId(id_bytes.to_vec()); + let id = RequestId::decode(id_bytes.to_vec())?; let message = match msg_type { 1 => { @@ -859,6 +859,29 @@ mod tests { assert_eq!(Message::decode(&encoded_message).unwrap(), message); } + #[test] + fn reject_oversized_request_id() { + // A PING request with a 9-byte request ID should be rejected. + // The discv5 spec limits request IDs to a maximum of 8 bytes. + let id = RequestId(vec![1, 2, 3, 4, 5, 6, 7, 8, 9]); // 9 bytes + let request = Request { + id, + body: RequestBody::Ping { enr_seq: 1 }, + }; + let encoded = request.encode(); + Message::decode(&encoded).expect_err("should reject request ID longer than 8 bytes"); + + // An 8-byte request ID should be accepted. + let id = RequestId(vec![1, 2, 3, 4, 5, 6, 7, 8]); + let request = Message::Request(Request { + id, + body: RequestBody::Ping { enr_seq: 1 }, + }); + let encoded = request.clone().encode(); + let decoded = Message::decode(&encoded).expect("8-byte request ID should be valid"); + assert_eq!(request, decoded); + } + #[test] fn test_large_enr_hex_data() { // This is the exact hex data from the logs that was failing to decode