+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
/* 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
{
/* 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. */
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;
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;
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)
{
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;
}
while (z.avail_out == 0); /* Need more output buffer. */
- if (ei_data != MY_ELFDATA)
+ if (convert)
{
free (cdata.d_buf);
cdata.d_buf = NULL;
if (zrc != Z_OK)
{
__libelf_seterrno (ELF_E_COMPRESS_ERROR);
- return deflate_cleanup (NULL);
+ return deflate_cleanup (NULL, NULL);
}
*new_size = used;
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);