Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package blosc2 for openSUSE:Factory checked in at 2026-10-18 19:25:27 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/blosc2 (Old) and /work/SRC/openSUSE:Factory/.blosc2.new.3698736 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "blosc2" Sun Oct 18 19:25:27 2026 rev:19 rq:1385849 version:3.3.5 Changes: -------- --- /work/SRC/openSUSE:Factory/blosc2/blosc2.changes 2026-09-15 12:48:33.806290469 +0200 +++ /work/SRC/openSUSE:Factory/.blosc2.new.3698736/blosc2.changes 2026-10-18 19:25:41.702711637 +0200 @@ -1,0 +2,12 @@ +Sat Oct 17 14:41:37 UTC 2026 - Martin Pluskal <[email protected]> + +- Update to 3.3.5 (bugfix and security-hardening release, no API + or format changes): + * Fixed integer overflow in BloscLZ match-length accumulation + that could lead to heap-buffer-overflow on crafted input + * Fixed heap-buffer-overflow in ZFP decompression paths from + missing input size validation + * Fixed division by zero in frame chunk handling on crafted + frames with zero chunksize + +------------------------------------------------------------------- Old: ---- c-blosc2-3.3.4.tar.gz New: ---- c-blosc2-3.3.5.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ blosc2.spec ++++++ --- /var/tmp/diff_new_pack.1JxIN6/_old 2026-10-18 19:25:42.503744961 +0200 +++ /var/tmp/diff_new_pack.1JxIN6/_new 2026-10-18 19:25:42.504745003 +0200 @@ -20,7 +20,7 @@ %define major 9 %define libname lib%{name}-%{major} Name: blosc2 -Version: 3.3.4 +Version: 3.3.5 Release: 0 Summary: A fast, compressed, persistent binary data store library for C License: BSD-2-Clause AND BSD-3-Clause AND MIT ++++++ c-blosc2-3.3.4.tar.gz -> c-blosc2-3.3.5.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/c-blosc2-3.3.4/ANNOUNCE.md new/c-blosc2-3.3.5/ANNOUNCE.md --- old/c-blosc2-3.3.4/ANNOUNCE.md 2026-09-10 11:48:50.000000000 +0200 +++ new/c-blosc2-3.3.5/ANNOUNCE.md 2026-09-24 11:35:30.000000000 +0200 @@ -1,27 +1,26 @@ -# Announcing C-Blosc2 3.3.4 +# Announcing C-Blosc2 3.3.5 A fast, compressed, and persistent binary data store library for C. ## What is new? -This release introduces bounded-memory tail compaction for contiguous on-disk -frames and clean file eviction for payload-free chunks in sparse frames. +This is a bugfix and maintenance release fixing robustness and security issues +discovered via OSS-Fuzz. -Updating chunks in place within an on-disk contiguous frame previously allocated -memory for the entire remaining payload tail in RAM. For large frames (tens or -hundreds of gigabytes), this caused large memory spikes or out-of-memory aborts. -Tail compaction now moves payload data using a bounded scratch buffer capped at -1 MiB, shifting data forward on shrink and backward on expansion for overlap -safety, ensuring RAM usage stays minimal regardless of dataset size. - -In sparse frames, updating chunks to payload-free special values (ZERO, UNINIT, -NAN) now unlinks and deletes the old physical chunk files instead of leaving -0-byte files on disk, preventing directory clutter and inode exhaustion during -cache churn. Deletion is coordinated safely after committing index updates and -is fully integrated with custom I/O backends. - -Additionally, memory mapping (`mmap`) stability has been improved on POSIX and -Windows, avoiding `MAP_FIXED` pitfalls on BSD/macOS and preserving external file -growth during cleanup. +First, an integer overflow in the BloscLZ decompressor's long-match length +accumulation loop was fixed. A crafted input with excessive continuation bytes +could wrap a 32-bit length past `INT32_MAX` into negative values, bypassing bounds +checks and leading to a heap buffer overflow. Length bounds are now verified +prior to addition. + +Second, input buffer size validation was added to the ZFP codec decompressors +(`zfp_acc_decompress`, `zfp_prec_decompress`, `zfp_rate_decompress`). Previously, +crafted frames with high metadata values could cause ZFP's bitstream reader to +read beyond buffer bounds. The required bitstream size is now validated against +the input length prior to decompression. + +Third, a potential division-by-zero (floating-point exception) in +`frame_get_chunk()` and `frame_get_lazychunk()` when encountering crafted frames +with `chunksize <= 0` during special-value chunk retrieval was guarded. There are no API or format changes in this release. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/c-blosc2-3.3.4/RELEASE_NOTES.md new/c-blosc2-3.3.5/RELEASE_NOTES.md --- old/c-blosc2-3.3.4/RELEASE_NOTES.md 2026-09-10 11:48:50.000000000 +0200 +++ new/c-blosc2-3.3.5/RELEASE_NOTES.md 2026-09-24 11:35:30.000000000 +0200 @@ -1,6 +1,41 @@ Release notes for C-Blosc2 ========================== +Changes from 3.3.4 to 3.3.5 +=========================== + +This is a bugfix and maintenance release addressing several robustness and +security issues reported via OSS-Fuzz in BloscLZ, ZFP codec plugins, and frame +handling. + +* **Fixed integer overflow in BloscLZ match-length accumulation (heap-buffer-overflow)**: + In `blosclz_decompress`, the `MATCH_LONG` decoding loop (`ctrl >> 5 == 7`) + accumulated continuation bytes (`0xFF`) into a signed 32-bit integer (`len`) + without overflow protection. After ~8 MB of `0xFF` bytes, `len` could wrap + past `INT32_MAX` into negative values, bypassing the `len > maxout` check and + causing a severe out-of-bounds heap write in `copy_match`. This is resolved + by checking `len > maxout - code` before the addition, rejecting invalid matches + before any overflow can occur. Reported via OSS-Fuzz (`decompress_chunk_fuzzer`). + +* **Fixed heap-buffer-overflow in ZFP decompression paths**: + In `zfp_acc_decompress`, `zfp_prec_decompress`, and `zfp_rate_decompress`, + a ZFP bitstream was opened on the compressed input without checking whether the + buffer was sufficiently sized for the stream reads dictated by codec parameters + and field dimensions. A crafted frame with a large `compcode_meta` and a small + payload could trigger an out-of-bounds read in ZFP's `stream_read_word`. Added + validation of the required bitstream size before decompression to ensure the + input buffer is large enough, returning `BLOSC2_ERROR_FAILURE` otherwise. + Reported via OSS-Fuzz (`decompress_frame_fuzzer`). + +* **Fixed division by zero (FPE) in `frame_get_chunk` and `frame_get_lazychunk`**: + When processing special-value chunks, a crafted frame with `chunksize <= 0` + caused a floating-point exception (division by zero) in the `nbytes % chunksize` + calculation for the last chunk. Added validation to ensure `chunksize > 0` before + evaluating the modulo expression, returning `BLOSC2_ERROR_INVALID_HEADER` on + invalid chunk sizes. Reported via OSS-Fuzz (`decompress_frame_fuzzer`). + +There are no API or format changes in this release. + Changes from 3.3.3 to 3.3.4 =========================== diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/c-blosc2-3.3.4/blosc/blosclz.c new/c-blosc2-3.3.5/blosc/blosclz.c --- old/c-blosc2-3.3.4/blosc/blosclz.c 2026-09-10 11:48:50.000000000 +0200 +++ new/c-blosc2-3.3.5/blosc/blosclz.c 2026-09-24 11:35:30.000000000 +0200 @@ -707,10 +707,13 @@ return 0; } code = *ip++; - len += code; - if (BLOSCLZ_UNLIKELY(len > maxout)) { + /* Guard before the addition so that `len` can never wrap past + INT32_MAX. The subsequent `len += 3` adds at most 3 more, + so capping at maxout here is safe and sufficient. */ + if (BLOSCLZ_UNLIKELY(len > maxout - code)) { return 0; } + len += code; } while (code == 255); } else { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/c-blosc2-3.3.4/blosc/frame.c new/c-blosc2-3.3.5/blosc/frame.c --- old/c-blosc2-3.3.4/blosc/frame.c 2026-09-10 11:48:50.000000000 +0200 +++ new/c-blosc2-3.3.5/blosc/frame.c 2026-09-24 11:35:30.000000000 +0200 @@ -3434,6 +3434,10 @@ if (offset < 0) { // Special value + if (chunksize <= 0) { + BLOSC_TRACE_ERROR("Cannot synthesize special chunk with chunksize <= 0."); + return BLOSC2_ERROR_INVALID_HEADER; + } chunk_cbytes = BLOSC_EXTENDED_HEADER_LENGTH; int32_t chunksize_ = chunksize; if ((nchunk == nchunks - 1) && (nbytes % chunksize)) { @@ -3588,6 +3592,10 @@ if (offset < 0) { // Special value + if (chunksize <= 0) { + BLOSC_TRACE_ERROR("Cannot synthesize special chunk with chunksize <= 0."); + return BLOSC2_ERROR_INVALID_HEADER; + } lazychunk_cbytes = BLOSC_EXTENDED_HEADER_LENGTH; int32_t chunksize_ = chunksize; if ((nchunk == nchunks - 1) && (nbytes % chunksize)) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/c-blosc2-3.3.4/include/blosc2.h new/c-blosc2-3.3.5/include/blosc2.h --- old/c-blosc2-3.3.4/include/blosc2.h 2026-09-10 11:48:50.000000000 +0200 +++ new/c-blosc2-3.3.5/include/blosc2.h 2026-09-24 11:35:30.000000000 +0200 @@ -83,10 +83,10 @@ /* Version numbers */ #define BLOSC2_VERSION_MAJOR 3 /* for major interface/format changes */ #define BLOSC2_VERSION_MINOR 3 /* for minor interface/format changes */ -#define BLOSC2_VERSION_RELEASE 4 /* for tweaks, bug-fixes, or development */ +#define BLOSC2_VERSION_RELEASE 5 /* for tweaks, bug-fixes, or development */ -#define BLOSC2_VERSION_STRING "3.3.4" /* string version. Sync with above! */ -#define BLOSC2_VERSION_DATE "$Date:: 2026-09-10 #$" /* date version year-month-day */ +#define BLOSC2_VERSION_STRING "3.3.5" /* string version. Sync with above! */ +#define BLOSC2_VERSION_DATE "$Date:: 2026-09-24 #$" /* date version year-month-day */ /* Tracing macros */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/c-blosc2-3.3.4/plugins/codecs/zfp/blosc2-zfp.c new/c-blosc2-3.3.5/plugins/codecs/zfp/blosc2-zfp.c --- old/c-blosc2-3.3.4/plugins/codecs/zfp/blosc2-zfp.c 2026-09-10 11:48:50.000000000 +0200 +++ new/c-blosc2-3.3.5/plugins/codecs/zfp/blosc2-zfp.c 2026-09-24 11:35:30.000000000 +0200 @@ -12,7 +12,9 @@ #include "b2nd.h" #include <assert.h> +#include <limits.h> #include <math.h> +#include <stdint.h> #include <stdlib.h> #include <string.h> @@ -313,6 +315,23 @@ return BLOSC2_ERROR_FAILURE; } + size_t blocks = zfp_field_blocks(field); + size_t min_bytes = (blocks + CHAR_BIT - 1) / CHAR_BIT; + if (min_bytes < sizeof(uint64_t)) { + min_bytes = sizeof(uint64_t); + } + if (input_len < (int32_t) min_bytes) { + BLOSC_TRACE_ERROR("ZFP acc: input too small (%d bytes) for the required " + "bitstream size (%zu bytes)", input_len, min_bytes); + zfp_field_free(field); + zfp_stream_close(zfp); + stream_close(stream); + free(shape); + free(chunkshape); + free(blockshape); + return BLOSC2_ERROR_FAILURE; + } + zfpsize = zfp_decompress(zfp, field); /* clean up */ @@ -613,6 +632,23 @@ return BLOSC2_ERROR_FAILURE; } + size_t blocks = zfp_field_blocks(field); + size_t min_bytes = (blocks + CHAR_BIT - 1) / CHAR_BIT; + if (min_bytes < sizeof(uint64_t)) { + min_bytes = sizeof(uint64_t); + } + if (input_len < (int32_t) min_bytes) { + BLOSC_TRACE_ERROR("ZFP prec: input too small (%d bytes) for the required " + "bitstream size (%zu bytes)", input_len, min_bytes); + zfp_field_free(field); + zfp_stream_close(zfp); + stream_close(stream); + free(shape); + free(chunkshape); + free(blockshape); + return BLOSC2_ERROR_FAILURE; + } + zfpsize = zfp_decompress(zfp, field); /* clean up */ @@ -877,6 +913,50 @@ return BLOSC2_ERROR_FAILURE; } + size_t blocks = zfp_field_blocks(field); + uint n = 1u << (2 * ndim); + uint bits = (uint) floor(n * rate + 0.5); + switch (type) { + case zfp_type_float: + if (bits < 1 + 8u) { + bits = 1 + 8u; + } + break; + case zfp_type_double: + if (bits < 1 + 11u) { + bits = 1 + 11u; + } + break; + default: + break; + } + if (bits > 0 && blocks > SIZE_MAX / bits) { + BLOSC_TRACE_ERROR("ZFP rate: required bits overflow size_t"); + zfp_field_free(field); + zfp_stream_close(zfp); + stream_close(stream); + free(shape); + free(chunkshape); + free(blockshape); + return BLOSC2_ERROR_FAILURE; + } + size_t required_bits = blocks * (size_t) bits; + size_t required_bytes = (required_bits + CHAR_BIT - 1) / CHAR_BIT; + if (required_bytes < sizeof(uint64_t)) { + required_bytes = sizeof(uint64_t); + } + if (input_len < (int32_t) required_bytes) { + BLOSC_TRACE_ERROR("ZFP rate: input too small (%d bytes) for the required " + "bitstream size (%zu bytes)", input_len, required_bytes); + zfp_field_free(field); + zfp_stream_close(zfp); + stream_close(stream); + free(shape); + free(chunkshape); + free(blockshape); + return BLOSC2_ERROR_FAILURE; + } + zfpsize = zfp_decompress(zfp, field); /* clean up */
