{"record":{"id":"265e00c26334b57a","repo":"oracle/graal","slug":"invalid-type-descriptor","errorCode":null,"errorMessage":"invalid type descriptor: {}","messagePattern":"invalid type descriptor: (.+?)","errorType":"exception","errorClass":"ParserException.ClassFormatError","httpStatus":null,"severity":"error","filePath":"espresso-shared/src/com.oracle.truffle.espresso.classfile/src/com/oracle/truffle/espresso/classfile/descriptors/TypeSymbols.java","lineNumber":217,"sourceCode":"                return forPrimitive(JavaKind.fromPrimitiveOrVoidTypeChar((char) descriptor.byteAt(beginIndex)));\n            } catch (IllegalStateException e) {\n                throw new ParserException.ClassFormatError(\"invalid descriptor: \" + descriptor);\n            }\n        }\n        return symbols.getOrCreate(descriptor.subSequence(beginIndex, endIndex));\n    }\n\n    /**\n     * Verifies that a valid type descriptor is at {@code beginIndex} in {@code type}.\n     *\n     * @param slashes specifies if package components are separated by {@code '/'} or {@code '.'}\n     * @return the index one past the valid type descriptor starting at {@code beginIndex}\n     * @throws ParserException.ClassFormatError if there is no valid type descriptor\n     */\n    @TruffleBoundary\n    static int skipValidTypeDescriptor(Symbol<? extends Descriptor> descriptor, int beginIndex, boolean slashes) throws ParserException.ClassFormatError {\n        if (beginIndex >= descriptor.length()) {\n            throw new ParserException.ClassFormatError(\"invalid type descriptor: \" + descriptor);\n        }\n        char ch = (char) descriptor.byteAt(beginIndex);\n        if (ch != '[' && ch != 'L') {\n            return beginIndex + 1;\n        }\n        switch (ch) {\n            case 'L': {\n                final int endIndex = skipClassName(descriptor, beginIndex + 1, slashes ? '/' : '.');\n                if (endIndex > beginIndex + 1 && endIndex < descriptor.length() && descriptor.byteAt(endIndex) == ';') {\n                    return endIndex + 1;\n                }\n                throw new ParserException.ClassFormatError(\"Invalid Java name \" + descriptor.subSequence(beginIndex));\n            }\n            case '[': {\n                // compute the number of dimensions\n                int index = beginIndex;\n                while (index < descriptor.length() && descriptor.byteAt(index) == '[') {\n                    index++;","sourceCodeStart":199,"sourceCodeEnd":235,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/espresso-shared/src/com.oracle.truffle.espresso.classfile/src/com/oracle/truffle/espresso/classfile/descriptors/TypeSymbols.java#L199-L235","documentation":"skipValidTypeDescriptor verifies that a valid type descriptor starts at beginIndex. The first check is bounds: if beginIndex >= descriptor.length() there is nothing to parse, and it throws ParserException.ClassFormatError 'invalid type descriptor: <desc>'.","triggerScenarios":"Calling parse/skip with a beginIndex equal to or beyond the descriptor length — typically a scanner that already consumed the string (e.g. after ')' in a malformed signature) or an off-by-one loop bound.","commonSituations":"Custom signature-walking loops that advance past the end before re-checking; empty descriptor strings from failed lookups; sliced substrings that dropped the last character.","solutions":["Always bound-check beginIndex < descriptor.length() before each parse/skip step in your own loop","Fix the driver logic that produced the out-of-range index (usually the preceding descriptor's length was wrong)","Pre-validate full signatures with a complete parser rather than manual index arithmetic"],"exampleFix":"// before\nint i = ...; // may equal descriptor.length()\nTypeSymbols.skipValidTypeDescriptor(desc, i, true);\n\n// after\nif (i >= desc.length()) throw new ClassFormatException(\"signature ended unexpectedly\");\nTypeSymbols.skipValidTypeDescriptor(desc, i, true);","handlingStrategy":"validation","validationCode":"if (beginIndex < 0 || beginIndex >= descriptor.length()) throw new IllegalArgumentException(\"beginIndex out of range: \" + beginIndex);","typeGuard":null,"tryCatchPattern":"catch (ParserException.ClassFormatError e) { dump descriptor plus index to pinpoint the scanning bug }","preventionTips":["Re-check bounds after every index advance in descriptor-walking loops","Prefer whole-signature parsers over manual index arithmetic"],"tags":["espresso","classfile","descriptor","parsing","indexing"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}