Bug 1468552 - Update bspatch.cpp to match Chromium version; r=rstrong
authorJune Wilde <jewilde@mozilla.com>
Tue, 27 Nov 2018 18:30:30 +0000
changeset 507584 6798cc7aaed0765f259470eb5f7cac16d4310545
parent 507583 e54386a858606c13bd4c7c93426c8bacdab0d7b2
child 507585 cd593d522d2486ca982697e4b6c620924894b6fb
push id1905
push userffxbld-merge
push dateMon, 21 Jan 2019 12:33:13 +0000
treeherdermozilla-release@c2fca1944d8c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrstrong
bugs1468552
milestone65.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 1468552 - Update bspatch.cpp to match Chromium version; r=rstrong Adds bounds checking around file reads and header values Differential Revision: https://phabricator.services.mozilla.com/D12356
toolkit/mozapps/update/updater/bspatch.cpp
--- a/toolkit/mozapps/update/updater/bspatch.cpp
+++ b/toolkit/mozapps/update/updater/bspatch.cpp
@@ -66,35 +66,53 @@ MBS_ReadHeader(FILE* file, MBSPatchHeade
   header->scrc32    = ntohl(header->scrc32);
   header->dlen      = ntohl(header->dlen);
   header->cblen     = ntohl(header->cblen);
   header->difflen   = ntohl(header->difflen);
   header->extralen  = ntohl(header->extralen);
 
   struct stat hs;
   s = fstat(fileno(file), &hs);
-  if (s)
+  if (s != 0)
     return READ_ERROR;
 
   if (memcmp(header->tag, "MBDIFF10", 8) != 0)
     return UNEXPECTED_BSPATCH_ERROR;
 
-  if (sizeof(MBSPatchHeader) +
-      header->cblen +
-      header->difflen +
-      header->extralen != uint32_t(hs.st_size))
+  if (hs.st_size > INT_MAX)
+    return UNEXPECTED_BSPATCH_ERROR;
+
+  size_t size = static_cast<size_t>(hs.st_size);
+  if (size < sizeof(MBSPatchHeader))
+    return UNEXPECTED_BSPATCH_ERROR;
+  size -= sizeof(MBSPatchHeader);
+
+  if (size < header->cblen)
+    return UNEXPECTED_BSPATCH_ERROR;
+  size -= header->cblen;
+
+  if (size < header->difflen)
+    return UNEXPECTED_BSPATCH_ERROR;
+  size -= header->difflen;
+
+  if (size < header->extralen)
+    return UNEXPECTED_BSPATCH_ERROR;
+  size -= header->extralen;
+
+  if (size != 0)
     return UNEXPECTED_BSPATCH_ERROR;
 
   return OK;
 }
 
 int
 MBS_ApplyPatch(const MBSPatchHeader *header, FILE* patchFile,
                unsigned char *fbuffer, FILE* file)
 {
+  unsigned char *fbufstart = fbuffer;
   unsigned char *fbufend = fbuffer + header->slen;
 
   unsigned char *buf = (unsigned char*) malloc(header->cblen +
                                                header->difflen +
                                                header->extralen);
   if (!buf)
     return BSPATCH_MEM_ERROR;
 
@@ -107,81 +125,92 @@ MBS_ApplyPatch(const MBSPatchHeader *hea
     size_t c = fread(wb, 1, count, patchFile);
     if (c != count) {
       rv = READ_ERROR;
       goto end;
     }
 
     r -= c;
     wb += c;
+
+    if (c == 0 && r) {
+      rv = UNEXPECTED_BSPATCH_ERROR;
+      goto end;
+    }
   }
 
   {
     MBSPatchTriple *ctrlsrc = (MBSPatchTriple*) buf;
+    if (header->cblen % sizeof(MBSPatchTriple) != 0) {
+      rv = UNEXPECTED_BSPATCH_ERROR;
+      goto end;
+    }
+
     unsigned char *diffsrc = buf + header->cblen;
     unsigned char *extrasrc = diffsrc + header->difflen;
 
     MBSPatchTriple *ctrlend = (MBSPatchTriple*) diffsrc;
     unsigned char *diffend = extrasrc;
     unsigned char *extraend = extrasrc + header->extralen;
 
-    do {
+    while (ctrlsrc < ctrlend) {
       ctrlsrc->x = ntohl(ctrlsrc->x);
       ctrlsrc->y = ntohl(ctrlsrc->y);
       ctrlsrc->z = ntohl(ctrlsrc->z);
 
 #ifdef DEBUG_bsmedberg
       printf("Applying block:\n"
              " x: %u\n"
              " y: %u\n"
              " z: %i\n",
              ctrlsrc->x,
              ctrlsrc->y,
              ctrlsrc->z);
 #endif
 
       /* Add x bytes from oldfile to x bytes from the diff block */
 
-      if (fbuffer + ctrlsrc->x > fbufend ||
-          diffsrc + ctrlsrc->x > diffend) {
+      if (ctrlsrc->x > static_cast<size_t>(fbufend - fbuffer) ||
+          ctrlsrc->x > static_cast<size_t>(diffend - diffsrc)) {
         rv = UNEXPECTED_BSPATCH_ERROR;
         goto end;
       }
       for (uint32_t i = 0; i < ctrlsrc->x; ++i) {
         diffsrc[i] += fbuffer[i];
       }
       if ((uint32_t) fwrite(diffsrc, 1, ctrlsrc->x, file) != ctrlsrc->x) {
         rv = WRITE_ERROR_PATCH_FILE;
         goto end;
       }
       fbuffer += ctrlsrc->x;
       diffsrc += ctrlsrc->x;
 
       /* Copy y bytes from the extra block */
 
-      if (extrasrc + ctrlsrc->y > extraend) {
+      if (ctrlsrc->y > static_cast<size_t>(extraend - extrasrc)) {
         rv = UNEXPECTED_BSPATCH_ERROR;
         goto end;
       }
       if ((uint32_t) fwrite(extrasrc, 1, ctrlsrc->y, file) != ctrlsrc->y) {
         rv = WRITE_ERROR_PATCH_FILE;
         goto end;
       }
       extrasrc += ctrlsrc->y;
 
       /* "seek" forwards in oldfile by z bytes */
 
-      if (fbuffer + ctrlsrc->z > fbufend) {
+      if (ctrlsrc->z < fbufstart - fbuffer ||
+          ctrlsrc->z > fbufend - fbuffer) {
         rv = UNEXPECTED_BSPATCH_ERROR;
         goto end;
       }
       fbuffer += ctrlsrc->z;
 
       /* and on to the next control block */
 
       ++ctrlsrc;
-    } while (ctrlsrc < ctrlend);
+    }
   }
 
 end:
   free(buf);
   return rv;
 }