https://gcc.gnu.org/g:ffe4c314b15510b97cc389bead5de8ab95cff204
commit r17-1933-gffe4c314b15510b97cc389bead5de8ab95cff204 Author: Ian Lance Taylor <[email protected]> Date: Sat Jun 27 08:46:14 2026 -0700 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. Diff: --- libbacktrace/elf.c | 32 ++++++++++++++++++++++++-------- libbacktrace/zstdtest.c | 31 ++++++++++++++++++++++++++++--- 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/libbacktrace/elf.c b/libbacktrace/elf.c index f3033580e037..0de12bc112e8 100644 --- a/libbacktrace/elf.c +++ b/libbacktrace/elf.c @@ -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)) diff --git a/libbacktrace/zstdtest.c b/libbacktrace/zstdtest.c index 7776c80fc9b3..db8072645b97 100644 --- a/libbacktrace/zstdtest.c +++ b/libbacktrace/zstdtest.c @@ -182,7 +182,32 @@ static const struct zstd_test tests[] = "\xb4\x21\x45\x3b\x10\xe4\x7b\x99\x4d\x8a\x36\x64\x5c\x77\x08\x02" "\xcb\xe0\xce"), 179, - } + }, + { + "window-descriptor", + "hello, world\n", + 0, + ("\x28\xb5\x2f\xfd" + "\x04" /* no Single_Segment_flag; Frame_Content_Size_flag = 0 */ + "\x00" /* Window_Descriptor */ + "\x69\x00\x00" + "\x68\x65\x6c\x6c\x6f\x2c\x20\x77\x6f\x72\x6c\x64\x0a" + "\x4c\x1f\xf9\xf1"), + 26, + }, + { + "window-descriptor-and-content-size", + "hello, world\n", + 0, + ("\x28\xb5\x2f\xfd" + "\x84" /* no Single_Segment_flag; Frame_Content_Size_flag = 2 */ + "\x00" /* Window_Descriptor */ + "\x0d\x00\x00\x00" /* Frame_Content_Size */ + "\x69\x00\x00" + "\x68\x65\x6c\x6c\x6f\x2c\x20\x77\x6f\x72\x6c\x64\x0a" + "\x4c\x1f\xf9\xf1"), + 30, + }, }; /* Test the hand coded samples. */ @@ -217,7 +242,7 @@ test_samples (struct backtrace_state *state) error_callback_compress, NULL, uncompressed, uncompressed_len)) { - fprintf (stderr, "test %s: uncompress failed\n", tests[i].name); + fprintf (stderr, "FAIL: test %s: uncompress failed\n", tests[i].name); ++failures; } else @@ -227,7 +252,7 @@ test_samples (struct backtrace_state *state) { size_t j; - fprintf (stderr, "test %s: uncompressed data mismatch\n", + fprintf (stderr, "FAIL: test %s: uncompressed data mismatch\n", tests[i].name); for (j = 0; j < uncompressed_len; ++j) if (tests[i].uncompressed[j] != uncompressed[j])
