summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2019-07-26 12:58:52 +0930
committerAlan Modra <amodra@gmail.com>2019-07-26 13:05:16 +0930
commit8e2e3c6c346c1c8142e714715e5a86b32f7e31ea (patch)
treef37c408660f255113544c75cda01fd0d8dc4580d
parent6dd17ae0f9b0d9fc230e75ce345da9793498554d (diff)
downloadbinutils-8e2e3c6c346c1c8142e714715e5a86b32f7e31ea.tar.gz
binutils-8e2e3c6c346c1c8142e714715e5a86b32f7e31ea.tar.xz
binutils-8e2e3c6c346c1c8142e714715e5a86b32f7e31ea.zip
PR24798, buffer overflow in process_cu_tu_index
PR 24798 * dwarf.c (process_cu_tu_index): Avoid integer overflow on 64-bit systems by casting ncols and nslots expressions to size_t. Display number of columns and slots before giving up due to buffer overflow. Use %u to display unsigned ints. Perform more pointer wrap tests.
-rw-r--r--binutils/ChangeLog8
-rw-r--r--binutils/dwarf.c53
2 files changed, 32 insertions, 29 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index bbb5570fd6..9195540282 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,11 @@
+2019-07-26 Alan Modra <amodra@gmail.com>
+
+ PR 24798
+ * dwarf.c (process_cu_tu_index): Avoid integer overflow on 64-bit
+ systems by casting ncols and nslots expressions to size_t. Display
+ number of columns and slots before giving up due to buffer overflow.
+ Use %u to display unsigned ints. Perform more pointer wrap tests.
+
2019-07-25 Tom Tromey <tromey@adacore.com>
PR 24809
diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index 94c8a03f40..d63383271b 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -9314,33 +9314,29 @@ process_cu_tu_index (struct dwarf_section *section, int do_display)
SAFE_BYTE_GET (nslots, phdr + 12, 4, limit);
phash = phdr + 16;
- pindex = phash + nslots * 8;
- ppool = pindex + nslots * 4;
-
- /* PR 17531: file: 45d69832. */
- if (pindex < phash || ppool < phdr || (pindex == phash && nslots != 0))
- {
- warn (ngettext ("Section %s is too small for %d slot\n",
- "Section %s is too small for %d slots\n",
- nslots),
- section->name, nslots);
- return 0;
- }
+ pindex = phash + (size_t) nslots * 8;
+ ppool = pindex + (size_t) nslots * 4;
if (do_display)
{
introduce (section, FALSE);
- printf (_(" Version: %d\n"), version);
+ printf (_(" Version: %u\n"), version);
if (version >= 2)
- printf (_(" Number of columns: %d\n"), ncols);
- printf (_(" Number of used entries: %d\n"), nused);
- printf (_(" Number of slots: %d\n\n"), nslots);
+ printf (_(" Number of columns: %u\n"), ncols);
+ printf (_(" Number of used entries: %u\n"), nused);
+ printf (_(" Number of slots: %u\n\n"), nslots);
}
- if (ppool > limit || ppool < phdr)
+ /* PR 17531: file: 45d69832. */
+ if ((size_t) nslots * 8 / 8 != nslots
+ || phash < phdr || phash > limit
+ || pindex < phash || pindex > limit
+ || ppool < pindex || ppool > limit)
{
- warn (_("Section %s too small for %d hash table entries\n"),
+ warn (ngettext ("Section %s is too small for %u slot\n",
+ "Section %s is too small for %u slots\n",
+ nslots),
section->name, nslots);
return 0;
}
@@ -9402,9 +9398,9 @@ process_cu_tu_index (struct dwarf_section *section, int do_display)
unsigned int dw_sect;
unsigned char *ph = phash;
unsigned char *pi = pindex;
- unsigned char *poffsets = ppool + ncols * 4;
- unsigned char *psizes = poffsets + nused * ncols * 4;
- unsigned char *pend = psizes + nused * ncols * 4;
+ unsigned char *poffsets = ppool + (size_t) ncols * 4;
+ unsigned char *psizes = poffsets + (size_t) nused * ncols * 4;
+ unsigned char *pend = psizes + (size_t) nused * ncols * 4;
bfd_boolean is_tu_index;
struct cu_tu_set *this_set = NULL;
unsigned int row;
@@ -9413,14 +9409,13 @@ process_cu_tu_index (struct dwarf_section *section, int do_display)
is_tu_index = strcmp (section->name, ".debug_tu_index") == 0;
/* PR 17531: file: 0dd159bf.
- Check for wraparound with an overlarge ncols value. */
- if (poffsets < ppool || (unsigned int) ((poffsets - ppool) / 4) != ncols)
- {
- warn (_("Overlarge number of columns: %x\n"), ncols);
- return 0;
- }
-
- if (pend > limit)
+ Check for integer overflow (can occur when size_t is 32-bit)
+ with overlarge ncols or nused values. */
+ if ((size_t) ncols * 4 / 4 != ncols
+ || (size_t) nused * ncols * 4 / ((size_t) ncols * 4) != nused
+ || poffsets < ppool || poffsets > limit
+ || psizes < poffsets || psizes > limit
+ || pend < psizes || pend > limit)
{
warn (_("Section %s too small for offset and size tables\n"),
section->name);