Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-3-0]: src/gnu/dist/binutils/bfd Pull up following revision(s) (re...



details:   https://anonhg.NetBSD.org/src/rev/712471018236
branches:  netbsd-3-0
changeset: 579485:712471018236
user:      ghen <ghen%NetBSD.org@localhost>
date:      Mon Jun 23 10:39:33 2008 +0000

description:
Pull up following revision(s) (requested by adrianp in ticket #1941):
        gnu/dist/binutils/bfd/tekhex.c: revision 1.2 via patch
Fix for PR #33551 (a.k.a CVE-2006-2362)
Back port from the binutils CVS tree
Buffer overflow in getsym in tekhex.c in libbfd in Free Software Foundation
GNU Binutils before 20060423, as used by GNU strings, allows context-dependent
attackers to cause a denial of service (application crash) and possibly
execute arbitrary code via a file with a crafted Tektronix Hex Format (TekHex)
record in which the length character is not a valid hexadecimal character.

diffstat:

 gnu/dist/binutils/bfd/tekhex.c |  86 ++++++++++++++++++++++++++++-------------
 1 files changed, 58 insertions(+), 28 deletions(-)

diffs (228 lines):

diff -r e8932886bbf0 -r 712471018236 gnu/dist/binutils/bfd/tekhex.c
--- a/gnu/dist/binutils/bfd/tekhex.c    Tue May 13 06:27:43 2008 +0000
+++ b/gnu/dist/binutils/bfd/tekhex.c    Mon Jun 23 10:39:33 2008 +0000
@@ -99,7 +99,7 @@
 #define        ISHEX(x)  hex_p(x)
 
 static void tekhex_init PARAMS ((void));
-static bfd_vma getvalue PARAMS ((char **));
+static bfd_boolean getvalue PARAMS ((char **, bfd_vma *));
 static void tekhex_print_symbol
  PARAMS ((bfd *, PTR, asymbol *, bfd_print_symbol_type));
 static void tekhex_get_symbol_info PARAMS ((bfd *, asymbol *, symbol_info *));
@@ -121,11 +121,11 @@
 static bfd_boolean tekhex_mkobject PARAMS ((bfd *));
 static long tekhex_get_symtab_upper_bound PARAMS ((bfd *));
 static long tekhex_canonicalize_symtab PARAMS ((bfd *, asymbol **));
-static void pass_over PARAMS ((bfd *, void (*) (bfd*, int, char *)));
-static void first_phase PARAMS ((bfd *, int, char *));
+static bfd_boolean pass_over PARAMS ((bfd *, bfd_boolean (*) (bfd*, int, char *)));
+static bfd_boolean first_phase PARAMS ((bfd *, int, char *));
 static void insert_byte PARAMS ((bfd *, int, bfd_vma));
 static struct data_struct *find_chunk PARAMS ((bfd *, bfd_vma));
-static unsigned int getsym PARAMS ((char *, char **));
+static bfd_boolean getsym PARAMS ((char *, char **, unsigned int *));
 
 /*
 Here's an example
@@ -304,40 +304,53 @@
 
 #define enda(x) (x->vma + x->size)
 
-static bfd_vma
-getvalue (srcp)
+static bfd_boolean
+getvalue (srcp, valuep)
      char **srcp;
+     bfd_vma *valuep;
 {
   char *src = *srcp;
   bfd_vma value = 0;
-  unsigned int len = hex_value(*src++);
+  unsigned int len;
 
+  if (!ISHEX(*src))
+    return FALSE;
+
+  len = hex_value(*src++);
   if (len == 0)
     len = 16;
   while (len--)
     {
+      if (!ISHEX(*src))
+        return FALSE;
       value = value << 4 | hex_value(*src++);
     }
   *srcp = src;
-  return value;
+  *valuep = value;
+  return TRUE;
 }
 
-static unsigned int
-getsym (dstp, srcp)
+static bfd_boolean
+getsym (dstp, srcp, lenp)
      char *dstp;
      char **srcp;
+     unsigned int *lenp;
 {
   char *src = *srcp;
   unsigned int i;
-  unsigned int len = hex_value(*src++);
+  unsigned int len;
 
+  if (!ISHEX(*src))
+    return FALSE;
+  len = hex_value(*src++);
   if (len == 0)
     len = 16;
   for (i = 0; i < len; i++)
     dstp[i] = src[i];
   dstp[i] = 0;
   *srcp = src + i;
-  return len;
+  *lenp = len;
+  return TRUE;
 }
 
 static struct data_struct *
@@ -383,7 +396,7 @@
 
 /* The first pass is to find the names of all the sections, and see
   how big the data is */
-static void
+static bfd_boolean
 first_phase (abfd, type, src)
      bfd *abfd;
      int type;
@@ -391,6 +404,7 @@
 {
   asection *section = bfd_abs_section_ptr;
   unsigned int len;
+  bfd_vma val;
   char sym[17];                        /* A symbol can only be 16chars long */
 
   switch (type)
@@ -398,7 +412,10 @@
     case '6':
       /* Data record - read it and store it */
       {
-       bfd_vma addr = getvalue (&src);
+       bfd_vma addr;
+
+       if (!getvalue (&src, &addr))
+         return FALSE;
 
        while (*src)
          {
@@ -408,17 +425,18 @@
          }
       }
 
-      return;
+      return TRUE;
     case '3':
       /* Symbol record, read the segment */
-      len = getsym (sym, &src);
+      if (!getsym (sym, &src, &len))
+       return FALSE;
       section = bfd_get_section_by_name (abfd, sym);
       if (section == (asection *) NULL)
        {
          char *n = bfd_alloc (abfd, (bfd_size_type) len + 1);
 
          if (!n)
-           abort ();           /* FIXME */
+           return FALSE;
          memcpy (n, sym, len + 1);
          section = bfd_make_section (abfd, n);
        }
@@ -428,8 +446,11 @@
            {
            case '1':           /* section range */
              src++;
-             section->vma = getvalue (&src);
-             section->_raw_size = getvalue (&src) - section->vma;
+             if (!getvalue (&src, &section->vma))
+               return FALSE;
+             if (!getvalue (&src, &val))
+               return FALSE;
+             section->_raw_size = val - section->vma;
              section->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
              break;
            case '0':
@@ -447,37 +468,43 @@
                char stype = (*src);
 
                if (!new)
-                 abort ();     /* FIXME */
+                 return FALSE;
                new->symbol.the_bfd = abfd;
                src++;
                abfd->symcount++;
                abfd->flags |= HAS_SYMS;
                new->prev = abfd->tdata.tekhex_data->symbols;
                abfd->tdata.tekhex_data->symbols = new;
-               len = getsym (sym, &src);
+               if (!getsym (sym, &src, &len))
+                 return FALSE;
                new->symbol.name = bfd_alloc (abfd, (bfd_size_type) len + 1);
                if (!new->symbol.name)
-                 abort ();     /* FIXME */
+                 return FALSE;
                memcpy ((char *) (new->symbol.name), sym, len + 1);
                new->symbol.section = section;
                if (stype <= '4')
                  new->symbol.flags = (BSF_GLOBAL | BSF_EXPORT);
                else
                  new->symbol.flags = BSF_LOCAL;
-               new->symbol.value = getvalue (&src) - section->vma;
+               if (!getvalue (&src, &val))
+                 return FALSE;
+               new->symbol.value = val - section->vma;
              }
+           default:
+             return FALSE;
            }
        }
     }
+  return TRUE;
 }
 
 /* Pass over a tekhex, calling one of the above functions on each
    record.  */
 
-static void
+static bfd_boolean
 pass_over (abfd, func)
      bfd *abfd;
-     void (*func) PARAMS ((bfd *, int, char *));
+     bfd_boolean (*func) PARAMS ((bfd *, int, char *));
 {
   unsigned int chars_on_line;
   bfd_boolean eof = FALSE;
@@ -516,9 +543,10 @@
        abort (); /* FIXME */
       src[chars_on_line] = 0;  /* put a null at the end */
 
-      func (abfd, type, src);
+      if (!func (abfd, type, src))
+       return FALSE;
     }
-
+  return TRUE;
 }
 
 static long
@@ -585,7 +613,9 @@
 
   tekhex_mkobject (abfd);
 
-  pass_over (abfd, first_phase);
+  if (!pass_over (abfd, first_phase))
+    return NULL;
+
   return abfd->xvec;
 }
 



Home | Main Index | Thread Index | Old Index