stacks-core icon indicating copy to clipboard operation
stacks-core copied to clipboard

`ContractName::try_from()` allows invalid `ContractName` to be created

Open jbencin opened this issue 1 year ago • 0 comments

Description

The ContractName struct is implemented using a macro, like this:

guarded_string!(
    ContractName,
    "ContractName",
    CONTRACT_NAME_REGEX,
    MAX_STRING_LEN,
    RuntimeErrorType,
    RuntimeErrorType::BadNameValue
);

MAX_STRING_LEN is 128, so it's possible to construct a ContractName with up to 128 characters. However, when we implement StacksMessageCodec for ContractName:

    fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
        if self.as_bytes().len() < CONTRACT_MIN_NAME_LENGTH as usize
            || self.as_bytes().len() > CONTRACT_MAX_NAME_LENGTH as usize
        {
            // Error!
        }
        // ...
    }

CONTRACT_MAX_NAME_LENGTH is 40, much smaller than MAX_STRING_LEN. This means that ContractName::try_from() allows us to create structs that can't be serialized

Proposed solutions

  • Change the macro to use CONTRACT_MAX_NAME_LENGTH instead of MAX_STRING_LEN. This won't actually fix the problem, and will likely expose more invalid ContractNames that were never being serialized, but it will make invalid ContractNames easy to find and fix. Where it fails, we can replace ContractName::try_from() with ContractName::from_truncated() or ContractName::try_from_truncated()
  • Change CONTRACT_MAX_NAME_LENGTH to match MAX_STRING_LEN. Probably not what we want to do, but would fix the issue immediately

Related issues

  • #4396

jbencin avatar Apr 29 '24 15:04 jbencin