aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2014-12-03 19:50:48 +0000
committerNick Clifton <nickc@redhat.com>2014-12-03 19:50:48 +0000
commitdb6b071a97893d5c7bf34e7fb171a0b710ea736d (patch)
treee6a0854550b4bd07b8aadfab2cb873e7f688ecd0
parent4759c34e128035e57b06a7b3d7c58f135061c6da (diff)
downloadgdb-db6b071a97893d5c7bf34e7fb171a0b710ea736d.zip
gdb-db6b071a97893d5c7bf34e7fb171a0b710ea736d.tar.gz
gdb-db6b071a97893d5c7bf34e7fb171a0b710ea736d.tar.bz2
Fix memory access problems exposed by fuzzed binaries.
PR binutils/17512 * objdump.c (free_debug_section): Reset the compress_status as well. * compress.c (bfd_get_full_section_contents): Fail if there are no section contents available when the compress_status is COMPRESS_SECTION_DONE. * libbfd.c (bfd_malloc): Refuse to allocate a negative size. (bfd_malloc2): Use bfd_malloc. (bfd_realloc): Refuse to reallocate a negative size. (bfd_realloc2): Use bfd_realloc. (bfd_realloc_or_free): Use bfd_realloc. (bfd_zmalloc): Use bfd_malloc. (bfd_zmalloc): Use bfd_malloc2. * opncls.c (bfd_alloc): Refuse to allocate a negative size.
-rw-r--r--bfd/ChangeLog15
-rw-r--r--bfd/compress.c2
-rw-r--r--bfd/libbfd.c127
-rw-r--r--bfd/opncls.c14
-rw-r--r--binutils/ChangeLog6
-rw-r--r--binutils/objdump.c1
6 files changed, 61 insertions, 104 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 61a8b2b..65c7243 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,18 @@
+2014-12-03 Nick Clifton <nickc@redhat.com>
+
+ PR binutils/17512
+ * compress.c (bfd_get_full_section_contents): Fail if there are no
+ section contents available when the compress_status is
+ COMPRESS_SECTION_DONE.
+ * libbfd.c (bfd_malloc): Refuse to allocate a negative size.
+ (bfd_malloc2): Use bfd_malloc.
+ (bfd_realloc): Refuse to reallocate a negative size.
+ (bfd_realloc2): Use bfd_realloc.
+ (bfd_realloc_or_free): Use bfd_realloc.
+ (bfd_zmalloc): Use bfd_malloc.
+ (bfd_zmalloc): Use bfd_malloc2.
+ * opncls.c (bfd_alloc): Refuse to allocate a negative size.
+
2014-12-03 H.J. Lu <hongjiu.lu@intel.com>
* elf64-x86-64.c (elf_x86_64_create_dynamic_sections): Reformat.
diff --git a/bfd/compress.c b/bfd/compress.c
index 3fcbd78..a3a2f35 100644
--- a/bfd/compress.c
+++ b/bfd/compress.c
@@ -244,6 +244,8 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
#endif
case COMPRESS_SECTION_DONE:
+ if (sec->contents == NULL)
+ return FALSE;
if (p == NULL)
{
p = (bfd_byte *) bfd_malloc (sz);
diff --git a/bfd/libbfd.c b/bfd/libbfd.c
index 6352c9c..ade8e0f 100644
--- a/bfd/libbfd.c
+++ b/bfd/libbfd.c
@@ -171,15 +171,18 @@ void *
bfd_malloc (bfd_size_type size)
{
void *ptr;
+ size_t sz = (size_t) size;
- if (size != (size_t) size)
+ if (size != sz
+ /* This is to pacify memory checkers like valgrind. */
+ || ((signed long) sz) < 0)
{
bfd_set_error (bfd_error_no_memory);
return NULL;
}
- ptr = malloc ((size_t) size);
- if (ptr == NULL && (size_t) size != 0)
+ ptr = malloc (sz);
+ if (ptr == NULL && sz != 0)
bfd_set_error (bfd_error_no_memory);
return ptr;
@@ -190,8 +193,6 @@ bfd_malloc (bfd_size_type size)
void *
bfd_malloc2 (bfd_size_type nmemb, bfd_size_type size)
{
- void *ptr;
-
if ((nmemb | size) >= HALF_BFD_SIZE_TYPE
&& size != 0
&& nmemb > ~(bfd_size_type) 0 / size)
@@ -200,19 +201,7 @@ bfd_malloc2 (bfd_size_type nmemb, bfd_size_type size)
return NULL;
}
- size *= nmemb;
-
- if (size != (size_t) size)
- {
- bfd_set_error (bfd_error_no_memory);
- return NULL;
- }
-
- ptr = malloc ((size_t) size);
- if (ptr == NULL && (size_t) size != 0)
- bfd_set_error (bfd_error_no_memory);
-
- return ptr;
+ return bfd_malloc (size * nmemb);
}
/* Reallocate memory using realloc. */
@@ -221,19 +210,22 @@ void *
bfd_realloc (void *ptr, bfd_size_type size)
{
void *ret;
+ size_t sz = (size_t) size;
+
+ if (ptr == NULL)
+ return bfd_malloc (size);
- if (size != (size_t) size)
+ if (size != sz
+ /* This is to pacify memory checkers like valgrind. */
+ || ((signed long) sz) < 0)
{
bfd_set_error (bfd_error_no_memory);
return NULL;
}
- if (ptr == NULL)
- ret = malloc ((size_t) size);
- else
- ret = realloc (ptr, (size_t) size);
+ ret = realloc (ptr, sz);
- if (ret == NULL && (size_t) size != 0)
+ if (ret == NULL && sz != 0)
bfd_set_error (bfd_error_no_memory);
return ret;
@@ -244,8 +236,6 @@ bfd_realloc (void *ptr, bfd_size_type size)
void *
bfd_realloc2 (void *ptr, bfd_size_type nmemb, bfd_size_type size)
{
- void *ret;
-
if ((nmemb | size) >= HALF_BFD_SIZE_TYPE
&& size != 0
&& nmemb > ~(bfd_size_type) 0 / size)
@@ -254,23 +244,7 @@ bfd_realloc2 (void *ptr, bfd_size_type nmemb, bfd_size_type size)
return NULL;
}
- size *= nmemb;
-
- if (size != (size_t) size)
- {
- bfd_set_error (bfd_error_no_memory);
- return NULL;
- }
-
- if (ptr == NULL)
- ret = malloc ((size_t) size);
- else
- ret = realloc (ptr, (size_t) size);
-
- if (ret == NULL && (size_t) size != 0)
- bfd_set_error (bfd_error_no_memory);
-
- return ret;
+ return bfd_realloc (ptr, size * nmemb);
}
/* Reallocate memory using realloc.
@@ -279,24 +253,10 @@ bfd_realloc2 (void *ptr, bfd_size_type nmemb, bfd_size_type size)
void *
bfd_realloc_or_free (void *ptr, bfd_size_type size)
{
- size_t amount = (size_t) size;
- void *ret;
+ void *ret = bfd_realloc (ptr, size);
- if (size != amount)
- ret = NULL;
- else if (ptr == NULL)
- ret = malloc (amount);
- else
- ret = realloc (ptr, amount);
-
- if (ret == NULL)
- {
- if (amount > 0)
- bfd_set_error (bfd_error_no_memory);
-
- if (ptr != NULL)
- free (ptr);
- }
+ if (ret == NULL && ptr != NULL)
+ free (ptr);
return ret;
}
@@ -306,23 +266,10 @@ bfd_realloc_or_free (void *ptr, bfd_size_type size)
void *
bfd_zmalloc (bfd_size_type size)
{
- void *ptr;
+ void *ptr = bfd_malloc (size);
- if (size != (size_t) size)
- {
- bfd_set_error (bfd_error_no_memory);
- return NULL;
- }
-
- ptr = malloc ((size_t) size);
-
- if ((size_t) size != 0)
- {
- if (ptr == NULL)
- bfd_set_error (bfd_error_no_memory);
- else
- memset (ptr, 0, (size_t) size);
- }
+ if (ptr != NULL && size > 0)
+ memset (ptr, 0, (size_t) size);
return ptr;
}
@@ -333,32 +280,14 @@ bfd_zmalloc (bfd_size_type size)
void *
bfd_zmalloc2 (bfd_size_type nmemb, bfd_size_type size)
{
- void *ptr;
+ void *ptr = bfd_malloc2 (nmemb, size);
- if ((nmemb | size) >= HALF_BFD_SIZE_TYPE
- && size != 0
- && nmemb > ~(bfd_size_type) 0 / size)
+ if (ptr != NULL)
{
- bfd_set_error (bfd_error_no_memory);
- return NULL;
- }
+ size_t sz = nmemb * size;
- size *= nmemb;
-
- if (size != (size_t) size)
- {
- bfd_set_error (bfd_error_no_memory);
- return NULL;
- }
-
- ptr = malloc ((size_t) size);
-
- if ((size_t) size != 0)
- {
- if (ptr == NULL)
- bfd_set_error (bfd_error_no_memory);
- else
- memset (ptr, 0, (size_t) size);
+ if (sz > 0)
+ memset (ptr, 0, sz);
}
return ptr;
diff --git a/bfd/opncls.c b/bfd/opncls.c
index 75af627..404b944 100644
--- a/bfd/opncls.c
+++ b/bfd/opncls.c
@@ -940,15 +940,19 @@ bfd_alloc (bfd *abfd, bfd_size_type size)
unsigned long ul_size = (unsigned long) size;
if (size != ul_size
- /* A small negative size can result in objalloc_alloc allocating just
- 1 byte of memory, but the caller will be expecting more. So catch
- this case here. */
- || (size != 0 && (((ul_size + OBJALLOC_ALIGN - 1) &~ (OBJALLOC_ALIGN - 1)) == 0)))
+ /* Note - although objalloc_alloc takes an unsigned long as its
+ argument, internally the size is treated as a signed long. This can
+ lead to problems where, for example, a request to allocate -1 bytes
+ can result in just 1 byte being allocated, rather than
+ ((unsigned long) -1) bytes. Also memory checkers will often
+ complain about attempts to allocate a negative amount of memory.
+ So to stop these problems we fail if the size is negative. */
+ || ((signed long) ul_size) < 0)
{
bfd_set_error (bfd_error_no_memory);
return NULL;
}
-
+
ret = objalloc_alloc ((struct objalloc *) abfd->memory, ul_size);
if (ret == NULL)
bfd_set_error (bfd_error_no_memory);
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 2d28e1c..8740dd2 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,5 +1,11 @@
2014-12-03 Nick Clifton <nickc@redhat.com>
+ PR binutils/17512
+ * objdump.c (free_debug_section): Reset the compress_status as
+ well.
+
+2014-12-03 Nick Clifton <nickc@redhat.com>
+
PR binutils/17531
* readelf.c (get_machine_flags): Replace call to abort with a
warning message and a return value.
diff --git a/binutils/objdump.c b/binutils/objdump.c
index b13bf00..b43d111 100644
--- a/binutils/objdump.c
+++ b/binutils/objdump.c
@@ -2360,6 +2360,7 @@ free_debug_section (enum dwarf_section_display_enum debug)
{
sec->contents = NULL;
sec->flags &= ~ SEC_IN_MEMORY;
+ sec->compress_status = COMPRESS_SECTION_NONE;
}
}