sigp / enr

Ethereum Node Record
MIT License
61 stars 29 forks source link

Check rlp size when creating a record from string #30

Closed weipin closed 1 year ago

weipin commented 1 year ago

Problem

When creating a record (struct ENR) from its textual form ("enr:xxx"), it seems MAX_ENR_SIZE isn't checked.

To look at the issue from a different perspective, the code snippet below shows that the behavior when "reading from text" is inconsistent with the internal ones, such as when "updating a content field".

use enr::k256::ecdsa::SigningKey;
use enr::{k256, Enr};
use hex_literal::hex;

type DefaultEnr = Enr<k256::ecdsa::SigningKey>;

fn main() {
    // The `key` is irrelevant here, for the resulting signature size is the same.
    let key = SigningKey::from_slice(&hex!("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")).unwrap();

    // Address of a record with 301-byte rlp-encoded content.
    let text = "enr:-QEquEBxABglcZbIGKJ8RHDCp2Ft59tdf61RhV3XXf2BKTlKE2XwzNfihH-46hKkANsXaGRwH8Dp7a3lTrKiv2FMMaFYAYJpZIJ2NIJpcIR_AAABiXNlY3AyNTZrMaEDymNMrg1JrLQB2KTGtv6MVbcNEVv0AHacwUAPMljNMTiDdWRwgnZferijeHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA";
    // Creating a record from the address succeeds (which probably should not).
    let mut record = text.parse::<DefaultEnr>().unwrap();
    // Updating the content field `udp` with the same value results an error.
    let err = record.set_udp4(record.udp4().unwrap(), &key).unwrap_err();
    assert_eq!(format!("{err}"), "enr exceeds max size");
}

Solution

When creating a record from text, check the size of the rlp-encoded content. The check is made right before rlp::decode(..), which seems to be the last place the rlp data is represented as bytes. The change should cover the serde feature, but no related tests are included.