How to Get the Decompressed Size of a Zstd Frame
Call ZSTD_getFrameContentSize() to extract the original uncompressed size directly from the Zstandard frame header without performing full decompression.
The Zstandard (zstd) compression library embeds the decompressed content size within the frame header whenever the size is known at compression time. According to the facebook/zstd source code, the ZSTD_getFrameContentSize() helper parses this metadata in constant time, enabling efficient buffer pre-allocation before calling ZSTD_decompress().
ZSTD_getFrameContentSize() Function Signature
The primary API for retrieving frame size information is declared in [lib/zstd.h](https://github.com/facebook/zstd/blob/dev/lib/zstd.h) (lines 179-190):
ZSTDLIB_API unsigned long long ZSTD_getFrameContentSize(const void *src,
size_t srcSize);
Key parameters:
src: Pointer to the beginning of a ZSTD encoded frame.srcSize: Size of the buffer pointed to bysrc. Must be at least the header size (minimum 12 bytes for the maximum header).
The function performs strict header parsing only—it never touches the compressed payload—making it an O(1) operation regardless of frame size.
Return Value Semantics
ZSTD_getFrameContentSize() returns an unsigned long long with three distinct outcome categories, as documented in the header:
| Return Value | Macro Definition | Meaning |
|---|---|---|
>= 0 |
N/A | Exact decompressed size in bytes (may be 0 for empty frames). |
0ULL - 1 |
ZSTD_CONTENTSIZE_UNKNOWN |
Header does not contain a size (typical for streaming compression). |
0ULL - 2 |
ZSTD_CONTENTSIZE_ERROR |
Invalid frame header, corrupt data, or srcSize too small. |
Critical handling logic:
ZSTD_CONTENTSIZE_ERROR: Indicates malformed input or insufficient buffer size. Abort decompression.ZSTD_CONTENTSIZE_UNKNOWN: The frame was produced using streaming APIs (ZSTD_compressStream()) without storing the final size. Fall back to streaming decompression or supply a safe upper bound.- Valid size: Allocate a destination buffer of exactly the returned size and proceed with
ZSTD_decompress().
Deprecated API Differences
The older helper ZSTD_getDecompressedSize() (declared in [lib/zstd.h](https://github.com/facebook/zstd/blob/dev/lib/zstd.h) lines 202-214) is now deprecated. It merges empty frames, unknown sizes, and errors into a single 0 return value, making error handling ambiguous. New code should exclusively use ZSTD_getFrameContentSize() for explicit sentinel checking.
Practical Implementation Example
The following example demonstrates the recommended workflow: probing the frame header, validating return codes, allocating exact memory, and decompressing.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "zstd.h"
int decompress_frame(const void *src, size_t srcSize)
{
/* 1. Probe the frame header */
unsigned long long decSize = ZSTD_getFrameContentSize(src, srcSize);
if (decSize == ZSTD_CONTENTSIZE_ERROR) {
fprintf(stderr, "Invalid ZSTD frame header or insufficient input.\n");
return 1;
}
if (decSize == ZSTD_CONTENTSIZE_UNKNOWN) {
fprintf(stderr, "Decompressed size not stored. Use ZSTD_decompressStream().\n");
return 1;
}
/* 2. Pre-allocate exact output buffer */
void *dst = malloc((size_t)decSize);
if (!dst) {
perror("malloc");
return 1;
}
/* 3. Decompress in single pass */
size_t ret = ZSTD_decompress(dst, (size_t)decSize, src, srcSize);
if (ZSTD_isError(ret)) {
fprintf(stderr, "Decompression failed: %s\n", ZSTD_getErrorName(ret));
free(dst);
return 1;
}
printf("Successfully decompressed %zu bytes (expected %llu).\n", ret, decSize);
/* ... use dst ... */
free(dst);
return 0;
}
Streaming Fallback for Unknown Sizes
When ZSTD_CONTENTSIZE_UNKNOWN is returned, implement streaming decompression using ZSTD_decompressStream():
void decompress_streaming(const void *src, size_t srcSize)
{
ZSTD_DCtx *dctx = ZSTD_createDCtx();
if (!dctx) {
fprintf(stderr, "Failed to create decompression context.\n");
return;
}
ZSTD_inBuffer input = { src, srcSize, 0 };
size_t outBuffSize = ZSTD_DStreamOutSize(); /* 128KB default */
void *outBuff = malloc(outBuffSize);
if (!outBuff) {
ZSTD_freeDCtx(dctx);
return;
}
while (input.pos < input.size) {
ZSTD_outBuffer output = { outBuff, outBuffSize, 0 };
size_t ret = ZSTD_decompressStream(dctx, &output, &input);
if (ZSTD_isError(ret)) {
fprintf(stderr, "Stream error: %s\n", ZSTD_getErrorName(ret));
break;
}
/* Process output.dst[0..output.pos] here */
}
free(outBuff);
ZSTD_freeDCtx(dctx);
}
Key Source Files in facebook/zstd
Understanding the implementation context requires examining these specific files:
- [
lib/zstd.h](https://github.com/facebook/zstd/blob/dev/lib/zstd.h): DeclaresZSTD_getFrameContentSize()and documents the sentinel value semantics. - [
lib/decompress/zstd_decompress.c](https://github.com/facebook/zstd/blob/dev/lib/decompress/zstd_decompress.c): Contains the low-level decompression implementation where header sizes are validated and used for buffer allocation. - [
contrib/seekable_format/zstdseek_decompress.c](https://github.com/facebook/zstd/blob/dev/contrib/seekable_format/zstdseek_decompress.c): Real-world usage demonstrating how seekable frame formats utilize the size extraction helper to navigate compressed archives. - [
doc/educational_decoder/zstd_decompress.h](https://github.com/facebook/zstd/blob/dev/doc/educational_decoder/zstd_decompress.h): Educational reference implementation showing header parsing logic.
Summary
ZSTD_getFrameContentSize()is the modern, non-deprecated API to get the decompressed size of a zstd frame from its header.- The function returns
unsigned long longvalues interpretable via three states: valid size,ZSTD_CONTENTSIZE_UNKNOWN, orZSTD_CONTENTSIZE_ERROR. - Always provide at least 12 bytes of the frame header to ensure the function can parse the maximum header size.
- The operation parses only header metadata (O(1)), never touching the compressed payload.
- For unknown sizes, fall back to the streaming API (
ZSTD_decompressStream()) to avoid unbounded memory allocation. - Avoid the deprecated
ZSTD_getDecompressedSize()due to its ambiguous0return value.
Frequently Asked Questions
What is the minimum buffer size required to call ZSTD_getFrameContentSize?
You must provide at least 12 bytes of the compressed frame. This represents the maximum possible header size for a ZSTD frame. Providing fewer bytes will result in ZSTD_CONTENTSIZE_ERROR because the function cannot parse the complete size field.
How do I handle frames where the decompressed size is unknown?
When ZSTD_getFrameContentSize() returns ZSTD_CONTENTSIZE_UNKNOWN, the frame was compressed using streaming APIs without storing the final size in the header. You must use ZSTD_decompressStream() with a circular output buffer of reasonable size (e.g., ZSTD_DStreamOutSize()) to decompress incrementally rather than pre-allocating a single large buffer.
What is the difference between ZSTD_getFrameContentSize and ZSTD_getDecompressedSize?
ZSTD_getDecompressedSize() is deprecated and ambiguous—it returns 0 for empty frames, unknown sizes, and errors alike. ZSTD_getFrameContentSize() distinguishes these cases using explicit sentinel values (ZSTD_CONTENTSIZE_UNKNOWN and ZSTD_CONTENTSIZE_ERROR), allowing proper error handling and distinct logic for streaming scenarios.
Can ZSTD_getFrameContentSize return a size larger than available memory?
Yes. Because the function returns unsigned long long (64-bit), the declared decompressed size may exceed the addressable memory of a 32-bit process or available system RAM. Always check the returned value against system limits before calling malloc(), and prefer the streaming API if the size exceeds safe allocation thresholds.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →