# Regex compiler memory corruption

Compilation or encoding writing past buffers sized from a different length than emitted

_Area: Memory corruption and native code. Seen in 2 disclosed reports; latest 2023-03-21. Updated 2026-11-02._

## How it works
A compiler or encoder computes a buffer size from one length, then emits or copies a different number of bytes. The assumption that "the length I measured equals the length I write" breaks. In regex compilation, a crafted source string drives the compiler down a path where the same memory is freed twice [E1](https://bugbountylibrary.com/r/h1%3A1549636.md). In ABI encoding, a pointer is advanced by an offset computed against the wrong layout, so a copy reads from unallocated memory [E2](https://bugbountylibrary.com/r/c4%3A2023-01-opensea%3AM-01.md). In a token parser, a scan loop terminates only on a delimiter, not on end-of-buffer, so it walks past the buffer and writes out of bounds [E3](https://bugbountylibrary.com/r/h1%3A1753224.md).

## Where it shows up
- Regex compilation of attacker-controlled source strings, especially malformed conditional/group constructs [E1](https://bugbountylibrary.com/r/h1%3A1549636.md)
- Assembly memory-pointer helpers using `.next()`/`.offset()` against ABI head/tail layout [E2](https://bugbountylibrary.com/r/c4%3A2023-01-opensea%3AM-01.md)
- Identity precompile (0x04) copies whose source region is computed, not fixed [E2](https://bugbountylibrary.com/r/c4%3A2023-01-opensea%3AM-01.md)
- Token-scan loops that terminate only on `ISSPACE` or similar delimiters, with no NUL/bounds check [E3](https://bugbountylibrary.com/r/h1%3A1753224.md)
- Parsers reading files that may end without a trailing newline or whitespace [E3](https://bugbountylibrary.com/r/h1%3A1753224.md)

## How to review
For each buffer, find where its size is computed and where bytes are written; confirm the two derive from the same length and that the write loop is bounded by that length, not by a delimiter. For pointer arithmetic, trace every `.next()`/`.offset()` against the actual head/tail layout and confirm the resulting region is allocated. For scan loops, require a NUL or end-of-buffer terminator in addition to the delimiter. The invariant: no write or read may occur outside the region whose size was computed for it.

## How finders spotted it
- Read the encoder alongside the 0x04 precompile and Solidity compiler docs, then traced each pointer step against the ABI layout to see the copy would read unallocated memory [E2](https://bugbountylibrary.com/r/c4%3A2023-01-opensea%3AM-01.md)
- Read `parsenetrc()` and noticed the token loop only stops on `ISSPACE`; reasoned a file ending in non-space chars without newline runs past the buffer, then confirmed with a 4095-byte 'a' file [E3](https://bugbountylibrary.com/r/h1%3A1753224.md)

## Variants seen
- Double free during regexp compilation from a crafted source string [E1](https://bugbountylibrary.com/r/h1%3A1549636.md)
- Pointer advanced past an array, copying unallocated memory into order payloads [E2](https://bugbountylibrary.com/r/c4%3A2023-01-opensea%3AM-01.md)
- OOB read plus 1-byte zero write in a token parser at EOF without newline [E3](https://bugbountylibrary.com/r/h1%3A1753224.md)

## Impact and severity
E1 is a double free potentially enabling RCE when chained with `marshal.load` (chaining hypothetical) [E1](https://bugbountylibrary.com/r/h1%3A1549636.md). E2 corrupts order hashes in validation payloads [E2](https://bugbountylibrary.com/r/c4%3A2023-01-opensea%3AM-01.md). E3 crashes curl via OOB read and zero write [E3](https://bugbountylibrary.com/r/h1%3A1753224.md). Severity rises with reachability of attacker-controlled input and with a chain that converts corruption into control flow [E1](https://bugbountylibrary.com/r/h1%3A1549636.md).

## Evidence
- E1: https://bugbountylibrary.com/r/h1%3A1549636.md
- E2: https://bugbountylibrary.com/r/c4%3A2023-01-opensea%3AM-01.md
- E3: https://bugbountylibrary.com/r/h1%3A1753224.md
