libbacktrace: support window size in zstd decompression

Reportedly this occurs on AerynOS.

Patch from Ivan Molodetskikh.

	* elf.c (elf_zstd_decompress_frame): Support a compressed block
	that does not set the single segment flag.
	* zstdtest.c (tests): Add tests without single segment.
This commit is contained in:
Ian Lance Taylor
2026-06-27 08:53:22 -07:00
parent 549b81b43b
commit 058d953bb7
2 changed files with 52 additions and 11 deletions
+24 -8
View File
@@ -4364,6 +4364,7 @@ elf_zstd_decompress_frame (const unsigned char **ppin,
uint32_t repeated_offset3;
uint16_t *scratch;
unsigned char hdr;
int single_segment;
int has_checksum;
uint64_t content_size;
int last_block;
@@ -4422,11 +4423,17 @@ elf_zstd_decompress_frame (const unsigned char **ppin,
hdr = *pin++;
/* We expect a single frame. */
if (unlikely ((hdr & (1 << 5)) == 0))
single_segment = (hdr & (1 << 5)) != 0;
if (!single_segment)
{
elf_uncompress_failed ();
return 0;
if (unlikely (pin >= pinend))
{
elf_uncompress_failed ();
return 0;
}
/* We have all the data in memory, so we can ignore the window
size. */
pin++;
}
/* Reserved bit must be zero. */
if (unlikely ((hdr & (1 << 3)) != 0))
@@ -4444,12 +4451,21 @@ elf_zstd_decompress_frame (const unsigned char **ppin,
switch (hdr >> 6)
{
case 0:
if (unlikely (pin >= pinend))
if (!single_segment)
{
elf_uncompress_failed ();
return 0;
/* The content_size is not specified, but we know it from the
section header. */
content_size = (uint64_t) sout;
}
else
{
if (unlikely (pin >= pinend))
{
elf_uncompress_failed ();
return 0;
}
content_size = (uint64_t) *pin++;
}
content_size = (uint64_t) *pin++;
break;
case 1:
if (unlikely (pin + 1 >= pinend))