Bug 598416: add try/catch in places in nsZipReader.cpp that access mmaped memory directly r=bsmedberg a=blocking2.0-betaN
authorTaras Glek <tglek@mozilla.com>
Thu, 11 Nov 2010 12:13:48 -0800
changeset 57341 be3852cc225ba0ed09621439c7f53a7c3fae9c47
parent 57340 07f583c6cc07107b8a6a5fe1552ca740a6e8f70f
child 57342 964821cb53ace230092ead8b73f2f2e2104412ac
push idunknown
push userunknown
push dateunknown
reviewersbsmedberg, blocking2
bugs598416
milestone2.0b8pre
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 598416: add try/catch in places in nsZipReader.cpp that access mmaped memory directly r=bsmedberg a=blocking2.0-betaN
modules/libjar/nsJARInputStream.cpp
modules/libjar/nsZipArchive.cpp
modules/libjar/nsZipArchive.h
--- a/modules/libjar/nsJARInputStream.cpp
+++ b/modules/libjar/nsJARInputStream.cpp
@@ -42,16 +42,19 @@
 #include "nsJARInputStream.h"
 #include "zipstruct.h"         // defines ZIP compression codes
 #include "nsZipArchive.h"
 
 #include "nsNetUtil.h"
 #include "nsEscape.h"
 #include "nsIFile.h"
 #include "nsDebug.h"
+#if defined(XP_WIN)
+#include <windows.h>
+#endif
 
 /*---------------------------------------------
  *  nsISupports implementation
  *--------------------------------------------*/
 
 NS_IMPL_THREADSAFE_ISUPPORTS1(nsJARInputStream, nsIInputStream)
 
 /*----------------------------------------------------------
@@ -207,16 +210,17 @@ NS_IMETHODIMP
 nsJARInputStream::Read(char* aBuffer, PRUint32 aCount, PRUint32 *aBytesRead)
 {
     NS_ENSURE_ARG_POINTER(aBuffer);
     NS_ENSURE_ARG_POINTER(aBytesRead);
 
     *aBytesRead = 0;
 
     nsresult rv = NS_OK;
+MOZ_WIN_MEM_TRY_BEGIN
     switch (mMode) {
       case MODE_NOTINITED:
         return NS_OK;
 
       case MODE_CLOSED:
         return NS_BASE_STREAM_CLOSED;
 
       case MODE_DIRECTORY:
@@ -245,16 +249,17 @@ nsJARInputStream::Read(char* aBuffer, PR
         }
         // be aggressive about releasing the file!
         // note that sometimes, we will release mFd before we've finished copying.
         if (mZs.total_out >= mOutSize) {
             mFd = nsnull;
         }
         break;
     }
+MOZ_WIN_MEM_TRY_CATCH(rv = NS_ERROR_FAILURE)
     return rv;
 }
 
 NS_IMETHODIMP
 nsJARInputStream::ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint32 count, PRUint32 *_retval)
 {
     // don't have a buffer to read from, so this better not be called!
     NS_NOTREACHED("Consumers should be using Read()!");
--- a/modules/libjar/nsZipArchive.cpp
+++ b/modules/libjar/nsZipArchive.cpp
@@ -57,16 +57,19 @@
 #include "plstr.h"
 #include "prlog.h"
 #include "stdlib.h"
 #include "nsWildCard.h"
 #include "nsZipArchive.h"
 #include "nsString.h"
 #include "mozilla/FunctionTimer.h"
 #include "prenv.h"
+#if defined(XP_WIN)
+#include <windows.h>
+#endif
 
 /**
  * Global allocator used with zlib. Destroyed in module shutdown.
  */
 #define NBUCKETS 6
 nsRecyclingAllocator *gZlibAllocator = NULL;
 
 // For placement new used for arena allocations of zip file list
