Impact
A malformed RLP transaction inside a v7 DA blob causes Codec.DecodeBlob to panic rather than return an error. Reproduced locally with github.com/scroll-tech/da-codec v0.10.1 at 54929786434f00efd00431517a332f1ec8ca58d4. The affected expression also exists in the dependency revision used by the checked Scroll node source. This report establishes decoder behavior, not an unprivileged route to put arbitrary transaction bytes into an accepted L1 batch.
Describe the bug
In encoding/da.go, getNextTx reads an RLP long-form payload length as uint64, then narrows it to int for both a bounds check and a slice. On a 64-bit host, a declared length greater than math.MaxInt becomes negative; the converted value can pass the check and then cause a negative slice bound panic.
Steps to reproduce
- Construct a v7 blob with one block and one L2 transaction entry. Use
ff8000000000000000 as the nine transaction bytes: ff declares an eight-byte RLP length, and the following bytes declare 2^63 bytes of payload although none are present. Pack the v7 envelope as canonical blob field elements, as required by Codec.DecodeBlob. The nine bytes alone are an inner transaction entry, not a complete blob.
- Pass the blob to the public
Codec.DecodeBlob API.
- Observe a slice bounds panic. A blob with a valid transaction decodes through the same API.
The narrowing and slice are in getNextTx. The node's DA sync code calls DecodeBlob after checking the blob hash; the effect on a deployment depends on its DA sync configuration and accepted batch source.
Actual result
panic: runtime error: slice bounds out of range [:-9223372036854775799] in the local public-API harness.
Expected result
Compare the uint64 length with the remaining input before converting it to int, and return an error if it exceeds the available bytes.
Impact
A malformed RLP transaction inside a v7 DA blob causes
Codec.DecodeBlobto panic rather than return an error. Reproduced locally withgithub.com/scroll-tech/da-codec v0.10.1at54929786434f00efd00431517a332f1ec8ca58d4. The affected expression also exists in the dependency revision used by the checked Scroll node source. This report establishes decoder behavior, not an unprivileged route to put arbitrary transaction bytes into an accepted L1 batch.Describe the bug
In
encoding/da.go,getNextTxreads an RLP long-form payload length asuint64, then narrows it tointfor both a bounds check and a slice. On a 64-bit host, a declared length greater thanmath.MaxIntbecomes negative; the converted value can pass the check and then cause a negative slice bound panic.Steps to reproduce
ff8000000000000000as the nine transaction bytes:ffdeclares an eight-byte RLP length, and the following bytes declare2^63bytes of payload although none are present. Pack the v7 envelope as canonical blob field elements, as required byCodec.DecodeBlob. The nine bytes alone are an inner transaction entry, not a complete blob.Codec.DecodeBlobAPI.The narrowing and slice are in getNextTx. The node's DA sync code calls
DecodeBlobafter checking the blob hash; the effect on a deployment depends on its DA sync configuration and accepted batch source.Actual result
panic: runtime error: slice bounds out of range [:-9223372036854775799]in the local public-API harness.Expected result
Compare the
uint64length with the remaining input before converting it toint, and return an error if it exceeds the available bytes.