NationalSecurityAgency/ghidra · error · SQLException
Zero byte in SQL string
Error message
Zero byte in SQL string
What it means
`appendEscapedLiteral` walks a string char-by-char to build a safe SQL literal (doubling `\` and `'`). If it hits a NUL byte (`\0`) it throws SQLException immediately rather than escaping. NUL bytes can truncate strings in C-based drivers and corrupt SQL parsing, so they are rejected outright.
Source
Thrown at Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/client/AbstractSQLFunctionDatabase.java:810
else {
newArray = new OptionalTable[1];
newArray[0] = table;
}
optionaltables = newArray;
return table;
}
/**
*
* @param buf the string builder object
* @param str the string to parse
* @throws SQLException if there is a zero byte in the string
*/
public static void appendEscapedLiteral(StringBuilder buf, String str) throws SQLException {
for (int i = 0; i < str.length(); ++i) {
char ch = str.charAt(i);
if (ch == '\0') {
throw new SQLException("Zero byte in SQL string");
}
if (ch == '\\' || ch == '\'') {
buf.append(ch);
}
buf.append(ch);
}
}
/**
* Convert a low-level list of function rows into full FunctionDescription objects
* @param simres (optional -- may be null) generate a SimilarityNote for every function
* @param descvec is the list of low-level function rows
* @param vecres (optional -- may be null) vector result producing these functions
* @param res is the DescriptionManager holding the newly generated FunctionDescriptions
* @param srec (optional -- may be null) is a description object of the vector
* @throws SQLException is there is an error querying tables
* @throws LSHException for internal consistency errors
*/View on GitHub (pinned to d5f144c24d)
Solutions
- Sanitize the offending string -- strip NUL bytes -- before passing it to BSim insert/query APIs.
- Identify which field carries the \0 (exe name vs function name vs metadata) from the call stack.
- Fix the upstream importer if it is emitting null bytes into name fields.
Example fix
// before
String name = rawFunctionName; // may contain \0
// after
String name = rawFunctionName.replace("\0", ""); Defensive patterns
Strategy: validation
Validate before calling
// Reject any string carrying NUL before it reaches appendEscapedLiteral / insert.
static String sanitizeForSql(String s) {
if (s == null) return s;
if (s.indexOf('\0') >= 0)
throw new IllegalArgumentException("NUL byte in value");
return s;
} Type guard
// isSafeForSqlLiteral: true iff the string can be escaped without error.
static boolean isSafeForSqlLiteral(String s) {
return s != null && s.indexOf('\0') < 0;
} Try / catch
try {
db.insert(manager);
} catch (SQLException e) {
if (e.getMessage().equals("Zero byte in SQL string")) {
// bad input -- sanitize the offending name and retry, or skip the record
throw new BadInputException("NUL byte in symbol/exe name", e);
}
throw e;
} Prevention
- Sanitize every string sourced from binary analysis before DB write.
- Strip or reject control characters (NUL especially) in name fields.
- Add a pre-flight assertion on name fields during ingest.
When it happens
Trigger: Inserting or querying with a string field (function name, exe name, metadata) that contains an embedded `\0`. In Ghidra's reverse-engineering context, malformed or obfuscated binaries can yield symbol names carrying null bytes that leak through to the BSim ingest path.
Common situations: Importing analysis from corrupted/obfuscated binaries; binary data accidentally placed in a name field; reading non-UTF-8 or non-null-terminated buffers; symbol tables with embedded nulls.
Related errors
- Database does not exist: {}
- Database already exists: {}
- Could not create database: {}
- Insert failed for vector table
- Bad characters in requested category type
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/25e240f6fbdfb123.
Report an issue: GitHub.