Skip to content

Commit 2e951bd

Browse files
author
Qian Gong
committed
Fix floating-point exception in Zstd::Decompress
Bug: When decompressing multiple variables sequentially, if the decompressed size (actual_out_count) was larger than the current buffer_size, the Resize() function would free and reallocate BOTH in_data AND out_data. This destroyed the compressed data that was just copied to in_data, causing ZSTD_decompress to read garbage/zeros and produce invalid output. Fix: Only reallocate out_data when needed for larger output, leaving in_data (which contains the compressed data) untouched.
1 parent e420727 commit 2e951bd

1 file changed

Lines changed: 14 additions & 2 deletions

File tree

include/mgard-x/Lossless/Zstd.hpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,19 @@ template <typename DeviceType> class Zstd {
111111

112112
uint32_t actual_out_count = 0;
113113
actual_out_count = *reinterpret_cast<const size_t *>(in_data);
114-
Resize(actual_out_count, compressionLevel, queue_idx);
114+
115+
// FIX: Only resize out_data if needed, do not touch in_data which contains
116+
// the compressed data we just copied. The original code called Resize()
117+
// which would free and reallocate BOTH in_data and out_data, destroying
118+
// the compressed data when actual_out_count > buffer_size.
119+
if (this->buffer_size < actual_out_count) {
120+
size_t const estimated_out_size = ZSTD_compressBound(actual_out_count);
121+
if (out_data != nullptr) {
122+
MemoryManager<DeviceType>::FreeHost(out_data, queue_idx);
123+
}
124+
MemoryManager<DeviceType>::MallocHost(
125+
out_data, estimated_out_size + sizeof(size_t), queue_idx);
126+
}
115127
DeviceRuntime<DeviceType>::SyncQueue(queue_idx);
116128

117129
ZSTD_decompress(out_data, actual_out_count, in_data + sizeof(size_t),
@@ -137,4 +149,4 @@ template <typename DeviceType> class Zstd {
137149

138150
} // namespace mgard_x
139151

140-
#endif
152+
#endif

0 commit comments

Comments
 (0)