{"record":{"id":"7e3d96e4c901455c","repo":"oracle/graal","slug":"got-illegal-regionfrom-value-d-regionfrom-must","errorCode":null,"errorMessage":"got illegal regionFrom value: %d. regionFrom must be >= 0 and <= input length (%d)","messagePattern":"got illegal regionFrom value: (.+?)\\. regionFrom must be >= 0 and <= input length \\((.+?)\\)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/RegexExecNode.java","lineNumber":85,"sourceCode":"        Object[] args = frame.getArguments();\n        TruffleString.Encoding encoding = getEncoding().getTStringEncoding();\n        CompilerAsserts.partialEvaluationConstant(encoding);\n        TruffleString input = expectStringNode.execute(args[0], encoding);\n        int length = InputOps.length(input, getEncoding());\n        long fromIndex = toLongNode.execute(args[1]);\n        if (fromIndex > Integer.MAX_VALUE) {\n            return RegexResult.getNoMatchInstance();\n        }\n        final int toIndex;\n        final int regionFrom;\n        final int regionTo;\n        if (args.length == 5) {\n            long toIndexLong = toLongNode.execute(args[2]);\n            long regionFromLong = toLongNode.execute(args[3]);\n            long regionToLong = toLongNode.execute(args[4]);\n            if (regionFromLong < 0 || regionFromLong > length) {\n                CompilerDirectives.transferToInterpreterAndInvalidate();\n                throw new IllegalArgumentException(String.format(\"got illegal regionFrom value: %d. regionFrom must be >= 0 and <= input length (%d)\", regionFromLong, length));\n            }\n            if (regionToLong < regionFromLong || regionToLong > length) {\n                CompilerDirectives.transferToInterpreterAndInvalidate();\n                throw new IllegalArgumentException(String.format(\"got illegal regionTo value: %d. regionTo must be >= regionFrom (%d) and <= input length (%d)\", regionToLong, regionFromLong, length));\n            }\n            if (fromIndex < regionFromLong || fromIndex > regionToLong) {\n                CompilerDirectives.transferToInterpreterAndInvalidate();\n                throw new IllegalArgumentException(\n                                String.format(\"got illegal fromIndex value: %d. fromIndex must be >= regionFrom (%d) and <= regionTo (%d)\", fromIndex, regionFromLong, regionToLong));\n            }\n            if (toIndexLong < fromIndex || toIndexLong > regionToLong) {\n                CompilerDirectives.transferToInterpreterAndInvalidate();\n                throw new IllegalArgumentException(String.format(\"got illegal toIndex value: %d. toIndex must be >= fromIndex (%d) and <= regionTo (%d)\", toIndexLong, fromIndex, regionToLong));\n            }\n            if (toIndexLong != regionToLong) {\n                CompilerDirectives.transferToInterpreterAndInvalidate();\n                throw new UnsupportedOperationException(String.format(\"got non-equal toIndex (%d) and regionTo (%d), support for this is not implemented yet\", toIndexLong, regionToLong));\n            }","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/RegexExecNode.java#L67-L103","documentation":"RegexExecNode is the Truffle regex engine's execution entry. In the 5-argument form (input, fromIndex, toIndex, regionFrom, regionTo) it validates the search region; regionFrom must be within [0, inputLength]. A negative regionFrom or one past the end of the input throws IllegalArgumentException.","triggerScenarios":"Calling the TRegex builtin/foreign function with 5 args where the 4th argument (regionFrom) is negative or greater than the input string length, e.g. regionFrom = input.length() + 1 or regionFrom = -1.","commonSituations":"Guest-language adapters (GraalJS, FastR, Python on GraalVM) mapping native regex APIs with region parameters; off-by-one bugs where callers pass a region computed against a different string than the one matched; lastIndex bookkeeping bugs.","solutions":["Clamp regionFrom to Math.max(0, Math.min(regionFrom, inputLength)) before invoking the engine.","Check that the region was computed against the same input string instance you pass as argument 1.","Audit lastIndex/region propagation in your adapter for negative or stale values after failed matches."],"exampleFix":"// before\nObject res = exec(in, start, end, regionFrom, regionTo); // regionFrom may be -1\n\n// after\nint rf = Math.max(0, Math.min((int) regionFrom, input.length()));\nObject res = exec(in, start, end, rf, regionTo);","handlingStrategy":"validation","validationCode":"static boolean validRegionFrom(long regionFrom, int inputLength) {\n    return regionFrom >= 0 && regionFrom <= inputLength;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Clamp all region/search indices into [0, input.length()] before calling the engine.","Compute region bounds from the same string instance you pass to the matcher.","Reset lastIndex/region state when switching to a new input string."],"tags":["regex","truffle","graalvm","argument-validation","region"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}