libbacktrace: don't assume compressed section is aligned (7ead8c1)

This commit is contained in:
Bartosz Taudul 2024-03-13 00:29:01 +01:00
parent 49478ec3b3
commit 2df972d586
No known key found for this signature in database
GPG Key ID: B7FE2008B7575DF3

View File

@ -5094,7 +5094,7 @@ elf_uncompress_chdr (struct backtrace_state *state,
backtrace_error_callback error_callback, void *data, backtrace_error_callback error_callback, void *data,
unsigned char **uncompressed, size_t *uncompressed_size) unsigned char **uncompressed, size_t *uncompressed_size)
{ {
const b_elf_chdr *chdr; b_elf_chdr chdr;
char *alc; char *alc;
size_t alc_len; size_t alc_len;
unsigned char *po; unsigned char *po;
@ -5106,27 +5106,30 @@ elf_uncompress_chdr (struct backtrace_state *state,
if (compressed_size < sizeof (b_elf_chdr)) if (compressed_size < sizeof (b_elf_chdr))
return 1; return 1;
chdr = (const b_elf_chdr *) compressed; /* The lld linker can misalign a compressed section, so we can't safely read
the fields directly as we can for other ELF sections. See
https://github.com/ianlancetaylor/libbacktrace/pull/120. */
memcpy (&chdr, compressed, sizeof (b_elf_chdr));
alc = NULL; alc = NULL;
alc_len = 0; alc_len = 0;
if (*uncompressed != NULL && *uncompressed_size >= chdr->ch_size) if (*uncompressed != NULL && *uncompressed_size >= chdr.ch_size)
po = *uncompressed; po = *uncompressed;
else else
{ {
alc_len = chdr->ch_size; alc_len = chdr.ch_size;
alc = (char*)backtrace_alloc (state, alc_len, error_callback, data); alc = (char*)backtrace_alloc (state, alc_len, error_callback, data);
if (alc == NULL) if (alc == NULL)
return 0; return 0;
po = (unsigned char *) alc; po = (unsigned char *) alc;
} }
switch (chdr->ch_type) switch (chdr.ch_type)
{ {
case ELFCOMPRESS_ZLIB: case ELFCOMPRESS_ZLIB:
if (!elf_zlib_inflate_and_verify (compressed + sizeof (b_elf_chdr), if (!elf_zlib_inflate_and_verify (compressed + sizeof (b_elf_chdr),
compressed_size - sizeof (b_elf_chdr), compressed_size - sizeof (b_elf_chdr),
zdebug_table, po, chdr->ch_size)) zdebug_table, po, chdr.ch_size))
goto skip; goto skip;
break; break;
@ -5134,7 +5137,7 @@ elf_uncompress_chdr (struct backtrace_state *state,
if (!elf_zstd_decompress (compressed + sizeof (b_elf_chdr), if (!elf_zstd_decompress (compressed + sizeof (b_elf_chdr),
compressed_size - sizeof (b_elf_chdr), compressed_size - sizeof (b_elf_chdr),
(unsigned char *)zdebug_table, po, (unsigned char *)zdebug_table, po,
chdr->ch_size)) chdr.ch_size))
goto skip; goto skip;
break; break;
@ -5144,7 +5147,7 @@ elf_uncompress_chdr (struct backtrace_state *state,
} }
*uncompressed = po; *uncompressed = po;
*uncompressed_size = chdr->ch_size; *uncompressed_size = chdr.ch_size;
return 1; return 1;
@ -6895,8 +6898,8 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
} }
} }
// A debuginfo file may not have a useful .opd section, but we can use the /* A debuginfo file may not have a useful .opd section, but we can use the
// one from the original executable. one from the original executable. */
if (opd == NULL) if (opd == NULL)
opd = caller_opd; opd = caller_opd;