NationalSecurityAgency/ghidra · critical · IOException
compressed memory buffer is corrupt
Error message
compressed memory buffer is corrupt
What it means
Thrown by DBTraceMemoryBufferEntry.doGetCompressedBytes() when reading from a GZIP-compressed memory buffer and the decompressed stream returns fewer bytes (amt) than the requested length (len). The method wraps the buffer in a GZIPInputStream and reads len bytes at a computed offset; if amt != len, the compressed buffer is internally inconsistent. An IOException (checked) indicates the compressed data is truncated or corrupt.
Source
Thrown at Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceMemoryBufferEntry.java:167
assert isSane(srcOffset, len, blockNum);
if (compressed) {
return doGetCompressedBytes(buf, srcOffset, len, blockNum);
}
buffer.get((blockNum << DBTraceMemorySpace.BLOCK_SHIFT) + srcOffset, buf.array(),
buf.arrayOffset() + buf.position(), len);
buf.position(buf.position() + len);
return len;
}
protected int doGetCompressedBytes(ByteBuffer buf, int srcOffset, int len, int blockNum)
throws IOException {
try (InputStream is = new GZIPInputStream(new DBBufferInputStream(buffer))) {
is.skip((blockNum << DBTraceMemorySpace.BLOCK_SHIFT) + srcOffset);
int amt = is.read(buf.array(), buf.arrayOffset() + buf.position(), len);
buf.position(buf.position() + amt);
if (amt != len) {
// There should always be enough
throw new IOException("compressed memory buffer is corrupt");
}
return len;
}
}
protected void doGetBlock(int blockNum, byte[] data)
throws IndexOutOfBoundsException, IOException {
assert isInUse(blockNum);
if (compressed) {
doGetCompressedBlock(blockNum, data);
}
buffer.get(blockNum << DBTraceMemorySpace.BLOCK_SHIFT, data);
}
protected void doGetCompressedBlock(int blockNum, byte[] data) throws IOException {
try (InputStream is = new GZIPInputStream(new DBBufferInputStream(buffer))) {
is.skip(blockNum << DBTraceMemorySpace.BLOCK_SHIFT);
int amt = is.read(data);View on GitHub (pinned to d5f144c24d)
Solutions
- Restore the trace database from a backup taken before the corruption.
- Re-record the trace from the debugging session if a backup is unavailable.
- If only specific memory blocks are affected, clear and re-record those regions.
- Investigate storage integrity (disk health, filesystem checks) to prevent recurrence.
Defensive patterns
Strategy: fallback
Try / catch
try {
int amt = memory.getBytes(snap, addr, buf);
} catch (IOException e) {
if (e.getMessage().contains("compressed memory buffer is corrupt")) {
// corrupted compressed buffer; restore from backup or re-record
logger.severe("Corrupt compressed buffer at " + addr + ": " + e.getMessage());
}
} Prevention
- Keep backups of trace databases before upgrades or migrations.
- Ensure disk writes complete before shutting down Ghidra.
- Avoid concurrent access to trace database files.
- Re-record corrupted traces from the original debug session.
When it happens
Trigger: Calling doGetCompressedBytes() (via getBytes or doGetBlock) on a DBTraceMemoryBufferEntry flagged as compressed, where the underlying GZIP data stream is shorter than expected. This happens when the compressed buffer was partially written, truncated during save, or corrupted on disk.
Common situations: Database corruption after a crash or improper shutdown during a save operation. Disk space exhaustion that truncated a write. Partial trace database copy or transfer. Version or format incompatibility in the compression scheme.
Related errors
- Trace Bytes table is corrupt
- Open failed: {}
- Failed to read {len} bytes at {addr}
- Trace does not contain referenced instruction: ({getStartSna
- Instruction has incompatible prototype at: ({getStartSnap},{
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/63859ead43858df1.
Report an issue: GitHub.