rectorphp/rector · error · InvalidEregException

a literal null byte in the regex

Error message

a literal null byte in the regex

What it means

_ere2pcre_escape() refuses to emit a literal NUL byte: when a pattern character is "\x00", EregToPcreTransformer throws InvalidEregException('a literal null byte in the regex') (EregToPcreTransformer.php:241). A raw null byte cannot appear safely in a PCRE pattern string, so the ereg-to-preg conversion is aborted instead of producing a broken pattern.

Source

Thrown at rules/Php70/EregToPcreTransformer.php:241

                    }
                    if (ord($a) > ord($b)) {
                        $errorMessage = sprintf('an invalid character range %d-%d"', (int) $a, (int) $b);
                        throw new InvalidEregException($errorMessage);
                    }
                    $cls .= $this->_ere2pcre_escape($a) . '-' . $this->_ere2pcre_escape($b);
                    ++$i;
                } else {
                    $cls .= $this->_ere2pcre_escape($a);
                }
            }
            $start = \false;
        } while ($i < $l && $s[$i] !== ']');
        return [$cls, $i];
    }
    private function _ere2pcre_escape(string $content): string
    {
        if ($content === "\x00") {
            throw new InvalidEregException('a literal null byte in the regex');
        }
        if (strpos('\^$.[]|()?*+{}-/', $content) !== \false) {
            return '\\' . $content;
        }
        return $content;
    }
    /**
     * @param array<int, mixed> $r
     */
    private function processCurlyBracket(string $s, int $i, array &$r, int $rr): int
    {
        $ii = strpos($s, '}', $i);
        if ($ii === \false) {
            throw new InvalidEregException('"{" does not have a matching "}"');
        }
        $start = $i + 1;
        $length = $ii - ($i + 1);
        $bound = Strings::substring($s, $start, $length);

View on GitHub (pinned to 408fcb0ff1)

Solutions

  1. Remove the raw NUL byte from the literal in the file Rector reported.
  2. If matching a NUL separator is intentional, rewrite that call by hand to str_replace/explode with chr(0) or a preg pattern using an escaped sequence, instead of relying on rector's ereg conversion.
  3. Re-run rector; preflight-scan ereg/split literals for "\x00" (grep -P '"\x00"|\x00') before bulk migrations.

Example fix

// before - literal NUL byte inside the pattern (shown as \x00)
ereg("a\x00b", $subject);

// after - handle binary separator explicitly, no raw NUL in the regex
explode("\x00", $subject); // or preg_match('/a\x00b/', $subject) written by hand
Defensive patterns

Strategy: validation

Validate before calling

if (strpos($pattern, "\x00") !== false) {
    throw new InvalidArgumentException('pattern contains a literal null byte; rewrite the call without ereg');
}

Try / catch

try {
    $pcre = $eregToPcreTransformer->transform($pattern, $ignoreCase);
} catch (InvalidEregException $e) {
    // raw NUL in the pattern — remove it or handle binary splitting outside regex
    continue;
}

Prevention

When it happens

Trigger: Rector (Php70 set / EregToPregMatchRector, target PHP >= 7.0) encounters an ereg-family call whose string-literal pattern contains an actual "\x00" byte — e.g. source written as "a\x00b" (double-quoted, real NUL), or a binary/legacy file where a NUL ended up inside the literal. Applies both in normal atoms and inside character classes, since _ere2pcre_escape() is used for both.

Common situations: Code migrated from binary-processing scripts (fixed-width records separated by NUL) where ereg/split was fed "\x00"-separated patterns; literals corrupted by an encoding conversion or editor that inserted NULs; copy-paste of binary data into pattern strings.

Related errors


AI-assisted analysis of rectorphp/rector@408fcb0ff1 (2026-08-21). Data as JSON: /api/errors/d1cf16ffefd1bb5c. Report an issue: GitHub.