mirror of
https://github.com/ianlancetaylor/libbacktrace.git
synced 2026-09-07 12:17:06 +08:00
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:
@@ -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,12 +4423,18 @@ 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)
|
||||
{
|
||||
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 (!single_segment)
|
||||
{
|
||||
/* 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++;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (unlikely (pin + 1 >= pinend))
|
||||
|
||||
+28
-3
@@ -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])
|
||||
|
||||
Reference in New Issue
Block a user