{"record":{"id":"a8a1038f49f7304b","repo":"prestodb/presto","slug":"malformed-dn","errorCode":null,"errorMessage":"Malformed DN: ","messagePattern":"Malformed DN: ","errorType":"exception","errorClass":"java.lang.IllegalStateException","httpStatus":null,"severity":"error","filePath":"presto-client/src/main/java/okhttp/internal/tls/DistinguishedNameParser.java","lineNumber":329,"sourceCode":"                res = (res << 6) + (b & 0x3F);\n            }\n            return (char) res;\n        }\n        else {\n            return 0x3F; //FIXME failed to decode UTF-8 char - return '?'\n        }\n    }\n\n    // Returns byte representation of a char pair\n    // The char pair is composed of DN char in\n    // specified 'position' and the next char\n    // According to BNF syntax:\n    // hexchar    = DIGIT / \"A\" / \"B\" / \"C\" / \"D\" / \"E\" / \"F\"\n    //                    / \"a\" / \"b\" / \"c\" / \"d\" / \"e\" / \"f\"\n    private int getByte(int position)\n    {\n        if (position + 1 >= length) {\n            throw new IllegalStateException(\"Malformed DN: \" + dn);\n        }\n\n        int b1;\n        int b2;\n\n        b1 = chars[position];\n        if (b1 >= '0' && b1 <= '9') {\n            b1 = b1 - '0';\n        }\n        else if (b1 >= 'a' && b1 <= 'f') {\n            b1 = b1 - 87; // 87 = 'a' - 10\n        }\n        else if (b1 >= 'A' && b1 <= 'F') {\n            b1 = b1 - 55; // 55 = 'A' - 10\n        }\n        else {\n            throw new IllegalStateException(\"Malformed DN: \" + dn);\n        }","sourceCodeStart":311,"sourceCodeEnd":347,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-client/src/main/java/okhttp/internal/tls/DistinguishedNameParser.java#L311-L347","documentation":"getByte() decodes two hex characters into one byte; it throws \"Malformed DN\" when position+1 >= length, meaning there are fewer than two characters left to decode. Called from hexAV, res (escaped hex pairs like \\AB), and getUTF8. The DN ends in the middle of a hex pair.","triggerScenarios":"An escaped hex pair like \"CN=\\\\4\" (single hex char at end of string) or a hex AV whose byte decoding runs past the end of the DN string.","commonSituations":"Truncated certificates or DN strings, DNs cut off in log/config copy-paste, or non-conforming CAs emitting odd-length escaped hex sequences.","solutions":["Reissue or obtain an intact certificate; verify with openssl x509 -text that the subject DN is complete.","Fix the DN string in configuration so every \\\\XX escape has exactly two hex digits.","Check for truncation when storing DNs (column length limits in databases, line breaks in files).","Update presto-client/okhttp version if certificates use unusual encodings that newer parsers handle."],"exampleFix":"// before\n\"DN\": \"CN=Server,O=Acme,C=US\\\\4A\"  // truncated mid-escape\n// after\n\"DN\": \"CN=Server,O=Acme,C=US\\\\4A2B\"","handlingStrategy":"validation","validationCode":"boolean escapesAreComplete(String dn) {\n    if (dn == null) return false;\n    for (int i = 0; i < dn.length(); i++) {\n        if (dn.charAt(i) == '\\\\') {\n            if (i + 2 >= dn.length()) return false; // needs two chars after backslash\n            i += 2;\n        }\n    }\n    return true;\n}","typeGuard":"boolean hasTwoCharsAfterBackslash(String s) {\n    return s == null || s.length() < 2 || s.lastIndexOf('\\\\') <= s.length() - 3;\n}","tryCatchPattern":"try {\n    subject.parse();\n} catch (IllegalStateException e) {\n    rejectCertificate(\"Truncated escape sequence in DN\");\n}","preventionTips":["Check for DN truncation in DB columns, config keys, and logs.","Validate certificates externally (keytool -list, openssl) before client-side use.","Keep presto-client/okhttp updated for parser robustness fixes.","Avoid copy-pasting DNs; load them from verified files."],"tags":["tls","x509","hex-decoding","dn-parser"],"backgroundTag":"malformed-x509-dn","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}