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;
|
uint32_t repeated_offset3;
|
||||||
uint16_t *scratch;
|
uint16_t *scratch;
|
||||||
unsigned char hdr;
|
unsigned char hdr;
|
||||||
|
int single_segment;
|
||||||
int has_checksum;
|
int has_checksum;
|
||||||
uint64_t content_size;
|
uint64_t content_size;
|
||||||
int last_block;
|
int last_block;
|
||||||
@@ -4422,12 +4423,18 @@ elf_zstd_decompress_frame (const unsigned char **ppin,
|
|||||||
|
|
||||||
hdr = *pin++;
|
hdr = *pin++;
|
||||||
|
|
||||||
/* We expect a single frame. */
|
single_segment = (hdr & (1 << 5)) != 0;
|
||||||
if (unlikely ((hdr & (1 << 5)) == 0))
|
if (!single_segment)
|
||||||
|
{
|
||||||
|
if (unlikely (pin >= pinend))
|
||||||
{
|
{
|
||||||
elf_uncompress_failed ();
|
elf_uncompress_failed ();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
/* We have all the data in memory, so we can ignore the window
|
||||||
|
size. */
|
||||||
|
pin++;
|
||||||
|
}
|
||||||
/* Reserved bit must be zero. */
|
/* Reserved bit must be zero. */
|
||||||
if (unlikely ((hdr & (1 << 3)) != 0))
|
if (unlikely ((hdr & (1 << 3)) != 0))
|
||||||
{
|
{
|
||||||
@@ -4444,12 +4451,21 @@ elf_zstd_decompress_frame (const unsigned char **ppin,
|
|||||||
switch (hdr >> 6)
|
switch (hdr >> 6)
|
||||||
{
|
{
|
||||||
case 0:
|
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))
|
if (unlikely (pin >= pinend))
|
||||||
{
|
{
|
||||||
elf_uncompress_failed ();
|
elf_uncompress_failed ();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
content_size = (uint64_t) *pin++;
|
content_size = (uint64_t) *pin++;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (unlikely (pin + 1 >= pinend))
|
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"
|
"\xb4\x21\x45\x3b\x10\xe4\x7b\x99\x4d\x8a\x36\x64\x5c\x77\x08\x02"
|
||||||
"\xcb\xe0\xce"),
|
"\xcb\xe0\xce"),
|
||||||
179,
|
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. */
|
/* Test the hand coded samples. */
|
||||||
@@ -217,7 +242,7 @@ test_samples (struct backtrace_state *state)
|
|||||||
error_callback_compress, NULL,
|
error_callback_compress, NULL,
|
||||||
uncompressed, uncompressed_len))
|
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;
|
++failures;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -227,7 +252,7 @@ test_samples (struct backtrace_state *state)
|
|||||||
{
|
{
|
||||||
size_t j;
|
size_t j;
|
||||||
|
|
||||||
fprintf (stderr, "test %s: uncompressed data mismatch\n",
|
fprintf (stderr, "FAIL: test %s: uncompressed data mismatch\n",
|
||||||
tests[i].name);
|
tests[i].name);
|
||||||
for (j = 0; j < uncompressed_len; ++j)
|
for (j = 0; j < uncompressed_len; ++j)
|
||||||
if (tests[i].uncompressed[j] != uncompressed[j])
|
if (tests[i].uncompressed[j] != uncompressed[j])
|
||||||
|
|||||||
Reference in New Issue
Block a user