@@ -194,17 +197,17 @@ nsresult nsZipHandle::Init(nsILocalFile 
   // Bug 525755: PR_MemMap fails when fd points at something other than a normal file.
   if (!buf) {
     PR_CloseFileMap(map);
     return NS_ERROR_FAILURE;
   }
 
   nsRefPtr<nsZipHandle> handle = new nsZipHandle();
   if (!handle) {
-    PR_MemUnmap(buf, size);
+    PR_MemUnmap(buf, (PRUint32) size);
     PR_CloseFileMap(map);
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   handle->mMap = map;
   handle->mFile = file;
   handle->mLen = (PRUint32) size;
   handle->mFileData = buf;
@@ -364,35 +367,36 @@ nsZipItem*  nsZipArchive::GetItem(const 
     //-- If the request is for a directory, make sure that synthetic entries 
     //-- are created for the directories without their own entry.
     if (!mBuiltSynthetics) {
         if ((len > 0) && (aEntryName[len-1] == '/')) {
             if (BuildSynthetics() != NS_OK)
                 return 0;
         }
     }
-
+MOZ_WIN_MEM_TRY_BEGIN
     nsZipItem* item = mFiles[ HashName(aEntryName, len) ];
     while (item) {
       if ((len == item->nameLength) && 
           (!memcmp(aEntryName, item->Name(), len))) {
         
         if (mLog) {
           // Successful GetItem() is a good indicator that the file is about to be read
           char *tmp = PL_strdup(aEntryName);
           tmp[len]='\n';
           PR_Write(mLog, tmp, len+1);
           PL_strfree(tmp);
         }
         return item; //-- found it
       }
       item = item->next;
     }
+MOZ_WIN_MEM_TRY_CATCH(return nsnull)
   }
-  return 0;
+  return nsnull;
 }
 
 //---------------------------------------------
 // nsZipArchive::ExtractFile
 // This extracts the item to the filehandle provided.
 // If 'aFd' is null, it only tests the extraction.
 // On extraction error(s) it removes the file.
 // When needed, it also resolves the symlink.
@@ -508,17 +512,17 @@ nsZipArchive::FindInit(const char * aPat
 //---------------------------------------------
 nsresult nsZipFind::FindNext(const char ** aResult, PRUint16 *aNameLen)
 {
   if (!mArchive || !aResult || !aNameLen)
     return NS_ERROR_ILLEGAL_VALUE;
 
   *aResult = 0;
   *aNameLen = 0;
-
+MOZ_WIN_MEM_TRY_BEGIN
   // we start from last match, look for next
   while (mSlot < ZIP_TABSIZE)
   {
     // move to next in current chain, or move to new slot
     mItem = mItem ? mItem->next : mArchive->mFiles[mSlot];
 
     PRBool found = PR_FALSE;
     if (!mItem)
@@ -537,17 +541,17 @@ nsresult nsZipFind::FindNext(const char 
                (memcmp(mItem->Name(), mPattern, mItem->nameLength) == 0));
     if (found) {
       // Need also to return the name length, as it is NOT zero-terminatdd...
       *aResult = mItem->Name();
       *aNameLen = mItem->nameLength;
       return NS_OK;
     }
   }
-
+MOZ_WIN_MEM_TRY_CATCH(return NS_ERROR_FAILURE)
   return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST;
 }
 
 #if defined(XP_UNIX) || defined(XP_BEOS)
 //---------------------------------------------
 // ResolveSymlink
 //---------------------------------------------
 static nsresult ResolveSymlink(const char *path)
@@ -585,23 +589,24 @@ nsZipItem* nsZipArchive::CreateZipItem()
   return (nsZipItem*)mem;
 }
 
 //---------------------------------------------
 //  nsZipArchive::BuildFileList
 //---------------------------------------------
 nsresult nsZipArchive::BuildFileList()
 {
+#ifndef XP_WIN
   NS_TIME_FUNCTION;
-
+#endif
   // Get archive size using end pos
   const PRUint8* buf;
   const PRUint8* startp = mFd->mFileData;
   const PRUint8* endp = startp + mFd->mLen;
-  
+MOZ_WIN_MEM_TRY_BEGIN
   PRUint32 centralOffset = 4;
   if (mFd->mLen > ZIPCENTRAL_SIZE && xtolong(startp + centralOffset) == CENTRALSIG) {
     // Success means optimized jar layout from bug 559961 is in effect
   } else {
     for (buf = endp - ZIPEND_SIZE; buf > startp; buf--)
       {
         if (xtolong(buf) == ENDSIG) {
           centralOffset = xtolong(((ZipEnd *)buf)->offset_central_dir);
@@ -651,28 +656,31 @@ nsresult nsZipArchive::BuildFileList()
     item->next = mFiles[hash];
     mFiles[hash] = item;
 
     sig = xtolong(buf);
   } /* while reading central directory records */
 
   if (sig != ENDSIG)
     return NS_ERROR_FILE_CORRUPTED;
+
+MOZ_WIN_MEM_TRY_CATCH(return NS_ERROR_FAILURE)
   return NS_OK;
 }
 
 //---------------------------------------------
 //  nsZipArchive::BuildSynthetics
 //---------------------------------------------
 nsresult nsZipArchive::BuildSynthetics()
 {
   if (mBuiltSynthetics)
     return NS_OK;
   mBuiltSynthetics = true;
 
+MOZ_WIN_MEM_TRY_BEGIN
   // Create synthetic entries for any missing directories.
   // Do this when all ziptable has scanned to prevent double entries.
   for (int i = 0; i < ZIP_TABSIZE; ++i)
   {
     for (nsZipItem* item = mFiles[i]; item != 0; item = item->next)
     {
       if (item->isSynthetic)
         continue;
@@ -719,32 +727,34 @@ nsresult nsZipArchive::BuildSynthetics()
         diritem->isSynthetic = true;
 
         // add diritem to the file table
         diritem->next = mFiles[hash];
         mFiles[hash] = diritem;
       } /* end processing of dirs in item's name */
     }
   }
+MOZ_WIN_MEM_TRY_CATCH(return NS_ERROR_FAILURE)
   return NS_OK;
 }
 
 nsZipHandle* nsZipArchive::GetFD()
 {
   if (!mFd)
     return NULL;
   return mFd.get();
 }
 
 //---------------------------------------------
 // nsZipArchive::GetData
 //---------------------------------------------
 const PRUint8* nsZipArchive::GetData(nsZipItem* aItem)
 {
   PR_ASSERT (aItem);
+MOZ_WIN_MEM_TRY_BEGIN
   //-- read local header to get variable length values and calculate
   //-- the real data offset
   PRUint32 len = mFd->mLen;
   const PRUint8* data = mFd->mFileData;
   PRUint32 offset = aItem->LocalOffset();
   if (offset + ZIPLOCAL_SIZE > len)
     return nsnull;
 
@@ -760,16 +770,17 @@ const PRUint8* nsZipArchive::GetData(nsZ
             xtoint(Local->filename_len) +
             xtoint(Local->extrafield_len);
 
   // -- check if there is enough source data in the file
   if (offset + aItem->Size() > len)
     return nsnull;
 
   return data + offset;
+MOZ_WIN_MEM_TRY_CATCH(return nsnull)
 }
 
 PRBool 
 nsZipArchive::CheckCRC(nsZipItem* aItem, const PRUint8* aItemData) {
   PRUint32 crc = crc32(0, (const unsigned char*)aItemData, aItem->Size());
   return crc == aItem->CRC32();
 }
 
@@ -938,18 +949,18 @@ bool nsZipItem::IsDirectory()
 PRUint16 nsZipItem::Mode()
 {
   if (isSynthetic) return 0755;
   return ((PRUint16)(central->external_attributes[2]) | 0x100);
 }
 
 const PRUint8 * nsZipItem::GetExtraField(PRUint16 aTag, PRUint16 *aBlockSize)
 {
-  if (isSynthetic) return NULL;
-
+  if (isSynthetic) return nsnull;
+MOZ_WIN_MEM_TRY_BEGIN
   const unsigned char *buf = ((const unsigned char*)central) + ZIPCENTRAL_SIZE +
                              nameLength;
   PRUint32 buflen = (PRUint32)xtoint(central->extrafield_len);
   PRUint32 pos = 0;
   PRUint16 tag, blocksize;
 
   while (buf && (pos + 4) <= buflen) {
     tag = xtoint(buf + pos);
@@ -958,17 +969,18 @@ const PRUint8 * nsZipItem::GetExtraField
     if (aTag == tag && (pos + 4 + blocksize) <= buflen) {
       *aBlockSize = blocksize;
       return buf + pos;
     }
 
     pos += blocksize + 4;
   }
 
-  return NULL;
+MOZ_WIN_MEM_TRY_CATCH(return nsnull)
+  return nsnull;
 }
 
 
 PRTime nsZipItem::LastModTime()
 {
   if (isSynthetic) return GetModTime(kSyntheticDate, kSyntheticTime);
 
   // Try to read timestamp from extra field
@@ -1017,17 +1029,17 @@ nsZipCursor::~nsZipCursor()
 
 PRUint8* nsZipCursor::Read(PRUint32 *aBytesRead) {
   int zerr;
   PRUint8 *buf = nsnull;
   bool verifyCRC = true;
 
   if (!mZs.next_in)
     return nsnull;
-
+MOZ_WIN_MEM_TRY_BEGIN
   switch (mItem->Compression()) {
   case STORED:
     *aBytesRead = mZs.avail_in;
     buf = mZs.next_in;
     mZs.next_in += mZs.avail_in;
     mZs.avail_in = 0;
     break;
   case DEFLATED:
@@ -1046,25 +1058,26 @@ PRUint8* nsZipCursor::Read(PRUint32 *aBy
     return nsnull;
   }
 
   if (mDoCRC) {
     mCRC = crc32(mCRC, (const unsigned char*)buf, *aBytesRead);
     if (verifyCRC && mCRC != mItem->CRC32())
       return nsnull;
   }
+MOZ_WIN_MEM_TRY_CATCH(return nsnull)
   return buf;
 }
 
 nsZipItemPtr_base::nsZipItemPtr_base(nsZipArchive *aZip, const char * aEntryName, bool doCRC) :
   mReturnBuf(nsnull)
 {
   // make sure the ziparchive hangs around
   mZipHandle = aZip->GetFD();
-  
+
   nsZipItem* item = aZip->GetItem(aEntryName);
   if (!item)
     return;
 
   PRUint32 size = 0;
   if (item->Compression() == DEFLATED) {
     size = item->RealSize();
     mAutoBuf = new PRUint8[size];
--- a/modules/libjar/nsZipArchive.h
+++ b/modules/libjar/nsZipArchive.h
@@ -52,18 +52,31 @@
 #include "plarena.h"
 
 #include "zlib.h"
 #include "zipstruct.h"
 #include "nsAutoPtr.h"
 #include "nsILocalFile.h"
 #include "mozilla/FileUtils.h"
 
+#if defined(XP_WIN)
+#define MOZ_WIN_MEM_TRY_BEGIN __try {
+#define MOZ_WIN_MEM_TRY_CATCH(cmd) }                                \
+  __except(GetExceptionCode()==EXCEPTION_IN_PAGE_ERROR ?            \
+           EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)   \
+  {                                                                 \
+    NS_WARNING("EXCEPTION_IN_PAGE_ERROR in " __FUNCTION__);         \
+    cmd;                                                            \
+  }
+#else
+#define MOZ_WIN_MEM_TRY_BEGIN {
+#define MOZ_WIN_MEM_TRY_CATCH(cmd) }
+#endif
+
 class nsZipFind;
-
 struct PRFileDesc;
 
 /**
  * This file defines some of the basic structures used by libjar to
  * read Zip files. It makes use of zlib in order to do the decompression.
  *
  * A few notes on the classes/structs:
  * nsZipArchive   represents a single Zip file, and maintains an index