{"record":{"id":"68bac70123b52014","repo":"oracle/graal","slug":"invalid-type-descriptor-68bac7","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":244,"sourceCode":"                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++;\n                }\n                final int dimensions = index - beginIndex;\n                if (dimensions > 255) {\n                    throw new ParserException.ClassFormatError(\"Array with more than 255 dimensions \" + descriptor.subSequence(beginIndex));\n                }\n                return skipValidTypeDescriptor(descriptor, index, slashes);\n            }\n        }\n        throw new ParserException.ClassFormatError(\"Invalid type descriptor \" + descriptor.subSequence(beginIndex));\n    }\n\n    /**\n     * Gets the type descriptor for the specified component type descriptor with the specified\n     * number of dimensions. For example if the number of dimensions is 1, then this method will\n     * return a descriptor for an array of the component type; if the number of dimensions is 2, it\n     * will return a descriptor for an array of an array of the component type, etc.\n     *\n     * @param type the type descriptor for the component type of the array\n     * @param dimensions the number of array dimensions\n     * @return the canonical type descriptor for the specified component type and dimensions\n     */\n    public Symbol<Type> arrayOf(Symbol<Type> type, int dimensions) {\n        assert dimensions > 0;\n        if (TypeSymbols.getArrayDimensions(type) + dimensions > 255) {\n            throw new ParserException.ClassFormatError(\"Array type with more than 255 dimensions\");\n        }\n        // Prepend #dimensions '[' to type descriptor.","sourceCodeStart":226,"sourceCodeEnd":262,"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#L226-L262","documentation":"Defensive tail of skipValidTypeDescriptor: after the early return for non-'['/non-'L' characters and fully handling the 'L' and '[' cases, the final throw 'Invalid type descriptor <rest>' is only reachable through a switch mismatch. In practice it fires if the method is entered with a character value that is neither a valid single-char descriptor, 'L', nor '[' — e.g. an unexpected control or non-ASCII byte in the descriptor.","triggerScenarios":"Theoretically unreachable for ASCII input because non-'L'/'[' returns early; reachable only via unusual chars that slip past earlier validation or future enum/switch changes. Treat hits as a descriptor containing an unexpected byte (e.g. raw byte > 127 cast to char).","commonSituations":"Malformed or fuzzed class files with non-ASCII bytes in descriptors; byte-to-char casts producing unexpected values; changes to the descriptor grammar in newer JVM versions.","solutions":["Sanitize/validate descriptor bytes (printable ASCII, known grammar) before parsing","If hit while parsing a real class file, report the class/method context — the descriptor itself is corrupt","Use a strict descriptor validator (regex or full grammar parser) upstream"],"exampleFix":"// before: pass raw bytes straight through\nSymbol<Type> t = typeSymbols.parse(rawSymbol, 0, true);\n\n// after: validate first\nif (!desc.matches(\"(\\[)*(V|Z|C|F|D|B|S|I|J|L[^;.\\[]+;)\")) throw new ClassFormatException(\"bad descriptor: \" + desc);\nSymbol<Type> t = typeSymbols.parse(rawSymbol, 0, true);","handlingStrategy":"try-catch","validationCode":"if (!desc.matches(\"(\\[)*(V|Z|C|F|D|B|S|I|J|L[^;.\\[]+;)\")) throw new IllegalArgumentException(\"Descriptor failed grammar check: \" + desc);","typeGuard":null,"tryCatchPattern":"catch (ParserException.ClassFormatError e) { treat the whole class file as corrupt; skip/quarantine it and report the source artifact }","preventionTips":["Run a full grammar/regex validation on descriptors from untrusted or fuzzed input","Sanitize non-ASCII bytes before parsing class-file strings"],"tags":["espresso","classfile","descriptor","parsing","defensive"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}