/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <inttypes.h>
+#include <malloc.h>
#include <stdlib.h>
#include <sys/mman.h>
-#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/types.h>
#include <unistd.h>
#if HAVE_XZ
#endif
}
-int decompress_blob_xz(const void *src, uint64_t src_size,
- void **dst, size_t *dst_alloc_size, size_t* dst_size, size_t dst_max) {
+int decompress_blob_xz(
+ const void *src,
+ uint64_t src_size,
+ void **dst,
+ size_t* dst_size,
+ size_t dst_max) {
#if HAVE_XZ
_cleanup_(lzma_end) lzma_stream s = LZMA_STREAM_INIT;
assert(src);
assert(src_size > 0);
assert(dst);
- assert(dst_alloc_size);
assert(dst_size);
- assert(*dst_alloc_size == 0 || *dst);
ret = lzma_stream_decoder(&s, UINT64_MAX, 0);
if (ret != LZMA_OK)
return -ENOMEM;
space = MIN(src_size * 2, dst_max ?: SIZE_MAX);
- if (!greedy_realloc(dst, dst_alloc_size, space, 1))
+ if (!greedy_realloc(dst, space, 1))
return -ENOMEM;
s.next_in = src;
used = space - s.avail_out;
space = MIN(2 * space, dst_max ?: SIZE_MAX);
- if (!greedy_realloc(dst, dst_alloc_size, space, 1))
+ if (!greedy_realloc(dst, space, 1))
return -ENOMEM;
s.avail_out = space - used;
#endif
}
-int decompress_blob_lz4(const void *src, uint64_t src_size,
- void **dst, size_t *dst_alloc_size, size_t* dst_size, size_t dst_max) {
+int decompress_blob_lz4(
+ const void *src,
+ uint64_t src_size,
+ void **dst,
+ size_t* dst_size,
+ size_t dst_max) {
#if HAVE_LZ4
char* out;
assert(src);
assert(src_size > 0);
assert(dst);
- assert(dst_alloc_size);
assert(dst_size);
- assert(*dst_alloc_size == 0 || *dst);
if (src_size <= 8)
return -EBADMSG;
size = unaligned_read_le64(src);
if (size < 0 || (unsigned) size != unaligned_read_le64(src))
return -EFBIG;
- if ((size_t) size > *dst_alloc_size) {
- out = realloc(*dst, size);
- if (!out)
- return -ENOMEM;
- *dst = out;
- *dst_alloc_size = size;
- } else
- out = *dst;
+ out = greedy_realloc(dst, size, 1);
+ if (!out)
+ return -ENOMEM;
r = LZ4_decompress_safe((char*)src + 8, out, src_size - 8, size);
if (r < 0 || r != size)
}
int decompress_blob_zstd(
- const void *src, uint64_t src_size,
- void **dst, size_t *dst_alloc_size, size_t *dst_size, size_t dst_max) {
+ const void *src,
+ uint64_t src_size,
+ void **dst,
+ size_t *dst_size,
+ size_t dst_max) {
#if HAVE_ZSTD
uint64_t size;
assert(src);
assert(src_size > 0);
assert(dst);
- assert(dst_alloc_size);
assert(dst_size);
- assert(*dst_alloc_size == 0 || *dst);
size = ZSTD_getFrameContentSize(src, src_size);
if (IN_SET(size, ZSTD_CONTENTSIZE_ERROR, ZSTD_CONTENTSIZE_UNKNOWN))
if (size > SIZE_MAX)
return -E2BIG;
- if (!(greedy_realloc(dst, dst_alloc_size, MAX(ZSTD_DStreamOutSize(), size), 1)))
+ if (!(greedy_realloc(dst, MAX(ZSTD_DStreamOutSize(), size), 1)))
return -ENOMEM;
_cleanup_(ZSTD_freeDCtxp) ZSTD_DCtx *dctx = ZSTD_createDCtx();
};
ZSTD_outBuffer output = {
.dst = *dst,
- .size = *dst_alloc_size,
+ .size = MALLOC_SIZEOF_SAFE(*dst),
};
size_t k = ZSTD_decompressStream(dctx, &output, &input);
int decompress_blob(
int compression,
- const void *src, uint64_t src_size,
- void **dst, size_t *dst_alloc_size, size_t* dst_size, size_t dst_max) {
+ const void *src,
+ uint64_t src_size,
+ void **dst,
+ size_t* dst_size,
+ size_t dst_max) {
if (compression == OBJECT_COMPRESSED_XZ)
return decompress_blob_xz(
src, src_size,
- dst, dst_alloc_size, dst_size, dst_max);
+ dst, dst_size, dst_max);
else if (compression == OBJECT_COMPRESSED_LZ4)
return decompress_blob_lz4(
src, src_size,
- dst, dst_alloc_size, dst_size, dst_max);
+ dst, dst_size, dst_max);
else if (compression == OBJECT_COMPRESSED_ZSTD)
return decompress_blob_zstd(
src, src_size,
- dst, dst_alloc_size, dst_size, dst_max);
+ dst, dst_size, dst_max);
else
return -EPROTONOSUPPORT;
}
-int decompress_startswith_xz(const void *src, uint64_t src_size,
- void **buffer, size_t *buffer_size,
- const void *prefix, size_t prefix_len,
- uint8_t extra) {
+int decompress_startswith_xz(
+ const void *src,
+ uint64_t src_size,
+ void **buffer,
+ const void *prefix,
+ size_t prefix_len,
+ uint8_t extra) {
#if HAVE_XZ
_cleanup_(lzma_end) lzma_stream s = LZMA_STREAM_INIT;
+ size_t allocated;
lzma_ret ret;
- /* Checks whether the decompressed blob starts with the
- * mentioned prefix. The byte extra needs to follow the
- * prefix */
+ /* Checks whether the decompressed blob starts with the mentioned prefix. The byte extra needs to
+ * follow the prefix */
assert(src);
assert(src_size > 0);
assert(buffer);
- assert(buffer_size);
assert(prefix);
- assert(*buffer_size == 0 || *buffer);
ret = lzma_stream_decoder(&s, UINT64_MAX, 0);
if (ret != LZMA_OK)
return -EBADMSG;
- if (!(greedy_realloc(buffer, buffer_size, ALIGN_8(prefix_len + 1), 1)))
+ if (!(greedy_realloc(buffer, ALIGN_8(prefix_len + 1), 1)))
return -ENOMEM;
+ allocated = MALLOC_SIZEOF_SAFE(*buffer);
+
s.next_in = src;
s.avail_in = src_size;
s.next_out = *buffer;
- s.avail_out = *buffer_size;
+ s.avail_out = allocated;
for (;;) {
ret = lzma_code(&s, LZMA_FINISH);
if (!IN_SET(ret, LZMA_OK, LZMA_STREAM_END))
return -EBADMSG;
- if (*buffer_size - s.avail_out >= prefix_len + 1)
+ if (allocated - s.avail_out >= prefix_len + 1)
return memcmp(*buffer, prefix, prefix_len) == 0 &&
((const uint8_t*) *buffer)[prefix_len] == extra;
if (ret == LZMA_STREAM_END)
return 0;
- s.avail_out += *buffer_size;
+ s.avail_out += allocated;
- if (!(greedy_realloc(buffer, buffer_size, *buffer_size * 2, 1)))
+ if (!(greedy_realloc(buffer, allocated * 2, 1)))
return -ENOMEM;
- s.next_out = *(uint8_t**)buffer + *buffer_size - s.avail_out;
+ allocated = MALLOC_SIZEOF_SAFE(*buffer);
+ s.next_out = *(uint8_t**)buffer + allocated - s.avail_out;
}
#else
#endif
}
-int decompress_startswith_lz4(const void *src, uint64_t src_size,
- void **buffer, size_t *buffer_size,
- const void *prefix, size_t prefix_len,
- uint8_t extra) {
+int decompress_startswith_lz4(
+ const void *src,
+ uint64_t src_size,
+ void **buffer,
+ const void *prefix,
+ size_t prefix_len,
+ uint8_t extra) {
+
#if HAVE_LZ4
- /* Checks whether the decompressed blob starts with the
- * mentioned prefix. The byte extra needs to follow the
- * prefix */
+ /* Checks whether the decompressed blob starts with the mentioned prefix. The byte extra needs to
+ * follow the prefix */
+ size_t allocated;
int r;
assert(src);
assert(src_size > 0);
assert(buffer);
- assert(buffer_size);
assert(prefix);
- assert(*buffer_size == 0 || *buffer);
if (src_size <= 8)
return -EBADMSG;
- if (!(greedy_realloc(buffer, buffer_size, ALIGN_8(prefix_len + 1), 1)))
+ if (!(greedy_realloc(buffer, ALIGN_8(prefix_len + 1), 1)))
return -ENOMEM;
-
- r = LZ4_decompress_safe_partial((char*)src + 8, *buffer, src_size - 8,
- prefix_len + 1, *buffer_size);
- /* One lz4 < 1.8.3, we might get "failure" (r < 0), or "success" where
- * just a part of the buffer is decompressed. But if we get a smaller
- * amount of bytes than requested, we don't know whether there isn't enough
- * data to fill the requested size or whether we just got a partial answer.
+ allocated = MALLOC_SIZEOF_SAFE(*buffer);
+
+ r = LZ4_decompress_safe_partial(
+ (char*)src + 8,
+ *buffer,
+ src_size - 8,
+ prefix_len + 1,
+ allocated);
+
+ /* One lz4 < 1.8.3, we might get "failure" (r < 0), or "success" where just a part of the buffer is
+ * decompressed. But if we get a smaller amount of bytes than requested, we don't know whether there
+ * isn't enough data to fill the requested size or whether we just got a partial answer.
*/
if (r < 0 || (size_t) r < prefix_len + 1) {
size_t size;
/* Before version 1.8.3, lz4 always tries to decode full a "sequence",
* so in pathological cases might need to decompress the full field. */
- r = decompress_blob_lz4(src, src_size, buffer, buffer_size, &size, 0);
+ r = decompress_blob_lz4(src, src_size, buffer, &size, 0);
if (r < 0)
return r;
}
int decompress_startswith_zstd(
- const void *src, uint64_t src_size,
- void **buffer, size_t *buffer_size,
- const void *prefix, size_t prefix_len,
+ const void *src,
+ uint64_t src_size,
+ void **buffer,
+ const void *prefix,
+ size_t prefix_len,
uint8_t extra) {
#if HAVE_ZSTD
assert(src);
assert(src_size > 0);
assert(buffer);
- assert(buffer_size);
assert(prefix);
- assert(*buffer_size == 0 || *buffer);
uint64_t size = ZSTD_getFrameContentSize(src, src_size);
if (IN_SET(size, ZSTD_CONTENTSIZE_ERROR, ZSTD_CONTENTSIZE_UNKNOWN))
if (!dctx)
return -ENOMEM;
- if (!(greedy_realloc(buffer, buffer_size, MAX(ZSTD_DStreamOutSize(), prefix_len + 1), 1)))
+ if (!(greedy_realloc(buffer, MAX(ZSTD_DStreamOutSize(), prefix_len + 1), 1)))
return -ENOMEM;
ZSTD_inBuffer input = {
};
ZSTD_outBuffer output = {
.dst = *buffer,
- .size = *buffer_size,
+ .size = MALLOC_SIZEOF_SAFE(*buffer),
};
size_t k;
int decompress_startswith(
int compression,
- const void *src, uint64_t src_size,
- void **buffer, size_t *buffer_size,
- const void *prefix, size_t prefix_len,
+ const void *src,
+ uint64_t src_size,
+ void **buffer,
+ const void *prefix,
+ size_t prefix_len,
uint8_t extra) {
if (compression == OBJECT_COMPRESSED_XZ)
return decompress_startswith_xz(
src, src_size,
- buffer, buffer_size,
+ buffer,
prefix, prefix_len,
extra);
else if (compression == OBJECT_COMPRESSED_LZ4)
return decompress_startswith_lz4(
src, src_size,
- buffer, buffer_size,
+ buffer,
prefix, prefix_len,
extra);
else if (compression == OBJECT_COMPRESSED_ZSTD)
return decompress_startswith_zstd(
src, src_size,
- buffer, buffer_size,
+ buffer,
prefix, prefix_len,
extra);
else