Security: zstd decompression may allocate ZSTD_CONTENTSIZE_UNKNOWN bytes #159

Closed
opened 2026-07-29 18:34:59 +02:00 by TapTap · 0 comments
Owner

Description

data_decompress() in src/shared/compression.c:46-103 uses ZSTD_getFrameContentSize() to determine the decompression buffer size. This function can return ZSTD_CONTENTSIZE_UNKNOWN (0xFFFFFFFFFFFFFFFF) for frames that do not store the original size. The code only checks ZSTD_isError() and then immediately casts the result to size_t for malloc():

unsigned long long dst_size =
    ZSTD_getFrameContentSize(compressed_data->data, compressed_data->size);
...
size_t buf_size =
    (!ZSTD_isError(dst_size) && dst_size > 0) ? (size_t)dst_size : INITIAL_DECOMPRESS_BUF_SIZE;

If dst_size is ZSTD_CONTENTSIZE_UNKNOWN, the condition is true (dst_size > 0 and not an error), causing an allocation of SIZE_MAX bytes and an immediate OOM.

Reproduction scenario

Craft a valid zstd frame with the content-size flag unset and send it to the server. The decompressor will attempt to allocate a buffer of SIZE_MAX.

Suggested fix

  1. Explicitly check for ZSTD_CONTENTSIZE_UNKNOWN and ZSTD_CONTENTSIZE_ERROR and fall back to streaming growth with a small initial buffer.
  2. Use a bounded streaming decompression loop so that the buffer grows incrementally up to a configurable maximum.

Severity

High

Category

security


This issue was automatically generated by the issue-creator agent.

## Description `data_decompress()` in `src/shared/compression.c:46-103` uses `ZSTD_getFrameContentSize()` to determine the decompression buffer size. This function can return `ZSTD_CONTENTSIZE_UNKNOWN` (`0xFFFFFFFFFFFFFFFF`) for frames that do not store the original size. The code only checks `ZSTD_isError()` and then immediately casts the result to `size_t` for `malloc()`: ```c unsigned long long dst_size = ZSTD_getFrameContentSize(compressed_data->data, compressed_data->size); ... size_t buf_size = (!ZSTD_isError(dst_size) && dst_size > 0) ? (size_t)dst_size : INITIAL_DECOMPRESS_BUF_SIZE; ``` If `dst_size` is `ZSTD_CONTENTSIZE_UNKNOWN`, the condition is true (`dst_size > 0` and not an error), causing an allocation of `SIZE_MAX` bytes and an immediate OOM. ## Reproduction scenario Craft a valid zstd frame with the content-size flag unset and send it to the server. The decompressor will attempt to allocate a buffer of `SIZE_MAX`. ## Suggested fix 1. Explicitly check for `ZSTD_CONTENTSIZE_UNKNOWN` and `ZSTD_CONTENTSIZE_ERROR` and fall back to streaming growth with a small initial buffer. 2. Use a bounded streaming decompression loop so that the buffer grows incrementally up to a configurable maximum. ## Severity High ## Category security --- _This issue was automatically generated by the issue-creator agent._
TapTap added the bugsecurityneeds-triagememory labels 2026-07-29 18:34:59 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: TapTap/FastSync#159