Summary
pallas-addresses currently accepts non-canonical varuint encodings inside Pointer::parse, so two different byte sequences can parse to the same Pointer value.
That means the following converse property does not hold today:
- if
Pointer::parse(bytes) == Ok(p), then p.to_vec() == bytes
The forward roundtrip still holds:
Pointer::parse(p.to_vec()) == Ok(p)
Minimal repro
The varuint encoding [0x80, 0x00] is accepted as 0, even though the canonical encoding is [0x00].
So this parses successfully:
let bytes = [0x80, 0x00, 0x80, 0x00, 0x80, 0x00];
let parsed = Pointer::parse(&bytes).unwrap();
assert_eq!(parsed, Pointer::new(0, 0, 0));
assert_eq!(parsed.to_vec(), vec![0x00, 0x00, 0x00]);
assert_ne!(parsed.to_vec(), bytes);
Impact
Depending on how consumers use parsed values, this can affect:
- strict validation
- byte-level identity checks
- roundtrip assumptions
- normalization-sensitive caches or allowlists
Summary
pallas-addressescurrently accepts non-canonical varuint encodings insidePointer::parse, so two different byte sequences can parse to the samePointervalue.That means the following converse property does not hold today:
Pointer::parse(bytes) == Ok(p), thenp.to_vec() == bytesThe forward roundtrip still holds:
Pointer::parse(p.to_vec()) == Ok(p)Minimal repro
The varuint encoding
[0x80, 0x00]is accepted as0, even though the canonical encoding is[0x00].So this parses successfully:
Impact
Depending on how consumers use parsed values, this can affect: