[PATCH] Fix tekhex (take 2)

Jakub Jelinek jakub@redhat.com
Thu Jan 4 18:51:00 GMT 2007


Hi!

Additionally I found if the first hex number (2 hex digits after %) are
smaller than 5, the buffer could be overflown.  Before the patch I posted
it would overflow the buffer and if that call returned, abort (), but with
that patch it could go on and segfault or be exploited.
Sample input where this happens:
%016C6480004E56FFFC4E717063B0AEFFFC6D0652AEFFFC60F24E5E4E752109481290842190421111111414323333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
Well, even the current version could overflow without hitting the abort
%right after it, say when
%016C6 is followed by 4GB of arbitrary data on a 64-bit host.

Here is an updated version, ok?

2007-01-04  Jakub Jelinek  <jakub@redhat.com>

	* texhex.c (first_phase): Don't fall through into the default
	case.
	(pass_over): Replace abort () calls with return FALSE.  Fix
	buffer overflow.

--- bfd/tekhex.c.jj	2006-06-19 15:17:43.000000000 +0200
+++ bfd/tekhex.c	2007-01-04 19:40:39.000000000 +0100
@@ -436,6 +436,7 @@ first_phase (bfd *abfd, int type, char *
 		if (!getvalue (&src, &val))
 		  return FALSE;
 		new->symbol.value = val - section->vma;
+		break;
 	      }
 	    default:
 	      return FALSE;
@@ -457,7 +458,7 @@ pass_over (bfd *abfd, bfd_boolean (*func
 
   /* To the front of the file.  */
   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
-    abort ();
+    return FALSE;
   while (! eof)
     {
       char buffer[MAXCHUNK];
@@ -471,22 +472,24 @@ pass_over (bfd *abfd, bfd_boolean (*func
 
       if (eof)
 	break;
-      src++;
 
       /* Fetch the type and the length and the checksum.  */
       if (bfd_bread (src, (bfd_size_type) 5, abfd) != 5)
-	abort (); /* FIXME.  */
+	return FALSE;
 
       type = src[2];
 
       if (!ISHEX (src[0]) || !ISHEX (src[1]))
 	break;
 
-      /* Already read five char.  */
+      /* Already read five chars.  */
       chars_on_line = HEX (src) - 5;
 
+      if (chars_on_line >= MAXCHUNK)
+	return FALSE;
+
       if (bfd_bread (src, (bfd_size_type) chars_on_line, abfd) != chars_on_line)
-	abort (); /* FIXME.  */
+	return FALSE;
 
       /* Put a null at the end.  */
       src[chars_on_line] = 0;

	Jakub



More information about the Binutils mailing list