зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1550815 - Handle SIGBUS error when accessing mmapped file, r=aklotz,haik
This patch adds mmap page fault handling to linux/android. Differential Revision: https://phabricator.services.mozilla.com/D42010 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
0a069e2799
Коммит
ef9ac4c5c0
|
@ -0,0 +1,141 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MmapFaultHandler.h"
|
||||
|
||||
#if defined(XP_UNIX) && !defined(XP_DARWIN)
|
||||
|
||||
# include "nsZipArchive.h"
|
||||
# include "mozilla/Atomics.h"
|
||||
# include "mozilla/StaticMutex.h"
|
||||
# include "MainThreadUtils.h"
|
||||
# include "mozilla/ThreadLocal.h"
|
||||
# include <signal.h>
|
||||
|
||||
static MOZ_THREAD_LOCAL(MmapAccessScope*) sMmapAccessScope;
|
||||
|
||||
static struct sigaction sPrevSIGBUSHandler;
|
||||
|
||||
static void MmapSIGBUSHandler(int signum, siginfo_t* info, void* context) {
|
||||
MOZ_RELEASE_ASSERT(signum == SIGBUS);
|
||||
|
||||
MmapAccessScope* mas = sMmapAccessScope.get();
|
||||
|
||||
if (mas && mas->IsInsideBuffer(info->si_addr)) {
|
||||
// The address is inside the buffer, handle the failure.
|
||||
siglongjmp(mas->mJmpBuf, signum);
|
||||
return;
|
||||
}
|
||||
|
||||
// This signal is not caused by accessing region protected by MmapAccessScope.
|
||||
// Forward the signal to the next handler.
|
||||
if (sPrevSIGBUSHandler.sa_flags & SA_SIGINFO) {
|
||||
sPrevSIGBUSHandler.sa_sigaction(signum, info, context);
|
||||
} else if (sPrevSIGBUSHandler.sa_handler == SIG_DFL ||
|
||||
sPrevSIGBUSHandler.sa_handler == SIG_IGN) {
|
||||
// There is no next handler. Uninstalling our handler and returning will
|
||||
// cause a crash.
|
||||
sigaction(signum, &sPrevSIGBUSHandler, nullptr);
|
||||
} else {
|
||||
sPrevSIGBUSHandler.sa_handler(signum);
|
||||
}
|
||||
}
|
||||
|
||||
mozilla::Atomic<bool> gSIGBUSHandlerInstalled(false);
|
||||
mozilla::StaticMutex gSIGBUSHandlerMutex;
|
||||
|
||||
void InstallMmapFaultHandler() {
|
||||
// This function is called from MmapAccessScope's constructor because there is
|
||||
// no single point where we could install the handler during startup. This
|
||||
// means that it's called quite often, so to minimize using of the mutex we
|
||||
// first check the atomic variable outside the lock.
|
||||
if (gSIGBUSHandlerInstalled) {
|
||||
return;
|
||||
}
|
||||
|
||||
mozilla::StaticMutexAutoLock lock(gSIGBUSHandlerMutex);
|
||||
|
||||
// We must check it again, because the handler could be installed on another
|
||||
// thread when we were waiting for the lock.
|
||||
if (gSIGBUSHandlerInstalled) {
|
||||
return;
|
||||
}
|
||||
|
||||
sMmapAccessScope.infallibleInit();
|
||||
|
||||
struct sigaction busHandler;
|
||||
busHandler.sa_flags = SA_SIGINFO | SA_NODEFER | SA_ONSTACK;
|
||||
busHandler.sa_sigaction = MmapSIGBUSHandler;
|
||||
sigemptyset(&busHandler.sa_mask);
|
||||
if (sigaction(SIGBUS, &busHandler, &sPrevSIGBUSHandler)) {
|
||||
MOZ_CRASH("Unable to install SIGBUS handler");
|
||||
}
|
||||
|
||||
gSIGBUSHandlerInstalled = true;
|
||||
}
|
||||
|
||||
MmapAccessScope::MmapAccessScope(void* aBuf, uint32_t aBufLen) {
|
||||
// Install signal handler if it wasn't installed yet.
|
||||
InstallMmapFaultHandler();
|
||||
|
||||
// We'll handle the signal only if the crashing address is inside this buffer.
|
||||
mBuf = aBuf;
|
||||
mBufLen = aBufLen;
|
||||
|
||||
SetThreadLocalScope();
|
||||
}
|
||||
|
||||
MmapAccessScope::MmapAccessScope(nsZipHandle* aZipHandle)
|
||||
: mBuf(nullptr), mBufLen(0) {
|
||||
// Install signal handler if it wasn't installed yet.
|
||||
InstallMmapFaultHandler();
|
||||
|
||||
// It's OK if aZipHandle is null (e.g. called from nsJARInputStream::Read
|
||||
// when mFd was already release), because no access to mmapped memory is made
|
||||
// in this case.
|
||||
if (aZipHandle && aZipHandle->mMap) {
|
||||
// Handle SIGBUS only when it's an mmaped zip file.
|
||||
mZipHandle = aZipHandle;
|
||||
}
|
||||
|
||||
SetThreadLocalScope();
|
||||
}
|
||||
|
||||
MmapAccessScope::~MmapAccessScope() {
|
||||
MOZ_RELEASE_ASSERT(sMmapAccessScope.get() == this);
|
||||
sMmapAccessScope.set(mPreviousScope);
|
||||
}
|
||||
|
||||
void MmapAccessScope::SetThreadLocalScope() {
|
||||
// mJmpBuf is set outside of this classs for reasons mentioned in the header
|
||||
// file, but we need to initialize the member here too to make Coverity happy.
|
||||
memset(mJmpBuf, 0, sizeof(sigjmp_buf));
|
||||
|
||||
// If MmapAccessScopes are nested, save the previous one and restore it in
|
||||
// the destructor.
|
||||
mPreviousScope = sMmapAccessScope.get();
|
||||
|
||||
// MmapAccessScope is now set up (except mJmpBuf for reasons mentioned in the
|
||||
// header file). Store the pointer in a thread-local variable sMmapAccessScope
|
||||
// so we can use it in the handler if the signal is triggered.
|
||||
sMmapAccessScope.set(this);
|
||||
}
|
||||
|
||||
bool MmapAccessScope::IsInsideBuffer(void* aPtr) {
|
||||
bool isIn;
|
||||
|
||||
if (mZipHandle) {
|
||||
isIn =
|
||||
aPtr >= mZipHandle->mFileStart &&
|
||||
aPtr < (void*)((char*)mZipHandle->mFileStart + mZipHandle->mTotalLen);
|
||||
} else {
|
||||
isIn = aPtr >= mBuf && aPtr < (void*)((char*)mBuf + mBufLen);
|
||||
}
|
||||
|
||||
return isIn;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,88 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MmapFaultHandler_h_
|
||||
#define MmapFaultHandler_h_
|
||||
|
||||
#if defined(XP_WIN)
|
||||
// Windows
|
||||
|
||||
# ifdef HAVE_SEH_EXCEPTIONS
|
||||
# define MMAP_FAULT_HANDLER_BEGIN_HANDLE(fd) __try {
|
||||
# define MMAP_FAULT_HANDLER_BEGIN_BUFFER(buf, bufLen) __try {
|
||||
# define MMAP_FAULT_HANDLER_CATCH(retval) \
|
||||
} \
|
||||
__except (GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR \
|
||||
? EXCEPTION_EXECUTE_HANDLER \
|
||||
: EXCEPTION_CONTINUE_SEARCH) { \
|
||||
NS_WARNING("unexpected EXCEPTION_IN_PAGE_ERROR"); \
|
||||
return retval; \
|
||||
}
|
||||
# else
|
||||
# define MMAP_FAULT_HANDLER_BEGIN_HANDLE(fd) {
|
||||
# define MMAP_FAULT_HANDLER_BEGIN_BUFFER(buf, bufLen) {
|
||||
# define MMAP_FAULT_HANDLER_CATCH(retval) }
|
||||
# endif
|
||||
|
||||
#elif defined(XP_DARWIN)
|
||||
// MacOS
|
||||
|
||||
# define MMAP_FAULT_HANDLER_BEGIN_HANDLE(fd) {
|
||||
# define MMAP_FAULT_HANDLER_BEGIN_BUFFER(buf, bufLen) {
|
||||
# define MMAP_FAULT_HANDLER_CATCH(retval) }
|
||||
|
||||
#else
|
||||
// Linux
|
||||
|
||||
# include "mozilla/RefPtr.h"
|
||||
# include "mozilla/GuardObjects.h"
|
||||
# include <stdint.h>
|
||||
# include <setjmp.h>
|
||||
|
||||
class nsZipHandle;
|
||||
|
||||
class MOZ_RAII MmapAccessScope {
|
||||
public:
|
||||
MmapAccessScope(void* aBuf, uint32_t aBufLen);
|
||||
explicit MmapAccessScope(nsZipHandle* aZipHandle);
|
||||
~MmapAccessScope();
|
||||
|
||||
MmapAccessScope(const MmapAccessScope&) = delete;
|
||||
MmapAccessScope& operator=(const MmapAccessScope&) = delete;
|
||||
|
||||
void SetThreadLocalScope();
|
||||
bool IsInsideBuffer(void* aPtr);
|
||||
|
||||
// sigsetjmp cannot be called from a method that returns before calling
|
||||
// siglongjmp, so the macro must call sigsetjmp directly and mJmpBuf must be
|
||||
// public.
|
||||
sigjmp_buf mJmpBuf;
|
||||
|
||||
private:
|
||||
void* mBuf;
|
||||
uint32_t mBufLen;
|
||||
RefPtr<nsZipHandle> mZipHandle;
|
||||
MmapAccessScope* mPreviousScope;
|
||||
};
|
||||
|
||||
# define MMAP_FAULT_HANDLER_BEGIN_HANDLE(fd) \
|
||||
{ \
|
||||
MmapAccessScope mmapScope(fd); \
|
||||
if (sigsetjmp(mmapScope.mJmpBuf, 0) == 0) {
|
||||
# define MMAP_FAULT_HANDLER_BEGIN_BUFFER(buf, bufLen) \
|
||||
{ \
|
||||
MmapAccessScope mmapScope((void*)(buf), (bufLen)); \
|
||||
if (sigsetjmp(mmapScope.mJmpBuf, 0) == 0) {
|
||||
# define MMAP_FAULT_HANDLER_CATCH(retval) \
|
||||
} \
|
||||
else { \
|
||||
NS_WARNING("SIGBUS received when accessing mmapped file"); \
|
||||
return retval; \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -30,6 +30,7 @@ EXPORTS += [
|
|||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'MmapFaultHandler.cpp',
|
||||
'nsJAR.cpp',
|
||||
'nsJARChannel.cpp',
|
||||
'nsJARInputStream.cpp',
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
# include "brotli/decode.h" // brotli
|
||||
#endif
|
||||
#include "nsZipArchive.h"
|
||||
#include "MmapFaultHandler.h"
|
||||
|
||||
#include "nsEscape.h"
|
||||
#include "nsIFile.h"
|
||||
|
@ -193,7 +194,7 @@ nsJARInputStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytesRead) {
|
|||
*aBytesRead = 0;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
MOZ_WIN_MEM_TRY_BEGIN
|
||||
MMAP_FAULT_HANDLER_BEGIN_HANDLE(mFd)
|
||||
switch (mMode) {
|
||||
case MODE_NOTINITED:
|
||||
return NS_OK;
|
||||
|
@ -235,7 +236,7 @@ nsJARInputStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytesRead) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
MOZ_WIN_MEM_TRY_CATCH(rv = NS_ERROR_FAILURE)
|
||||
MMAP_FAULT_HANDLER_CATCH(NS_ERROR_FAILURE)
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
# include "brotli/decode.h" // brotli
|
||||
#endif
|
||||
#include "nsISupportsUtils.h"
|
||||
#include "MmapFaultHandler.h"
|
||||
#include "prio.h"
|
||||
#include "plstr.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
@ -278,7 +279,7 @@ nsresult nsZipHandle::findDataStart() {
|
|||
// type |uint8_t|, which is guaranteed to be 8 bits.
|
||||
const uint32_t CRXIntSize = 4;
|
||||
|
||||
MOZ_WIN_MEM_TRY_BEGIN
|
||||
MMAP_FAULT_HANDLER_BEGIN_HANDLE(this)
|
||||
if (mTotalLen > CRXIntSize * 4 && xtolong(mFileStart) == kCRXMagic) {
|
||||
const uint8_t* headerData = mFileStart;
|
||||
headerData += CRXIntSize * 2; // Skip magic number and version number
|
||||
|
@ -294,7 +295,7 @@ nsresult nsZipHandle::findDataStart() {
|
|||
}
|
||||
mLen = mTotalLen;
|
||||
mFileData = mFileStart;
|
||||
MOZ_WIN_MEM_TRY_CATCH(return NS_ERROR_FAILURE)
|
||||
MMAP_FAULT_HANDLER_CATCH(NS_ERROR_FAILURE)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -466,7 +467,7 @@ nsZipItem* nsZipArchive::GetItem(const char* aEntryName) {
|
|||
if (BuildSynthetics() != NS_OK) return 0;
|
||||
}
|
||||
}
|
||||
MOZ_WIN_MEM_TRY_BEGIN
|
||||
MMAP_FAULT_HANDLER_BEGIN_HANDLE(mFd)
|
||||
nsZipItem* item = mFiles[HashName(aEntryName, len)];
|
||||
while (item) {
|
||||
if ((len == item->nameLength) &&
|
||||
|
@ -480,7 +481,7 @@ nsZipItem* nsZipArchive::GetItem(const char* aEntryName) {
|
|||
}
|
||||
item = item->next;
|
||||
}
|
||||
MOZ_WIN_MEM_TRY_CATCH(return nullptr)
|
||||
MMAP_FAULT_HANDLER_CATCH(nullptr)
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -591,7 +592,7 @@ nsresult nsZipFind::FindNext(const char** aResult, uint16_t* aNameLen) {
|
|||
|
||||
*aResult = 0;
|
||||
*aNameLen = 0;
|
||||
MOZ_WIN_MEM_TRY_BEGIN
|
||||
MMAP_FAULT_HANDLER_BEGIN_HANDLE(mArchive->GetFD())
|
||||
// we start from last match, look for next
|
||||
while (mSlot < ZIP_TABSIZE) {
|
||||
// move to next in current chain, or move to new slot
|
||||
|
@ -617,7 +618,7 @@ nsresult nsZipFind::FindNext(const char** aResult, uint16_t* aNameLen) {
|
|||
return NS_OK;
|
||||
}
|
||||
}
|
||||
MOZ_WIN_MEM_TRY_CATCH(return NS_ERROR_FAILURE)
|
||||
MMAP_FAULT_HANDLER_CATCH(NS_ERROR_FAILURE)
|
||||
return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST;
|
||||
}
|
||||
|
||||
|
@ -641,7 +642,7 @@ nsresult nsZipArchive::BuildFileList(PRFileDesc* aFd) {
|
|||
const uint8_t* buf;
|
||||
const uint8_t* startp = mFd->mFileData;
|
||||
const uint8_t* endp = startp + mFd->mLen;
|
||||
MOZ_WIN_MEM_TRY_BEGIN
|
||||
MMAP_FAULT_HANDLER_BEGIN_HANDLE(mFd)
|
||||
uint32_t centralOffset = 4;
|
||||
// Only perform readahead in the parent process. Children processes
|
||||
// don't need readahead when the file has already been readahead by
|
||||
|
@ -734,7 +735,7 @@ nsresult nsZipArchive::BuildFileList(PRFileDesc* aFd) {
|
|||
}
|
||||
}
|
||||
|
||||
MOZ_WIN_MEM_TRY_CATCH(return NS_ERROR_FAILURE)
|
||||
MMAP_FAULT_HANDLER_CATCH(NS_ERROR_FAILURE)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -745,7 +746,7 @@ nsresult nsZipArchive::BuildSynthetics() {
|
|||
if (mBuiltSynthetics) return NS_OK;
|
||||
mBuiltSynthetics = true;
|
||||
|
||||
MOZ_WIN_MEM_TRY_BEGIN
|
||||
MMAP_FAULT_HANDLER_BEGIN_HANDLE(mFd)
|
||||
// Create synthetic entries for any missing directories.
|
||||
// Do this when all ziptable has scanned to prevent double entries.
|
||||
for (auto* item : mFiles) {
|
||||
|
@ -799,7 +800,7 @@ nsresult nsZipArchive::BuildSynthetics() {
|
|||
} /* end processing of dirs in item's name */
|
||||
}
|
||||
}
|
||||
MOZ_WIN_MEM_TRY_CATCH(return NS_ERROR_FAILURE)
|
||||
MMAP_FAULT_HANDLER_CATCH(NS_ERROR_FAILURE)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -813,12 +814,14 @@ nsZipHandle* nsZipArchive::GetFD() {
|
|||
//---------------------------------------------
|
||||
uint32_t nsZipArchive::GetDataOffset(nsZipItem* aItem) {
|
||||
MOZ_ASSERT(aItem);
|
||||
MOZ_WIN_MEM_TRY_BEGIN
|
||||
|
||||
uint32_t offset;
|
||||
MMAP_FAULT_HANDLER_BEGIN_HANDLE(mFd)
|
||||
//-- read local header to get variable length values and calculate
|
||||
//-- the real data offset
|
||||
uint32_t len = mFd->mLen;
|
||||
const uint8_t* data = mFd->mFileData;
|
||||
uint32_t offset = aItem->LocalOffset();
|
||||
offset = aItem->LocalOffset();
|
||||
if (len < ZIPLOCAL_SIZE || offset > len - ZIPLOCAL_SIZE) return 0;
|
||||
|
||||
// -- check signature before using the structure, in case the zip file is
|
||||
|
@ -832,8 +835,8 @@ uint32_t nsZipArchive::GetDataOffset(nsZipItem* aItem) {
|
|||
offset += ZIPLOCAL_SIZE + xtoint(Local->filename_len) +
|
||||
xtoint(Local->extrafield_len);
|
||||
|
||||
MMAP_FAULT_HANDLER_CATCH(0)
|
||||
return offset;
|
||||
MOZ_WIN_MEM_TRY_CATCH(return 0)
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
|
@ -841,25 +844,25 @@ uint32_t nsZipArchive::GetDataOffset(nsZipItem* aItem) {
|
|||
//---------------------------------------------
|
||||
const uint8_t* nsZipArchive::GetData(nsZipItem* aItem) {
|
||||
MOZ_ASSERT(aItem);
|
||||
MOZ_WIN_MEM_TRY_BEGIN
|
||||
uint32_t offset = GetDataOffset(aItem);
|
||||
|
||||
MMAP_FAULT_HANDLER_BEGIN_HANDLE(mFd)
|
||||
// -- check if there is enough source data in the file
|
||||
if (!offset || mFd->mLen < aItem->Size() ||
|
||||
offset > mFd->mLen - aItem->Size() ||
|
||||
(aItem->Compression() == STORED && aItem->Size() != aItem->RealSize())) {
|
||||
return nullptr;
|
||||
}
|
||||
MMAP_FAULT_HANDLER_CATCH(nullptr)
|
||||
|
||||
return mFd->mFileData + offset;
|
||||
MOZ_WIN_MEM_TRY_CATCH(return nullptr)
|
||||
}
|
||||
|
||||
// nsZipArchive::GetComment
|
||||
bool nsZipArchive::GetComment(nsACString& aComment) {
|
||||
MOZ_WIN_MEM_TRY_BEGIN
|
||||
MMAP_FAULT_HANDLER_BEGIN_BUFFER(mCommentPtr, mCommentLen)
|
||||
aComment.Assign(mCommentPtr, mCommentLen);
|
||||
MOZ_WIN_MEM_TRY_CATCH(return false)
|
||||
MMAP_FAULT_HANDLER_CATCH(false)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1024,13 +1027,19 @@ uint16_t nsZipItem::Mode() {
|
|||
|
||||
const uint8_t* nsZipItem::GetExtraField(uint16_t aTag, uint16_t* aBlockSize) {
|
||||
if (isSynthetic) return nullptr;
|
||||
MOZ_WIN_MEM_TRY_BEGIN
|
||||
|
||||
const unsigned char* buf =
|
||||
((const unsigned char*)central) + ZIPCENTRAL_SIZE + nameLength;
|
||||
uint32_t buflen = (uint32_t)xtoint(central->extrafield_len);
|
||||
uint32_t buflen;
|
||||
|
||||
MMAP_FAULT_HANDLER_BEGIN_BUFFER(central, ZIPCENTRAL_SIZE + nameLength)
|
||||
buflen = (uint32_t)xtoint(central->extrafield_len);
|
||||
MMAP_FAULT_HANDLER_CATCH(nullptr)
|
||||
|
||||
uint32_t pos = 0;
|
||||
uint16_t tag, blocksize;
|
||||
|
||||
MMAP_FAULT_HANDLER_BEGIN_BUFFER(buf, buflen)
|
||||
while (buf && (pos + 4) <= buflen) {
|
||||
tag = xtoint(buf + pos);
|
||||
blocksize = xtoint(buf + pos + 2);
|
||||
|
@ -1042,8 +1051,8 @@ const uint8_t* nsZipItem::GetExtraField(uint16_t aTag, uint16_t* aBlockSize) {
|
|||
|
||||
pos += blocksize + 4;
|
||||
}
|
||||
MMAP_FAULT_HANDLER_CATCH(nullptr)
|
||||
|
||||
MOZ_WIN_MEM_TRY_CATCH(return nullptr)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -1111,7 +1120,7 @@ uint8_t* nsZipCursor::ReadOrCopy(uint32_t* aBytesRead, bool aCopy) {
|
|||
bool verifyCRC = true;
|
||||
|
||||
if (!mZs.next_in) return nullptr;
|
||||
MOZ_WIN_MEM_TRY_BEGIN
|
||||
MMAP_FAULT_HANDLER_BEGIN_BUFFER(mZs.next_in, mZs.avail_in)
|
||||
switch (mItem->Compression()) {
|
||||
case STORED:
|
||||
if (!aCopy) {
|
||||
|
@ -1170,7 +1179,7 @@ uint8_t* nsZipCursor::ReadOrCopy(uint32_t* aBytesRead, bool aCopy) {
|
|||
mCRC = crc32(mCRC, (const unsigned char*)buf, *aBytesRead);
|
||||
if (verifyCRC && mCRC != mItem->CRC32()) return nullptr;
|
||||
}
|
||||
MOZ_WIN_MEM_TRY_CATCH(return nullptr)
|
||||
MMAP_FAULT_HANDLER_CATCH(nullptr)
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,21 +22,6 @@
|
|||
#include "mozilla/FileLocation.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
#ifdef HAVE_SEH_EXCEPTIONS
|
||||
# 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("unexpected EXCEPTION_IN_PAGE_ERROR"); \
|
||||
cmd; \
|
||||
}
|
||||
#else
|
||||
# define MOZ_WIN_MEM_TRY_BEGIN {
|
||||
# define MOZ_WIN_MEM_TRY_CATCH(cmd) }
|
||||
#endif
|
||||
|
||||
class nsZipFind;
|
||||
struct PRFileDesc;
|
||||
#ifdef MOZ_JAR_BROTLI
|
||||
|
@ -381,7 +366,12 @@ class nsZipItemPtr final : public nsZipItemPtr_base {
|
|||
|
||||
class nsZipHandle final {
|
||||
friend class nsZipArchive;
|
||||
friend class nsZipFind;
|
||||
friend class mozilla::FileLocation;
|
||||
friend class nsJARInputStream;
|
||||
#if defined(XP_UNIX) && !defined(XP_DARWIN)
|
||||
friend class MmapAccessScope;
|
||||
#endif
|
||||
|
||||
public:
|
||||
static nsresult Init(nsIFile* file, nsZipHandle** ret,
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
// Test checks SIGBUS handling on Linux. The test cannot be used to check page
|
||||
// error exception on Windows because the file cannot be truncated while it's
|
||||
// being used by zipreader.
|
||||
function run_test() {
|
||||
var file = do_get_file("data/test_bug333423.zip");
|
||||
var tmpFile = do_get_tempdir();
|
||||
|
||||
file.copyTo(tmpFile, "bug1550815.zip");
|
||||
tmpFile.append("bug1550815.zip");
|
||||
|
||||
var zipReader = Cc["@mozilla.org/libjar/zip-reader;1"].createInstance(
|
||||
Ci.nsIZipReader
|
||||
);
|
||||
zipReader.open(tmpFile);
|
||||
|
||||
// Truncate the file
|
||||
var ostream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(
|
||||
Ci.nsIFileOutputStream
|
||||
);
|
||||
ostream.init(tmpFile, -1, -1, 0);
|
||||
ostream.close();
|
||||
|
||||
try {
|
||||
zipReader.test("modules/libjar/test/Makefile.in");
|
||||
Assert.ok(false, "Should not reach here.");
|
||||
} catch (e) {
|
||||
Assert.equal(e.result, Cr.NS_ERROR_FILE_TARGET_DOES_NOT_EXIST);
|
||||
}
|
||||
|
||||
zipReader.close();
|
||||
tmpFile.remove(false);
|
||||
}
|
|
@ -41,3 +41,5 @@ skip-if = os == "mac"
|
|||
[test_uncompressed.js]
|
||||
[test_umlaute.js]
|
||||
[test_bug1328865.js]
|
||||
[test_bug1550815.js]
|
||||
skip-if = os != "linux"
|
||||
|
|
Загрузка…
Ссылка в новой задаче