Bug 1209551 - Don't read past the end of a buffer in libmar
authorMatt Howell <mhowell@mozilla.com>
Tue, 06 Oct 2015 09:11:43 -0700
changeset 266938 f832deb400b15ef2192600608f354177c12402ef
parent 266937 ba28fd929617d3673936f8a31ef40e3e6017f3c8
child 266939 6b7c0aa5fe9c9d7a1974ceaf2f6d2e5a00d995fa
push id29503
push usercbook@mozilla.com
push dateFri, 09 Oct 2015 09:36:47 +0000
treeherdermozilla-central@462074ffada4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1209551
milestone44.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1209551 - Don't read past the end of a buffer in libmar The index section of a MAR archive file contains several fixed-length fields and also variable-length names for each file in the archive, terminated by a null byte. Since that makes the length of the index variable, the length of the entire index is also provided in the file. When libmar opens a file, it allocates a buffer with the length given in the file and reads the index from the file into that buffer. mar_consume_index() then parses the entire index from that copy, trying to make sure it doesn't read past the buffer it was given. The length of the buffer is given to mar_consume_index() by providing it a pointer to one byte past the end of the buffer. However, mar_consume_index() treats this pointer as pointing *to* the end. Therefore, it is possible for a malformed MAR file (one where the stated length is less than the real length) to trigger a read of one byte beyond the allocated memory. Fix this by failing the parse when we reach the buffer end pointer minus one, instead of when we reach that address itself.
modules/libmar/src/mar_read.c
--- a/modules/libmar/src/mar_read.c
+++ b/modules/libmar/src/mar_read.c
@@ -86,17 +86,18 @@ static int mar_consume_index(MarFile *ma
 
   offset = ntohl(offset);
   length = ntohl(length);
   flags = ntohl(flags);
 
   name = *buf;
   /* find namelen; must take care not to read beyond buf_end */
   while (**buf) {
-    if (*buf == buf_end)
+    /* buf_end points one byte past the end of buf's allocation */
+    if (*buf == (buf_end - 1))
       return -1;
     ++(*buf);
   }
   namelen = (*buf - name);
   /* must ensure that namelen is valid */
   if (namelen < 0) {
     return -1;
   }