{"record":{"id":"b74034f8e39166b6","repo":"NationalSecurityAgency/ghidra","slug":"invalid-md5-hash-string-md5","errorCode":null,"errorMessage":"Invalid MD5 hash string: {md5}","messagePattern":"Invalid MD5 hash string: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/description/ExecutableRecord.java","lineNumber":88,"sourceCode":"\tprivate List<CategoryRecord> usercat; // Categories this executable belongs to\n\tprivate int xrefIndex; // Index for cross-referencing this executable from other records\n\n\tpublic static class Update {\n\t\tpublic ExecutableRecord update;\n\t\tpublic boolean name_exec; // Should name be updated\n\t\tpublic boolean architecture; // Should architecture be updated\n\t\tpublic boolean name_compiler;\n\t\tpublic boolean repository;\n\t\tpublic boolean path;\n\t\tpublic boolean date;\n\t\tpublic boolean categories; // True if there are either insertions or deletions\n\t\tpublic List<CategoryRecord> catinsert; // Non-null, if there are only insertions\n\t}\n\n\tprivate static void checkValidMD5(String md5) {\n\t\tMatcher matcher = md5Matcher.matcher(md5);\n\t\tif (!matcher.matches()) {\n\t\t\tthrow new IllegalArgumentException(\"Invalid MD5 hash string: \" + md5);\n\t\t}\n\t}\n\n\t/**\n\t * Convert a 32-bit integer to hexadecimal ascii representation\n\t * @param val is the integer to encode\n\t * @param buf accumulates the resulting ascii\n\t */\n\tprivate static void wordToAscii(int val, StringBuilder buf) {\n\t\tfor (int i = 28; i >= 0; i -= 4) {\n\t\t\tfinal int nibble = (val >> i) & 0xf;\n\t\t\tif (nibble < 10) {\n\t\t\t\tbuf.append((char) (nibble + '0'));\n\t\t\t}\n\t\t\telse {\n\t\t\t\tbuf.append((char) (nibble - 10 + 'a'));\n\t\t\t}\n\t\t}","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/description/ExecutableRecord.java#L70-L106","documentation":"Thrown by ExecutableRecord.checkValidMD5 when the supplied md5 string does not match the md5Matcher regex. checkValidMD5 is called from the ExecutableRecord constructor, so any path that builds an ExecutableRecord (newExecutableRecord, restoreXml, etc.) with a malformed md5 triggers it. It is an IllegalArgumentException (unchecked), not an LSHException.","triggerScenarios":"Constructing an ExecutableRecord or calling newExecutableRecord with a md5 string that is not a valid hex md5 (wrong length, non-hex characters, null-content, upper/lower case outside the allowed pattern).","commonSituations":"Passing a raw file hash with uppercase or with spaces; truncating the md5; passing an SHA-256 or other hash type instead of md5; empty or null-derived string; copy-paste introducing stray characters.","solutions":["Compute a real md5 and pass the 32-character lowercase hex string the matcher expects.","Validate the md5 against a hex regex (32 hex chars) before constructing the ExecutableRecord.","Normalize case (toLowerCase) and trim whitespace before passing.","Ensure you are not passing a different digest algorithm's output."],"exampleFix":"// before\nman.newExecutableRecord(maybeBadMd5, name, compiler, arch, date, repo, path, id);\n\n// after\nif (!md5.matches(\"[0-9a-fA-F]{32}\")) throw new IllegalArgumentException(\"bad md5\");\nman.newExecutableRecord(md5.toLowerCase(), name, compiler, arch, date, repo, path, id);","handlingStrategy":"validation","validationCode":"private static final java.util.regex.Pattern MD5 = java.util.regex.Pattern.compile(\"[0-9a-fA-F]{32}\");\nif (md5 == null || !MD5.matcher(md5).matches()) {\n    throw new IllegalArgumentException(\"md5 must be 32 hex chars: \" + md5);\n}\nman.newExecutableRecord(md5.toLowerCase(Locale.ROOT), ...);","typeGuard":"boolean isValidMd5(String s) { return s != null && s.length() == 32 && s.matches(\"[0-9a-fA-F]{32}\"); }","tryCatchPattern":"try {\n    man.newExecutableRecord(md5, ...);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"Invalid MD5 hash string\")) {\n        // recompute md5 and retry\n    } else throw e;\n}","preventionTips":["Always pass a freshly computed 32-char lowercase hex md5.","Trim whitespace and normalize case before constructing an ExecutableRecord.","Do not substitute other digest algorithms (SHA-256, etc.) for the md5 field."],"tags":["bsim","validation","md5","java"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}