mirror of
https://github.com/openharmony/third_party_elfutils.git
synced 2026-07-18 00:57:11 -04:00
libelf: Handle zero size decompressed data.
This is a corner case that will most likely never occur in practice, but we have several testcases that compress and decompress zero sized data. In that case during decompression we might malloc a buffer of size zero. It is allowed for malloc to return NULL in that case. But we do need a non-NULL buffer to return and set as result. So make sure to always at least allocate one byte. Also make sure that we don't allocate a zero sized conversion buffer for the data. https://sourceware.org/bugzilla/show_bug.cgi?id=24000 Signed-off-by: Mark Wielaard <mark@klomp.org>
This commit is contained in:
@@ -1,3 +1,13 @@
|
||||
2019-02-19 Mark Wielaard <mark@klomp.org>
|
||||
|
||||
* elf_compress.c (do_deflate_cleanup): Remove ei_data argument,
|
||||
check cdatap is not NULL before calling free.
|
||||
(deflate_cleanup): Add cdata as argument.
|
||||
(__libelf_compress): Also check whether the d_size is not zero
|
||||
before converting data. Call deflate_cleanup with an extra
|
||||
argument depending on whether there is converted data to free.
|
||||
Always allocate allocate at least one byte for buf_out.
|
||||
|
||||
2019-02-14 Mark Wielaard <mark@klomp.org>
|
||||
|
||||
* elf_begin.c (read_long_names): Make sure ar_size is properly
|
||||
|
||||
+18
-13
@@ -44,17 +44,17 @@
|
||||
/* Cleanup and return result. Don't leak memory. */
|
||||
static void *
|
||||
do_deflate_cleanup (void *result, z_stream *z, void *out_buf,
|
||||
int ei_data, Elf_Data *cdatap)
|
||||
Elf_Data *cdatap)
|
||||
{
|
||||
deflateEnd (z);
|
||||
free (out_buf);
|
||||
if (ei_data != MY_ELFDATA)
|
||||
if (cdatap != NULL)
|
||||
free (cdatap->d_buf);
|
||||
return result;
|
||||
}
|
||||
|
||||
#define deflate_cleanup(result) \
|
||||
do_deflate_cleanup(result, &z, out_buf, ei_data, &cdata)
|
||||
#define deflate_cleanup(result, cdata) \
|
||||
do_deflate_cleanup(result, &z, out_buf, cdata)
|
||||
|
||||
/* Given a section, uses the (in-memory) Elf_Data to extract the
|
||||
original data size (including the given header size) and data
|
||||
@@ -127,7 +127,8 @@ __libelf_compress (Elf_Scn *scn, size_t hsize, int ei_data,
|
||||
{
|
||||
/* Convert to raw if different endianess. */
|
||||
cdata = *data;
|
||||
if (ei_data != MY_ELFDATA)
|
||||
bool convert = ei_data != MY_ELFDATA && data->d_size > 0;
|
||||
if (convert)
|
||||
{
|
||||
/* Don't do this conversion in place, we might want to keep
|
||||
the original data around, caller decides. */
|
||||
@@ -135,10 +136,10 @@ __libelf_compress (Elf_Scn *scn, size_t hsize, int ei_data,
|
||||
if (cdata.d_buf == NULL)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_NOMEM);
|
||||
return deflate_cleanup (NULL);
|
||||
return deflate_cleanup (NULL, NULL);
|
||||
}
|
||||
if (gelf_xlatetof (scn->elf, &cdata, data, ei_data) == NULL)
|
||||
return deflate_cleanup (NULL);
|
||||
return deflate_cleanup (NULL, &cdata);
|
||||
}
|
||||
|
||||
z.avail_in = cdata.d_size;
|
||||
@@ -164,7 +165,7 @@ __libelf_compress (Elf_Scn *scn, size_t hsize, int ei_data,
|
||||
if (zrc == Z_STREAM_ERROR)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_COMPRESS_ERROR);
|
||||
return deflate_cleanup (NULL);
|
||||
return deflate_cleanup (NULL, convert ? &cdata : NULL);
|
||||
}
|
||||
used += (out_size - used) - z.avail_out;
|
||||
|
||||
@@ -172,7 +173,7 @@ __libelf_compress (Elf_Scn *scn, size_t hsize, int ei_data,
|
||||
compression forced and we are using more compressed data
|
||||
than original data. */
|
||||
if (!force && flush == Z_FINISH && used >= *orig_size)
|
||||
return deflate_cleanup ((void *) -1);
|
||||
return deflate_cleanup ((void *) -1, convert ? &cdata : NULL);
|
||||
|
||||
if (z.avail_out == 0)
|
||||
{
|
||||
@@ -180,7 +181,7 @@ __libelf_compress (Elf_Scn *scn, size_t hsize, int ei_data,
|
||||
if (bigger == NULL)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_NOMEM);
|
||||
return deflate_cleanup (NULL);
|
||||
return deflate_cleanup (NULL, convert ? &cdata : NULL);
|
||||
}
|
||||
out_buf = bigger;
|
||||
out_size += block;
|
||||
@@ -188,7 +189,7 @@ __libelf_compress (Elf_Scn *scn, size_t hsize, int ei_data,
|
||||
}
|
||||
while (z.avail_out == 0); /* Need more output buffer. */
|
||||
|
||||
if (ei_data != MY_ELFDATA)
|
||||
if (convert)
|
||||
{
|
||||
free (cdata.d_buf);
|
||||
cdata.d_buf = NULL;
|
||||
@@ -200,7 +201,7 @@ __libelf_compress (Elf_Scn *scn, size_t hsize, int ei_data,
|
||||
if (zrc != Z_OK)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_COMPRESS_ERROR);
|
||||
return deflate_cleanup (NULL);
|
||||
return deflate_cleanup (NULL, NULL);
|
||||
}
|
||||
|
||||
*new_size = used;
|
||||
@@ -220,7 +221,11 @@ __libelf_decompress (void *buf_in, size_t size_in, size_t size_out)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *buf_out = malloc (size_out);
|
||||
/* Malloc might return NULL when requestion zero size. This is highly
|
||||
unlikely, it would only happen when the compression was forced.
|
||||
But we do need a non-NULL buffer to return and set as result.
|
||||
Just make sure to always allocate at least 1 byte. */
|
||||
void *buf_out = malloc (size_out ?: 1);
|
||||
if (unlikely (buf_out == NULL))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_NOMEM);
|
||||
|
||||
Reference in New Issue
Block a user