{"record":{"id":"d4b97d62a7ac83a7","repo":"rectorphp/rector","slug":"an-invalid-character-range-d-d","errorCode":null,"errorMessage":"an invalid character range %d-%d\"","messagePattern":"an invalid character range (.+?)-(.+?)\"","errorType":"validation","errorClass":"InvalidEregException","httpStatus":null,"severity":"error","filePath":"rules/Php70/EregToPcreTransformer.php","lineNumber":226,"sourceCode":"        do {\n            if ($s[$i] === '[' && $i + 1 < $l && strpos('.=:', $s[$i + 1]) !== \\false) {\n                /** @var string $cls */\n                [$cls, $i] = $this->processCharacterClass($s, $i, $cls);\n            } else {\n                $a = $s[$i];\n                ++$i;\n                if ($a === '-' && !$start && ($i >= $l || $s[$i] !== ']')) {\n                    throw new InvalidEregException('\"-\" is invalid for the start character in the brackets');\n                }\n                if ($i < $l && $s[$i] === '-') {\n                    $b = $s[++$i];\n                    if ($b === ']') {\n                        $cls .= $this->_ere2pcre_escape($a) . '\\-';\n                        break;\n                    }\n                    if (ord($a) > ord($b)) {\n                        $errorMessage = sprintf('an invalid character range %d-%d\"', (int) $a, (int) $b);\n                        throw new InvalidEregException($errorMessage);\n                    }\n                    $cls .= $this->_ere2pcre_escape($a) . '-' . $this->_ere2pcre_escape($b);\n                    ++$i;\n                } else {\n                    $cls .= $this->_ere2pcre_escape($a);\n                }\n            }\n            $start = \\false;\n        } while ($i < $l && $s[$i] !== ']');\n        return [$cls, $i];\n    }\n    private function _ere2pcre_escape(string $content): string\n    {\n        if ($content === \"\\x00\") {\n            throw new InvalidEregException('a literal null byte in the regex');\n        }\n        if (strpos('\\^$.[]|()?*+{}-/', $content) !== \\false) {\n            return '\\\\' . $content;","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/rectorphp/rector/blob/408fcb0ff1833e3d26cbc9b04c23a77565814a16/rules/Php70/EregToPcreTransformer.php#L208-L244","documentation":"processSquareBracket() parsed a range 'a-b' inside a character class and found ord($a) > ord($b) — the range is inverted (EregToPcreTransformer.php:226). POSIX ERE requires the start code point to be <= the end code point, so '[z-a]' is invalid and InvalidEregException('an invalid character range %d-%d\"') is thrown with the offending code points, aborting the ereg-to-preg conversion.","triggerScenarios":"Rector (Php70 set / EregToPregMatchRector, target PHP >= 7.0) processes an ereg-family call whose literal pattern contains an inverted class range, e.g. `ereg('[z-a]', $s)`, `split('[Z-a]', $s)` is fine (Z < a) but `'[9-0]'` or `'[b-A]'` throw. The sprintf fills in (int) ord values of both endpoints.","commonSituations":"Typos when hand-writing ranges; 'make it match everything A-z' attempts that swap the endpoints; ranges copied between case-sensitive and case-insensitive contexts (eregi) where the author reversed letters expecting case folding.","solutions":["Swap the endpoints in the flagged pattern: '[z-a]' -> '[a-z]'.","If the intent was 'either case plus punctuation', write it explicitly, e.g. '[A-Za-z]'.","Re-run rector; preflight-scan literal ereg patterns for '-'-separated pairs inside classes where the left code point exceeds the right."],"exampleFix":"// before - inverted range\nereg('[z-a]', $subject);\n\n// after - correct order\nereg('[a-z]', $subject); // rector: preg_match('#[a-z]#m', $subject)","handlingStrategy":"validation","validationCode":"// quick lint: every a-b range inside a class must satisfy ord(a) <= ord(b)\nfunction rangesOrdered(string $class): bool {\n    return !preg_match('~(.)-(.)~', $class, $m) || ord($m[1]) <= ord($m[2]);\n}","typeGuard":null,"tryCatchPattern":"try {\n    $pcre = $eregToPcreTransformer->transform($pattern, $ignoreCase);\n} catch (InvalidEregException $e) {\n    // inverted range like [z-a] — swap the endpoints and re-run\n    continue;\n}","preventionTips":["Write ranges low-to-high by code point ('[a-z]', '[0-9]', '[A-Za-z]').","Remember case-sensitivity: 'a-Z' is invalid because ord('Z') < ord('a').","Lint class ranges for endpoint order before the Php70 migration run."],"tags":["rector","php","regex","posix-ere","character-class","range","migration"],"backgroundTag":"invalid-regex-syntax","analyzedSha":"408fcb0ff1833e3d26cbc9b04c23a77565814a16","analyzedAt":"2026-08-21T05:11:02.643Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}