Commit 6eeff2e5 authored by Alfred Kayser's avatar Alfred Kayser
Browse files

Bug 510844 - "Remove memcpy()s for compressed jar reading" [r=tglek]

parent bfa414a7
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -339,7 +339,7 @@ nsJAR::GetInputStreamWithSpec(const nsACString& aJarDirSpec,
  if (!item || item->isDirectory) {
    rv = jis->InitDirectory(this, aJarDirSpec, aEntryName);
  } else {
    rv = jis->InitFile(mZip.GetFD(item), item);
    rv = jis->InitFile(this, item);
  }
  if (NS_FAILED(rv)) {
    NS_RELEASE(*result);
+51 −85
Original line number Diff line number Diff line
@@ -59,43 +59,42 @@ NS_IMPL_THREADSAFE_ISUPPORTS1(nsJARInputStream, nsIInputStream)
 *--------------------------------------------------------*/

nsresult
nsJARInputStream::InitFile(nsZipHandle *aFd, nsZipItem *item)
nsJARInputStream::InitFile(nsJAR *aJar, nsZipItem *item)
{
    nsresult rv;
    NS_ABORT_IF_FALSE(aFd, "Argument may not be null");
    nsresult rv = NS_OK;
    NS_ABORT_IF_FALSE(aJar, "Argument may not be null");
    NS_ABORT_IF_FALSE(item, "Argument may not be null");

    // Mark it as closed, in case something fails in initialisation
    mClosed = PR_TRUE;
    // Keep the important bits of nsZipItem only
    mInSize = item->size;

    mClosed = true;
    //-- prepare for the compression type
    switch (item->compression) {
       case STORED: 
           mCompressed = false;
           break;

       case DEFLATED:
           mInflate = (InflateStruct *) PR_Malloc(sizeof(InflateStruct));
           NS_ENSURE_TRUE(mInflate, NS_ERROR_OUT_OF_MEMORY);
    
           rv = gZlibInit(&(mInflate->mZs));
           mCompressed = true;
           rv = gZlibInit(&mZs);
           NS_ENSURE_SUCCESS(rv, NS_ERROR_OUT_OF_MEMORY);
    
           mInflate->mOutSize = item->realsize;
           mInflate->mInCrc = item->crc32;
           mInflate->mOutCrc = crc32(0L, Z_NULL, 0);
           mOutSize = item->realsize;
           mInCrc = item->crc32;
           mOutCrc = crc32(0L, Z_NULL, 0);
           break;

       default:
           return NS_ERROR_NOT_IMPLEMENTED;
    }
   
    //-- Set filepointer to start of item
    mFd.Open(aFd, item->dataOffset, item->size);
        
    // Must keep handle to filepointer and mmap structure as long as we need access to the mmapped data
    mFd = aJar->mZip.GetFD();
    mZs.next_in = aJar->mZip.GetData(item);
    mZs.avail_in = item->size;
    mOutSize = item->realsize;
    mDirectory = false;
    // Open for reading
    mClosed = PR_FALSE;
    mClosed = false;
    mCurPos = 0;
    return NS_OK;
}
@@ -109,8 +108,9 @@ nsJARInputStream::InitDirectory(nsJAR* aJar,
    NS_ABORT_IF_FALSE(aDir, "Argument may not be null");

    // Mark it as closed, in case something fails in initialisation
    mClosed = PR_TRUE;
    mDirectory = PR_TRUE;
    mClosed = true;
    mDirectory = true;
    mCompressed = false;
    
    // Keep the zipReader for getting the actual zipItems
    mJar = aJar;
@@ -173,7 +173,7 @@ nsJARInputStream::InitDirectory(nsJAR* aJar,
    mBuffer.AppendLiteral("\n200: filename content-length last-modified file-type\n");

    // Open for reading
    mClosed = PR_FALSE;
    mClosed = false;
    mCurPos = 0;
    mArrPos = 0;
    return NS_OK;
@@ -187,10 +187,10 @@ nsJARInputStream::Available(PRUint32 *_retval)

    if (mDirectory)
        *_retval = mBuffer.Length();
    else if (mInflate) 
        *_retval = mInflate->mOutSize - mInflate->mZs.total_out;
    else if (mCompressed) 
        *_retval = mOutSize - mZs.total_out;
    else 
        *_retval = mInSize - mCurPos;
        *_retval = mOutSize - mCurPos;
    return NS_OK;
}

@@ -202,41 +202,30 @@ nsJARInputStream::Read(char* aBuffer, PRUint32 aCount, PRUint32 *aBytesRead)

    *aBytesRead = 0;

    nsresult rv = NS_OK;
    if (mClosed)
        return rv;
        return NS_OK;

    if (mDirectory) {
        rv = ReadDirectory(aBuffer, aCount, aBytesRead);
    } else {
        if (mInflate) {
            rv = ContinueInflate(aBuffer, aCount, aBytesRead);
        } else {
            PRInt32 bytesRead = 0;
            aCount = PR_MIN(aCount, mInSize - mCurPos);
            if (aCount) {
                bytesRead = mFd.Read(aBuffer, aCount);
                if (bytesRead < 0)
                    return NS_ERROR_FILE_CORRUPTED;
                mCurPos += bytesRead;
                if ((PRUint32)bytesRead != aCount) {
                    // file is truncated or was lying about size, we're done
                    Close();
                    return NS_ERROR_FILE_CORRUPTED;
                }
        return ReadDirectory(aBuffer, aCount, aBytesRead);
    } 
            *aBytesRead = bytesRead;
    if (mCompressed) {
        return ContinueInflate(aBuffer, aCount, aBytesRead);
    } 
    if (mFd) {
        PRUint32 count = PR_MIN(aCount, mOutSize - mCurPos);
        memcpy(aBuffer, mZs.next_in + mCurPos, count);
        mCurPos += count;
        *aBytesRead = count;
        // be aggressive about closing!
        // note that sometimes, we will close mFd before we've finished
        // deflating - this is because zlib buffers the input
        // So, don't free the ReadBuf/InflateStruct yet.
        // It is ok to close the fd multiple times (also in nsJARInputStream::Close())
        if (mCurPos >= mInSize) {
            mFd.Close();
        if (mCurPos >= mZs.avail_in) {
            mFd = nsnull;
        }
    }
    return rv;
    return NS_OK;
}

NS_IMETHODIMP
@@ -257,9 +246,9 @@ nsJARInputStream::IsNonBlocking(PRBool *aNonBlocking)
NS_IMETHODIMP
nsJARInputStream::Close()
{
    PR_FREEIF(mInflate);
    mClosed = PR_TRUE;
    mFd.Close();
    mClosed = true;
    mFd = nsnull;
    mJar = nsnull;
    return NS_OK;
}

@@ -268,56 +257,33 @@ nsJARInputStream::ContinueInflate(char* aBuffer, PRUint32 aCount,
                                  PRUint32* aBytesRead)
{
    // No need to check the args, ::Read did that, but assert them at least
    NS_ASSERTION(mInflate,"inflate data structure missing");
    NS_ASSERTION(aBuffer,"aBuffer parameter must not be null");
    NS_ASSERTION(aBytesRead,"aBytesRead parameter must not be null");

    // Keep old total_out count
    const PRUint32 oldTotalOut = mInflate->mZs.total_out;
    const PRUint32 oldTotalOut = mZs.total_out;
    
    // make sure we aren't reading too much
    mInflate->mZs.avail_out = (mInflate->mOutSize-oldTotalOut > aCount) ? aCount : mInflate->mOutSize-oldTotalOut;
    mInflate->mZs.next_out = (unsigned char*)aBuffer;

    int zerr = Z_OK;
    //-- inflate loop
    while (mInflate->mZs.avail_out > 0 && zerr == Z_OK) {

        if (mInflate->mZs.avail_in == 0 && mCurPos < mInSize) {
            // time to fill the buffer!
            PRUint32 bytesToRead = PR_MIN(mInSize - mCurPos, ZIP_BUFLEN);

            PRInt32 bytesRead = mFd.Read(mInflate->mReadBuf, bytesToRead);
            if (bytesRead < 0) {
                zerr = Z_ERRNO;
                break;
            }
            mCurPos += bytesRead;

            // now set the state for 'inflate'
            mInflate->mZs.next_in = mInflate->mReadBuf;
            mInflate->mZs.avail_in = bytesRead;
        }
    mZs.avail_out = PR_MIN(aCount, (mOutSize-oldTotalOut));
    mZs.next_out = (unsigned char*)aBuffer;

    // now inflate
        zerr = inflate(&(mInflate->mZs), Z_SYNC_FLUSH);
    }

    int zerr = inflate(&mZs, Z_SYNC_FLUSH);
    if ((zerr != Z_OK) && (zerr != Z_STREAM_END))
        return NS_ERROR_FILE_CORRUPTED;

    *aBytesRead = (mInflate->mZs.total_out - oldTotalOut);
    *aBytesRead = (mZs.total_out - oldTotalOut);

    // Calculate the CRC on the output
    mInflate->mOutCrc = crc32(mInflate->mOutCrc, (unsigned char*)aBuffer, *aBytesRead);
    mOutCrc = crc32(mOutCrc, (unsigned char*)aBuffer, *aBytesRead);

    // be aggressive about ending the inflation
    // for some reason we don't always get Z_STREAM_END
    if (zerr == Z_STREAM_END || mInflate->mZs.total_out == mInflate->mOutSize) {
        inflateEnd(&(mInflate->mZs));
    if (zerr == Z_STREAM_END || mZs.total_out == mOutSize) {
        inflateEnd(&mZs);

        // stop returning valid data as soon as we know we have a bad CRC
        if (mInflate->mOutCrc != mInflate->mInCrc) {
        if (mOutCrc != mInCrc) {
            // asserting because while this rarely happens, you definitely
            // want to catch it in debug builds!
            NS_NOTREACHED(0);
+19 −25
Original line number Diff line number Diff line
@@ -53,45 +53,39 @@ class nsJARInputStream : public nsIInputStream
{
  public:
    nsJARInputStream() : 
        mInSize(0), mCurPos(0), mInflate(nsnull), mDirectory(0), mClosed(PR_FALSE)
        mCurPos(0), mCompressed(false), mDirectory(false), mClosed(true)
    { }

  ~nsJARInputStream() {
    Close();
  }
    ~nsJARInputStream() { Close(); }

    NS_DECL_ISUPPORTS
    NS_DECL_NSIINPUTSTREAM
   
    // takes ownership of |fd|, even on failure
    nsresult InitFile(nsZipHandle *aFd, nsZipItem *item);
    nsresult InitFile(nsJAR *aJar, nsZipItem *item);

    nsresult InitDirectory(nsJAR *aJar,
                           const nsACString& aJarDirSpec,
                           const char* aDir);
  
  private:
    PRUint32      mInSize;          // Size in original file 
    nsRefPtr<nsZipHandle>  mFd;         // handle for reading
    PRUint32               mCurPos;     // Current position in input 

    struct InflateStruct {
    PRUint32               mOutSize;    // inflated size 
    PRUint32               mInCrc;      // CRC as provided by the zipentry
    PRUint32               mOutCrc;     // CRC as calculated by me
    z_stream               mZs;         // zip data structure
        unsigned char mReadBuf[ZIP_BUFLEN]; // Readbuffer to inflate from
    };
    struct InflateStruct *   mInflate;

    /* For directory reading */
    nsRefPtr<nsJAR>        mJar;        // string reference to zipreader
    PRUint32               mNameLen;    // length of dirname
    nsCAutoString           mBuffer;  // storage for generated text of stream
    nsCString              mBuffer;     // storage for generated text of stream
    PRUint32               mArrPos;     // current position within mArray
    nsTArray<nsCString>    mArray;      // array of names in (zip) directory
  PRPackedBool            mDirectory; // is this a directory?
    PRPackedBool            mClosed;  // Whether the stream is closed
    nsSeekableZipHandle     mFd;      // handle for reading

    bool                   mCompressed; // is this compressed?
    bool                   mDirectory;  // is this a directory?
    bool                   mClosed;     // Whether the stream is closed

    nsresult ContinueInflate(char* aBuf, PRUint32 aCount, PRUint32* aBytesRead);
    nsresult ReadDirectory(char* aBuf, PRUint32 aCount, PRUint32* aBytesRead);
+76 −169
Original line number Diff line number Diff line
@@ -50,7 +50,6 @@
 */


#define ZFILE_CREATE    PR_WRONLY | PR_CREATE_FILE
#define READTYPE  PRInt32
#include "zlib.h"
#include "nsISupportsUtils.h"
@@ -228,13 +227,14 @@ nsresult nsZipHandle::Init(PRFileDesc *fd, nsZipHandle **ret)
    return NS_ERROR_FILE_TOO_BIG;

  PRFileMap *map = PR_CreateFileMap(fd, size, PR_PROT_READONLY);

  if (!map)
    return NS_ERROR_FAILURE;

  nsZipHandle *handle = new nsZipHandle();
  if (!handle)
  if (!handle) {
    PR_CloseFileMap(map);
    return NS_ERROR_OUT_OF_MEMORY;
  }

  handle->mFd = fd;
  handle->mMap = map;
@@ -245,22 +245,17 @@ nsresult nsZipHandle::Init(PRFileDesc *fd, nsZipHandle **ret)
  return NS_OK;
}

PRInt32 nsZipHandle::Read(PRUint32 aPosition, void *aBuffer, PRUint32 aCount)
{
  if (mLen < 0 || aPosition+aCount > (PRUint32) mLen)
    return -1;
  PRInt32 count = PR_MIN(aCount, mLen - aPosition);
  memcpy(aBuffer, mFileData + aPosition, count);
  return count;
}

nsZipHandle::~nsZipHandle()
{
  if (mFd) {
  if (mFileData) {
    PR_MemUnmap(mFileData, mLen);
    PR_CloseFileMap(mMap);
    mFileData = nsnull;
    mMap = nsnull;
  }
  if (mFd) {
    PR_Close(mFd);
    mFd = 0;
    mFd = nsnull;
  }
  MOZ_COUNT_DTOR(nsZipHandle);
}
@@ -326,6 +321,7 @@ nsresult nsZipArchive::CloseArchive()
{
  if (mFd) {
    PL_FinishArenaPool(&mArena);
    mFd = NULL;
  }

  // CAUTION:
@@ -335,11 +331,8 @@ nsresult nsZipArchive::CloseArchive()
  // for all the nsZipItem in one shot. But if the ~nsZipItem is doing
  // anything more than cleaning up memory, we should start calling it.
  // Let us also cleanup the mFiles table for re-use on the next 'open' call
  for (int i = 0; i < ZIP_TABSIZE; i++) {
    mFiles[i] = 0;
  }
  mFd = NULL;
  mBuiltSynthetics = PR_FALSE;
  memset(mFiles, 0, sizeof(mFiles));
  mBuiltSynthetics = false;
  return ZIP_OK;
}

@@ -388,25 +381,17 @@ nsresult nsZipArchive::ExtractFile(nsZipItem *item, const char *outname,
  // so the item to be extracted should never be a directory
  PR_ASSERT(!item->isDirectory);

  //-- move to the start of file's data
  if (!MaybeReadItem(item))
    return ZIP_ERR_CORRUPT;

  nsSeekableZipHandle fd;
  if (!fd.Open(mFd.get(), item->dataOffset, item->size))
    return ZIP_ERR_CORRUPT;

  nsresult rv;

  //-- extract the file using the appropriate method
  switch(item->compression)
  {
    case STORED:
      rv = CopyItemToDisk(item->size, item->crc32, fd, aFd);
      rv = CopyItemToDisk(item, aFd);
      break;

    case DEFLATED:
      rv = InflateItem(item, fd, aFd);
      rv = InflateItem(item, aFd);
      break;

    default:
@@ -607,14 +592,12 @@ nsresult nsZipArchive::BuildFileList()
      return ZIP_ERR_MEMORY;

    item->headerOffset  = xtolong(central->localhdr_offset);
    item->dataOffset    = 0;
    item->size          = xtolong(central->size);
    item->realsize      = xtolong(central->orglen);
    item->crc32         = xtolong(central->crc32);
    item->time          = xtoint(central->time);
    item->date          = xtoint(central->date);
    item->isSynthetic   = PR_FALSE;
    item->hasDataOffset = PR_FALSE;
    item->compression   = PR_MIN(xtoint(central->method), UNSUPPORTED);
    item->mode          = ExtractMode(central->external_attributes);
#if defined(XP_UNIX) || defined(XP_BEOS)
@@ -652,7 +635,7 @@ nsresult nsZipArchive::BuildSynthetics()
{
  if (mBuiltSynthetics)
    return ZIP_OK;
  mBuiltSynthetics = PR_TRUE;
  mBuiltSynthetics = true;

  // Create synthetic entries for any missing directories.
  // Do this when all ziptable has scanned to prevent double entries.
@@ -737,91 +720,68 @@ nsresult nsZipArchive::BuildSynthetics()
  return ZIP_OK;
}

nsZipHandle* nsZipArchive::GetFD(nsZipItem* aItem)
nsZipHandle* nsZipArchive::GetFD()
{
  if (!mFd || !MaybeReadItem(aItem))
  if (!mFd)
    return NULL;
  return mFd.get();
}

//---------------------------------------------
// nsZipArchive::MaybeReadItem
// nsZipArchive::GetData
//---------------------------------------------
bool nsZipArchive::MaybeReadItem(nsZipItem* aItem)
PRUint8* nsZipArchive::GetData(nsZipItem* aItem)
{
  PR_ASSERT (aItem);

  //-- the first time an item is used we need to calculate its offset
  if (!aItem->hasDataOffset)
  {
  //-- read local header to get variable length values and calculate
  //-- the real data offset
    //--
    //-- NOTE: extralen is different in central header and local header
    //--       for archives created using the Unix "zip" utility. To set
    //--       the offset accurately we need the _local_ extralen.
    if (!mFd || !mFd->mLen > aItem->headerOffset + ZIPLOCAL_SIZE)
      return false;
  if (aItem->headerOffset + ZIPLOCAL_SIZE > mFd->mLen)
    return nsnull;

  // -- check signature before using the structure, in case the zip file is corrupt
  ZipLocal* Local = (ZipLocal*)(mFd->mFileData + aItem->headerOffset);
    //check limits here
  if ((xtolong(Local->signature) != LOCALSIG))
    {
      //-- read error or local header not found
      return false;
    }
    return nsnull;

    aItem->dataOffset = aItem->headerOffset +
  //-- NOTE: extralen is different in central header and local header
  //--       for archives created using the Unix "zip" utility. To set
  //--       the offset accurately we need the _local_ extralen.
  PRUint32 dataOffset = aItem->headerOffset +
                        ZIPLOCAL_SIZE +
                        xtoint(Local->filename_len) +
                        xtoint(Local->extrafield_len);
    aItem->hasDataOffset = PR_TRUE;
  }

  return true;
  // -- check if there is enough source data in the file
  if (dataOffset + aItem->size > mFd->mLen)
    return nsnull;

  return mFd->mFileData + dataOffset;
}

//---------------------------------------------
// nsZipArchive::CopyItemToDisk
//---------------------------------------------
nsresult
nsZipArchive::CopyItemToDisk(PRUint32 itemSize, PRUint32 itemCrc, 
                             nsSeekableZipHandle &fd, PRFileDesc* outFD)
/*
 * This function copies an archive item to disk, to the
 * file specified by outFD. If outFD is zero, the extracted data is
 * not written, only checked for CRC, so this is in effect same as 'Test'.
 */
nsZipArchive::CopyItemToDisk(nsZipItem *item, PRFileDesc* outFD)
{
  PRUint32    chunk, pos, crc;
  char buf[ZIP_BUFLEN];

  //-- initialize crc
  crc = crc32(0L, Z_NULL, 0);
  PR_ASSERT(item);

  //-- copy chunks until file is done
  for (pos = 0; pos < itemSize; pos += chunk)
  {
    chunk = (itemSize - pos < ZIP_BUFLEN) ? (itemSize - pos) : ZIP_BUFLEN;
    
    if (fd.Read(buf, chunk) != (READTYPE)chunk)
    {
      //-- unexpected end of data in archive
  //-- get to the start of file's data
  const PRUint8* itemData = GetData(item);
  if (!itemData)
    return ZIP_ERR_CORRUPT;
    }

    //-- incrementally update crc32
    crc = crc32(crc, (const unsigned char*)buf, chunk);

    if (outFD && PR_Write(outFD, buf, chunk) < (READTYPE)chunk)
  if (outFD && PR_Write(outFD, itemData, item->size) < (READTYPE)item->size)
  {
    //-- Couldn't write all the data (disk full?)
    return ZIP_ERR_DISK;
  }
  }

  //-- Calculate crc
  PRUint32 crc = crc32(0L, (const unsigned char*)itemData, item->size);
  //-- verify crc32
  if (crc != itemCrc)
  if (crc != item->crc32)
      return ZIP_ERR_CORRUPT;

  return ZIP_OK;
@@ -831,17 +791,15 @@ nsZipArchive::CopyItemToDisk(PRUint32 itemSize, PRUint32 itemCrc,
//---------------------------------------------
// nsZipArchive::InflateItem
//---------------------------------------------
nsresult nsZipArchive::InflateItem(const nsZipItem* aItem, nsSeekableZipHandle &fd, PRFileDesc* outFD)
nsresult nsZipArchive::InflateItem(nsZipItem * item, PRFileDesc* outFD)
/*
 * This function inflates an archive item to disk, to the
 * file specified by outFD. If outFD is zero, the extracted data is
 * not written, only checked for CRC, so this is in effect same as 'Test'.
 */
{
  PR_ASSERT(aItem);

  PR_ASSERT(item);
  //-- allocate deflation buffers
  Bytef inbuf[ZIP_BUFLEN];
  Bytef outbuf[ZIP_BUFLEN];

  //-- set up the inflate
@@ -851,95 +809,44 @@ nsresult nsZipArchive::InflateItem(const nsZipItem* aItem, nsSeekableZipHandle &
    return ZIP_ERR_GENERAL;

  //-- inflate loop
  zs.next_out = outbuf;
  zs.avail_out = ZIP_BUFLEN;
  zs.avail_in = item->size;
  zs.next_in = (Bytef*)GetData(item);
  if (!zs.next_in)
    return ZIP_ERR_CORRUPT;

  PRUint32  size = aItem->size;
  PRUint32  outpos = 0;
  PRUint32  crc = crc32(0L, Z_NULL, 0);
  int zerr = Z_OK;
  while (zerr == Z_OK)
  {
    PRBool      bRead = PR_FALSE;
    PRBool      bWrote= PR_FALSE;

    if (zs.avail_in == 0 && zs.total_in < size)
    {
      //-- no data to inflate yet still more in file:
      //-- read another chunk of compressed data
      PRUint32 chunk = (size-zs.total_in < ZIP_BUFLEN) ? size-zs.total_in : ZIP_BUFLEN;
    zs.next_out = outbuf;
    zs.avail_out = ZIP_BUFLEN;

      if (fd.Read(inbuf, chunk) != (READTYPE)chunk)
    zerr = inflate(&zs, Z_PARTIAL_FLUSH);
    if (zerr != Z_OK && zerr != Z_STREAM_END)
    {
        //-- unexpected end of data
        status = ZIP_ERR_CORRUPT;
      status = (zerr == Z_MEM_ERROR) ? ZIP_ERR_MEMORY : ZIP_ERR_CORRUPT;
      break;
    }
    PRUint32 count = zs.next_out - outbuf;

      zs.next_in  = inbuf;
      zs.avail_in = chunk;
      bRead       = PR_TRUE;
    }
    //-- incrementally update crc32
    crc = crc32(crc, (const unsigned char*)outbuf, count);

    if (zs.avail_out == 0)
    if (outFD && PR_Write(outFD, outbuf, count) < (READTYPE)count)
    {
      //-- write inflated buffer to disk and make space
      if (outFD && PR_Write(outFD, outbuf, ZIP_BUFLEN) < ZIP_BUFLEN)
      {
        //-- Couldn't write all the data (disk full?)
      status = ZIP_ERR_DISK;
      break;
    }

      outpos = zs.total_out;
      zs.next_out  = outbuf;
      zs.avail_out = ZIP_BUFLEN;
      bWrote       = PR_TRUE;
    }

    if(bRead || bWrote)
    {
      Bytef* old_next_out = zs.next_out;

      zerr = inflate(&zs, Z_PARTIAL_FLUSH);

      //-- incrementally update crc32
      crc = crc32(crc, (const unsigned char*)old_next_out, zs.next_out - old_next_out);
    }
    else
      zerr = Z_STREAM_END;

  } // while

  //-- free zlib internal state
  inflateEnd(&zs);

  //-- verify crc32
  if ((status == ZIP_OK) && (crc != aItem->crc32))
  if ((status == ZIP_OK) && (crc != item->crc32))
  {
    status = ZIP_ERR_CORRUPT;
      goto cleanup;
  }

  //-- write last inflated bit to disk
  if (zerr == Z_STREAM_END && outpos < zs.total_out)
  {
    PRUint32 chunk = zs.total_out - outpos;
    if (outFD && PR_Write(outFD, outbuf, chunk) < (READTYPE)chunk)
      status = ZIP_ERR_DISK;
  }

  //-- convert zlib error to return value
  if (status == ZIP_OK && zerr != Z_OK && zerr != Z_STREAM_END)
  {
    status = (zerr == Z_MEM_ERROR) ? ZIP_ERR_MEMORY : ZIP_ERR_CORRUPT;
  }

  //-- if found no errors make sure we've converted the whole thing
  PR_ASSERT(status != ZIP_OK || zs.total_in == aItem->size);
  PR_ASSERT(status != ZIP_OK || zs.total_out == aItem->realsize);

cleanup:
  //-- free zlib internal state
  inflateEnd(&zs);

  return status;
}

@@ -948,12 +855,12 @@ cleanup:
//------------------------------------------

nsZipArchive::nsZipArchive() :
  mBuiltSynthetics(PR_FALSE)
  mBuiltSynthetics(false)
{
  MOZ_COUNT_CTOR(nsZipArchive);

  // initialize the table to NULL
  memset(mFiles, 0, sizeof mFiles);
  memset(mFiles, 0, sizeof(mFiles));
}

nsZipArchive::~nsZipArchive()
+26 −97

File changed.

Preview size limit exceeded, changes collapsed.