Combine poky (Yocto scarthgap), meta-openembedded (scarthgap), and meta-openwrt into a single repository. Components: - poky/ Yocto core framework (BitBake + OE-Core) - meta-openembedded/ Community layers (meta-oe, meta-python, meta-networking) - meta-openwrt/ OpenWrt customization layer - setup-env.sh One-click build environment setup - README.md Project documentation
334 lines
16 KiB
Diff
334 lines
16 KiB
Diff
From cbce4c2ecf6f5557605890eec125ecfaa4371131 Mon Sep 17 00:00:00 2001
|
|
From: Libo Chen <libo.chen.cn@windriver.com>
|
|
Date: Fri, 30 Jan 2026 16:43:04 +0800
|
|
Subject: [PATCH] Fix CVE-2025-2308 (#5960)
|
|
|
|
A malformed file can cause the scale-offset filter to have too little input data causing a heap buffer overflow. Additional checks on the maximum buffer length are required during the decompression.
|
|
|
|
This PR fixes CVE-2025-2308.
|
|
|
|
CVE: CVE-2025-2308
|
|
|
|
Upstream-Status: Backport [https://github.com/HDFGroup/hdf5/commit/2ce7fdc4cf147d280aa6d49686297faacc250e40]
|
|
|
|
Signed-off-by: Libo Chen <libo.chen.cn@windriver.com>
|
|
---
|
|
src/H5Zscaleoffset.c | 177 ++--
|
|
src/H5Zscaleoffset.c.orig | 1781 +++++++++++++++++++++++++++++++++++++
|
|
1 files changed, 105 insertions(+), 72 deletions(-)
|
|
create mode 100644 src/H5Zscaleoffset.c.orig
|
|
|
|
diff --git a/src/H5Zscaleoffset.c b/src/H5Zscaleoffset.c
|
|
index fbf12d6..8355b13 100644
|
|
--- a/src/H5Zscaleoffset.c
|
|
+++ b/src/H5Zscaleoffset.c
|
|
@@ -69,21 +69,22 @@ static herr_t H5Z__scaleoffset_precompress_fd(void *data, unsigned d_nelmts, enu
|
|
static herr_t H5Z__scaleoffset_postdecompress_fd(void *data, unsigned d_nelmts, enum H5Z_scaleoffset_t type,
|
|
unsigned filavail, const unsigned cd_values[],
|
|
uint32_t minbits, unsigned long long minval, double D_val);
|
|
-static void H5Z__scaleoffset_next_byte(size_t *j, unsigned *buf_len);
|
|
-static void H5Z__scaleoffset_decompress_one_byte(unsigned char *data, size_t data_offset, unsigned k,
|
|
- unsigned begin_i, const unsigned char *buffer, size_t *j,
|
|
- unsigned *buf_len, parms_atomic p, unsigned dtype_len);
|
|
+static void H5Z__scaleoffset_next_byte(size_t *j, unsigned *bits_to_fill);
|
|
+static herr_t H5Z__scaleoffset_decompress_one_byte(unsigned char *data, size_t data_offset, unsigned k,
|
|
+ unsigned begin_i, const unsigned char *buffer,
|
|
+ size_t buf_size, size_t *j, unsigned *bits_to_fill,
|
|
+ parms_atomic p, unsigned dtype_len);
|
|
static void H5Z__scaleoffset_compress_one_byte(const unsigned char *data, size_t data_offset, unsigned k,
|
|
unsigned begin_i, unsigned char *buffer, size_t *j,
|
|
- unsigned *buf_len, parms_atomic p, unsigned dtype_len);
|
|
-static void H5Z__scaleoffset_decompress_one_atomic(unsigned char *data, size_t data_offset,
|
|
- unsigned char *buffer, size_t *j, unsigned *buf_len,
|
|
- parms_atomic p);
|
|
+ unsigned *bits_to_fill, parms_atomic p, unsigned dtype_len);
|
|
+static herr_t H5Z__scaleoffset_decompress_one_atomic(unsigned char *data, size_t data_offset,
|
|
+ unsigned char *buffer, size_t buf_size, size_t *j,
|
|
+ unsigned *bits_to_fill, parms_atomic p);
|
|
static void H5Z__scaleoffset_compress_one_atomic(unsigned char *data, size_t data_offset,
|
|
- unsigned char *buffer, size_t *j, unsigned *buf_len,
|
|
+ unsigned char *buffer, size_t *j, unsigned *bits_to_fill,
|
|
parms_atomic p);
|
|
-static void H5Z__scaleoffset_decompress(unsigned char *data, unsigned d_nelmts, unsigned char *buffer,
|
|
- parms_atomic p);
|
|
+static herr_t H5Z__scaleoffset_decompress(unsigned char *data, unsigned d_nelmts, unsigned char *buffer,
|
|
+ size_t buf_size, parms_atomic p);
|
|
static void H5Z__scaleoffset_compress(unsigned char *data, unsigned d_nelmts, unsigned char *buffer,
|
|
size_t buffer_size, parms_atomic p);
|
|
|
|
@@ -1261,8 +1262,11 @@ H5Z__filter_scaleoffset(unsigned flags, size_t cd_nelmts, const unsigned cd_valu
|
|
}
|
|
|
|
/* decompress the buffer if minbits not equal to zero */
|
|
- if (minbits != 0)
|
|
- H5Z__scaleoffset_decompress(outbuf, d_nelmts, (unsigned char *)(*buf) + buf_offset, p);
|
|
+ if (minbits != 0) {
|
|
+ if (H5Z__scaleoffset_decompress(outbuf, d_nelmts, (unsigned char *)(*buf) + buf_offset,
|
|
+ *buf_size - buf_offset, p))
|
|
+ HGOTO_ERROR(H5E_PLINE, H5E_BADVALUE, 0, "Scaleoffset decompression failed");
|
|
+ }
|
|
else {
|
|
/* fill value is not defined and all data elements have the same value */
|
|
for (i = 0; i < size_out; i++)
|
|
@@ -1603,55 +1607,69 @@ done:
|
|
}
|
|
|
|
static void
|
|
-H5Z__scaleoffset_next_byte(size_t *j, unsigned *buf_len)
|
|
+H5Z__scaleoffset_next_byte(size_t *j, unsigned *bits_to_fill)
|
|
{
|
|
++(*j);
|
|
- *buf_len = 8 * sizeof(unsigned char);
|
|
+ *bits_to_fill = 8 * sizeof(unsigned char);
|
|
}
|
|
|
|
-static void
|
|
+static herr_t
|
|
H5Z__scaleoffset_decompress_one_byte(unsigned char *data, size_t data_offset, unsigned k, unsigned begin_i,
|
|
- const unsigned char *buffer, size_t *j, unsigned *buf_len,
|
|
- parms_atomic p, unsigned dtype_len)
|
|
+ const unsigned char *buffer, size_t buf_size, size_t *j,
|
|
+ unsigned *bits_to_fill, parms_atomic p, unsigned dtype_len)
|
|
{
|
|
- unsigned dat_len; /* dat_len is the number of bits to be copied in each data byte */
|
|
- unsigned char val; /* value to be copied in each data byte */
|
|
+ unsigned bits_to_copy; /* bits_to_copy is the number of bits to be copied in each data byte */
|
|
+ unsigned char val; /* value to be copied in each data byte */
|
|
+ herr_t ret_value = SUCCEED; /* Return value */
|
|
+
|
|
+ FUNC_ENTER_PACKAGE
|
|
+
|
|
+ if (*j >= buf_size)
|
|
+ HGOTO_ERROR(H5E_PLINE, H5E_BADVALUE, 0, "Buffer too short");
|
|
|
|
/* initialize value and bits of unsigned char to be copied */
|
|
val = buffer[*j];
|
|
if (k == begin_i)
|
|
- dat_len = 8 - (dtype_len - p.minbits) % 8;
|
|
+ bits_to_copy = 8 - (dtype_len - p.minbits) % 8;
|
|
else
|
|
- dat_len = 8;
|
|
+ bits_to_copy = 8;
|
|
|
|
- if (*buf_len > dat_len) {
|
|
- data[data_offset + k] =
|
|
- (unsigned char)((unsigned)(val >> (*buf_len - dat_len)) & (unsigned)(~((unsigned)~0 << dat_len)));
|
|
- *buf_len -= dat_len;
|
|
+ if (*bits_to_fill > bits_to_copy) {
|
|
+ data[data_offset + k] = (unsigned char)((unsigned)(val >> (*bits_to_fill - bits_to_copy)) &
|
|
+ (unsigned)(~((unsigned)~0 << bits_to_copy)));
|
|
+ *bits_to_fill -= bits_to_copy;
|
|
} /* end if */
|
|
else {
|
|
data[data_offset + k] =
|
|
- (unsigned char)((val & ~((unsigned)(~0) << *buf_len)) << (dat_len - *buf_len));
|
|
- dat_len -= *buf_len;
|
|
- H5Z__scaleoffset_next_byte(j, buf_len);
|
|
- if (dat_len == 0)
|
|
- return;
|
|
+ (unsigned char)((val & ~((unsigned)(~0) << *bits_to_fill)) << (bits_to_copy - *bits_to_fill));
|
|
+ bits_to_copy -= *bits_to_fill;
|
|
+ H5Z__scaleoffset_next_byte(j, bits_to_fill);
|
|
+ if (bits_to_copy == 0)
|
|
+ goto done;
|
|
+ else if (*j >= buf_size)
|
|
+ HGOTO_ERROR(H5E_PLINE, H5E_BADVALUE, 0, "Buffer too short");
|
|
|
|
val = buffer[*j];
|
|
- data[data_offset + k] |=
|
|
- (unsigned char)((unsigned)(val >> (*buf_len - dat_len)) & ~((unsigned)(~0) << dat_len));
|
|
- *buf_len -= dat_len;
|
|
+ data[data_offset + k] |= (unsigned char)((unsigned)(val >> (*bits_to_fill - bits_to_copy)) &
|
|
+ ~((unsigned)(~0) << bits_to_copy));
|
|
+ *bits_to_fill -= bits_to_copy;
|
|
} /* end else */
|
|
+
|
|
+done:
|
|
+ FUNC_LEAVE_NOAPI(ret_value)
|
|
}
|
|
|
|
-static void
|
|
+static herr_t
|
|
H5Z__scaleoffset_decompress_one_atomic(unsigned char *data, size_t data_offset, unsigned char *buffer,
|
|
- size_t *j, unsigned *buf_len, parms_atomic p)
|
|
+ size_t buf_size, size_t *j, unsigned *bits_to_fill, parms_atomic p)
|
|
{
|
|
/* begin_i: the index of byte having first significant bit */
|
|
unsigned begin_i;
|
|
unsigned dtype_len;
|
|
int k;
|
|
+ herr_t ret_value = SUCCEED; /* Return value */
|
|
+
|
|
+ FUNC_ENTER_PACKAGE
|
|
|
|
assert(p.minbits > 0);
|
|
|
|
@@ -1661,8 +1679,9 @@ H5Z__scaleoffset_decompress_one_atomic(unsigned char *data, size_t data_offset,
|
|
begin_i = p.size - 1 - (dtype_len - p.minbits) / 8;
|
|
|
|
for (k = (int)begin_i; k >= 0; k--)
|
|
- H5Z__scaleoffset_decompress_one_byte(data, data_offset, (unsigned)k, begin_i, buffer, j, buf_len,
|
|
- p, dtype_len);
|
|
+ if (H5Z__scaleoffset_decompress_one_byte(data, data_offset, (unsigned)k, begin_i, buffer,
|
|
+ buf_size, j, bits_to_fill, p, dtype_len))
|
|
+ HGOTO_ERROR(H5E_PLINE, H5E_BADVALUE, 0, "Atomic decompression failed");
|
|
}
|
|
else { /* big endian */
|
|
assert(p.mem_order == H5Z_SCALEOFFSET_ORDER_BE);
|
|
@@ -1670,67 +1689,81 @@ H5Z__scaleoffset_decompress_one_atomic(unsigned char *data, size_t data_offset,
|
|
begin_i = (dtype_len - p.minbits) / 8;
|
|
|
|
for (k = (int)begin_i; k <= (int)(p.size - 1); k++)
|
|
- H5Z__scaleoffset_decompress_one_byte(data, data_offset, (unsigned)k, begin_i, buffer, j, buf_len,
|
|
- p, dtype_len);
|
|
+ if (H5Z__scaleoffset_decompress_one_byte(data, data_offset, (unsigned)k, begin_i, buffer,
|
|
+ buf_size, j, bits_to_fill, p, dtype_len))
|
|
+ HGOTO_ERROR(H5E_PLINE, H5E_BADVALUE, 0, "Atomic decompression failed");
|
|
}
|
|
+
|
|
+done:
|
|
+ FUNC_LEAVE_NOAPI(ret_value)
|
|
}
|
|
|
|
-static void
|
|
-H5Z__scaleoffset_decompress(unsigned char *data, unsigned d_nelmts, unsigned char *buffer, parms_atomic p)
|
|
+static herr_t
|
|
+H5Z__scaleoffset_decompress(unsigned char *data, unsigned d_nelmts, unsigned char *buffer, size_t buf_size,
|
|
+ parms_atomic p)
|
|
{
|
|
/* i: index of data, j: index of buffer,
|
|
- buf_len: number of bits to be filled in current byte */
|
|
+ bits_to_fill: number of bits to be filled in current byte */
|
|
size_t i, j;
|
|
- unsigned buf_len;
|
|
+ unsigned bits_to_fill;
|
|
+ herr_t ret_value = SUCCEED; /* Return value */
|
|
+
|
|
+ FUNC_ENTER_PACKAGE
|
|
|
|
/* must initialize to zeros */
|
|
for (i = 0; i < d_nelmts * (size_t)p.size; i++)
|
|
data[i] = 0;
|
|
|
|
/* initialization before the loop */
|
|
- j = 0;
|
|
- buf_len = sizeof(unsigned char) * 8;
|
|
+ j = 0;
|
|
+ bits_to_fill = sizeof(unsigned char) * 8;
|
|
|
|
/* decompress */
|
|
for (i = 0; i < d_nelmts; i++)
|
|
- H5Z__scaleoffset_decompress_one_atomic(data, i * p.size, buffer, &j, &buf_len, p);
|
|
+ if (H5Z__scaleoffset_decompress_one_atomic(data, i * p.size, buffer, buf_size, &j, &bits_to_fill, p))
|
|
+ HGOTO_ERROR(H5E_PLINE, H5E_BADVALUE, 0, "Scaleoffset decompression failed");
|
|
+
|
|
+done:
|
|
+ FUNC_LEAVE_NOAPI(ret_value)
|
|
}
|
|
|
|
static void
|
|
H5Z__scaleoffset_compress_one_byte(const unsigned char *data, size_t data_offset, unsigned k,
|
|
- unsigned begin_i, unsigned char *buffer, size_t *j, unsigned *buf_len,
|
|
+ unsigned begin_i, unsigned char *buffer, size_t *j, unsigned *bits_to_fill,
|
|
parms_atomic p, unsigned dtype_len)
|
|
{
|
|
- unsigned dat_len; /* dat_len is the number of bits to be copied in each data byte */
|
|
- unsigned char val; /* value to be copied in each data byte */
|
|
+ unsigned bits_to_copy; /* bits_to_copy is the number of bits to be copied in each data byte */
|
|
+ unsigned char val; /* value to be copied in each data byte */
|
|
|
|
/* initialize value and bits of unsigned char to be copied */
|
|
val = data[data_offset + k];
|
|
if (k == begin_i)
|
|
- dat_len = 8 - (dtype_len - p.minbits) % 8;
|
|
+ bits_to_copy = 8 - (dtype_len - p.minbits) % 8;
|
|
else
|
|
- dat_len = 8;
|
|
+ bits_to_copy = 8;
|
|
|
|
- if (*buf_len > dat_len) {
|
|
- buffer[*j] |= (unsigned char)((val & ~((unsigned)(~0) << dat_len)) << (*buf_len - dat_len));
|
|
- *buf_len -= dat_len;
|
|
+ if (*bits_to_fill > bits_to_copy) {
|
|
+ buffer[*j] |=
|
|
+ (unsigned char)((val & ~((unsigned)(~0) << bits_to_copy)) << (*bits_to_fill - bits_to_copy));
|
|
+ *bits_to_fill -= bits_to_copy;
|
|
}
|
|
else {
|
|
- buffer[*j] |=
|
|
- (unsigned char)((unsigned)(val >> (dat_len - *buf_len)) & ~((unsigned)(~0) << *buf_len));
|
|
- dat_len -= *buf_len;
|
|
- H5Z__scaleoffset_next_byte(j, buf_len);
|
|
- if (dat_len == 0)
|
|
+ buffer[*j] |= (unsigned char)((unsigned)(val >> (bits_to_copy - *bits_to_fill)) &
|
|
+ ~((unsigned)(~0) << *bits_to_fill));
|
|
+ bits_to_copy -= *bits_to_fill;
|
|
+ H5Z__scaleoffset_next_byte(j, bits_to_fill);
|
|
+ if (bits_to_copy == 0)
|
|
return;
|
|
|
|
- buffer[*j] = (unsigned char)((val & ~((unsigned)(~0) << dat_len)) << (*buf_len - dat_len));
|
|
- *buf_len -= dat_len;
|
|
+ buffer[*j] =
|
|
+ (unsigned char)((val & ~((unsigned)(~0) << bits_to_copy)) << (*bits_to_fill - bits_to_copy));
|
|
+ *bits_to_fill -= bits_to_copy;
|
|
} /* end else */
|
|
}
|
|
|
|
static void
|
|
H5Z__scaleoffset_compress_one_atomic(unsigned char *data, size_t data_offset, unsigned char *buffer,
|
|
- size_t *j, unsigned *buf_len, parms_atomic p)
|
|
+ size_t *j, unsigned *bits_to_fill, parms_atomic p)
|
|
{
|
|
/* begin_i: the index of byte having first significant bit */
|
|
unsigned begin_i;
|
|
@@ -1745,16 +1778,16 @@ H5Z__scaleoffset_compress_one_atomic(unsigned char *data, size_t data_offset, un
|
|
begin_i = p.size - 1 - (dtype_len - p.minbits) / 8;
|
|
|
|
for (k = (int)begin_i; k >= 0; k--)
|
|
- H5Z__scaleoffset_compress_one_byte(data, data_offset, (unsigned)k, begin_i, buffer, j, buf_len, p,
|
|
- dtype_len);
|
|
+ H5Z__scaleoffset_compress_one_byte(data, data_offset, (unsigned)k, begin_i, buffer, j,
|
|
+ bits_to_fill, p, dtype_len);
|
|
}
|
|
else { /* big endian */
|
|
assert(p.mem_order == H5Z_SCALEOFFSET_ORDER_BE);
|
|
begin_i = (dtype_len - p.minbits) / 8;
|
|
|
|
for (k = (int)begin_i; k <= (int)(p.size - 1); k++)
|
|
- H5Z__scaleoffset_compress_one_byte(data, data_offset, (unsigned)k, begin_i, buffer, j, buf_len, p,
|
|
- dtype_len);
|
|
+ H5Z__scaleoffset_compress_one_byte(data, data_offset, (unsigned)k, begin_i, buffer, j,
|
|
+ bits_to_fill, p, dtype_len);
|
|
}
|
|
}
|
|
|
|
@@ -1763,19 +1796,19 @@ H5Z__scaleoffset_compress(unsigned char *data, unsigned d_nelmts, unsigned char
|
|
parms_atomic p)
|
|
{
|
|
/* i: index of data, j: index of buffer,
|
|
- buf_len: number of bits to be filled in current byte */
|
|
+ bits_to_fill: number of bits to be filled in current byte */
|
|
size_t i, j;
|
|
- unsigned buf_len;
|
|
+ unsigned bits_to_fill;
|
|
|
|
/* must initialize buffer to be zeros */
|
|
for (j = 0; j < buffer_size; j++)
|
|
buffer[j] = 0;
|
|
|
|
/* initialization before the loop */
|
|
- j = 0;
|
|
- buf_len = sizeof(unsigned char) * 8;
|
|
+ j = 0;
|
|
+ bits_to_fill = sizeof(unsigned char) * 8;
|
|
|
|
/* compress */
|
|
for (i = 0; i < d_nelmts; i++)
|
|
- H5Z__scaleoffset_compress_one_atomic(data, i * p.size, buffer, &j, &buf_len, p);
|
|
+ H5Z__scaleoffset_compress_one_atomic(data, i * p.size, buffer, &j, &bits_to_fill, p);
|
|
}
|
|
--
|
|
2.34.1
|
|
|