libbacktrace: support compressed block with no sequences

* elf.c (elf_zstd_decompress_frame): Support a compressed block
	with no sequences, only literals.

Fixes https://github.com/ianlancetaylor/libbacktrace/issues/164
This commit is contained in:
Ian Lance Taylor
2026-06-01 21:34:27 -07:00
committed by Ivan Molodetskikh
parent 7fbe1d1345
commit 99c13e53bf

View File

@@ -4638,6 +4638,11 @@ elf_zstd_decompress_frame (const unsigned char **ppin,
pin += 2;
}
pback = NULL;
bits = 0;
literal_state = 0;
offset_state = 0;
match_state = 0;
if (seq_count > 0)
{
int (*pfn)(const struct elf_zstd_fse_entry *,
@@ -4677,28 +4682,28 @@ elf_zstd_decompress_frame (const unsigned char **ppin,
match_fse_table, 9, pfn,
&match_decode))
return 0;
pback = pblockend - 1;
if (!elf_fetch_backward_init (&pback, pin, &val, &bits))
return 0;
bits -= literal_decode.table_bits;
literal_state = ((val >> bits)
& ((1U << literal_decode.table_bits) - 1));
if (!elf_fetch_bits_backward (&pback, pin, &val, &bits))
return 0;
bits -= offset_decode.table_bits;
offset_state = ((val >> bits)
& ((1U << offset_decode.table_bits) - 1));
if (!elf_fetch_bits_backward (&pback, pin, &val, &bits))
return 0;
bits -= match_decode.table_bits;
match_state = ((val >> bits)
& ((1U << match_decode.table_bits) - 1));
}
pback = pblockend - 1;
if (!elf_fetch_backward_init (&pback, pin, &val, &bits))
return 0;
bits -= literal_decode.table_bits;
literal_state = ((val >> bits)
& ((1U << literal_decode.table_bits) - 1));
if (!elf_fetch_bits_backward (&pback, pin, &val, &bits))
return 0;
bits -= offset_decode.table_bits;
offset_state = ((val >> bits)
& ((1U << offset_decode.table_bits) - 1));
if (!elf_fetch_bits_backward (&pback, pin, &val, &bits))
return 0;
bits -= match_decode.table_bits;
match_state = ((val >> bits)
& ((1U << match_decode.table_bits) - 1));
seq = 0;
while (1)
{
@@ -4719,6 +4724,40 @@ elf_zstd_decompress_frame (const unsigned char **ppin,
uint32_t need;
uint32_t add;
if (unlikely (seq >= seq_count))
{
/* Copy remaining literals. */
if (literal_count > 0 && plit != pout)
{
if (unlikely ((size_t)(poutend - pout)
< literal_count))
{
elf_uncompress_failed ();
return 0;
}
if ((size_t)(plit - pout) < literal_count)
{
uint32_t move;
move = plit - pout;
while (literal_count > move)
{
memcpy (pout, plit, move);
pout += move;
plit += move;
literal_count -= move;
}
}
memcpy (pout, plit, literal_count);
}
pout += literal_count;
break;
}
pt = &offset_decode.table[offset_state];
offset_basebits = pt->basebits;
offset_baseline = pt->baseline;
@@ -4956,40 +4995,6 @@ elf_zstd_decompress_frame (const unsigned char **ppin,
}
}
}
if (unlikely (seq >= seq_count))
{
/* Copy remaining literals. */
if (literal_count > 0 && plit != pout)
{
if (unlikely ((size_t)(poutend - pout)
< literal_count))
{
elf_uncompress_failed ();
return 0;
}
if ((size_t)(plit - pout) < literal_count)
{
uint32_t move;
move = plit - pout;
while (literal_count > move)
{
memcpy (pout, plit, move);
pout += move;
plit += move;
literal_count -= move;
}
}
memcpy (pout, plit, literal_count);
}
pout += literal_count;
break;
}
}
pin = pblockend;