Bug 1353684 - nsIFileInputStream must return NS_ERROR_NOT_FOUND if Deserialize() fails, r=smaug

This commit is contained in:
Andrea Marchesini 2017-04-20 13:39:51 +02:00
Родитель 54c9498baf
Коммит e1cf92c22c
3 изменённых файлов: 78 добавлений и 62 удалений

Просмотреть файл

@ -158,7 +158,7 @@ onmessage = function(message) {
expectedTestCount++;
r = new FileReader();
r.onload = getLoadHandler(convertToDataURL(""), 0, "empt binary string reading");
r.onload = getLoadHandler(convertToDataURL(""), 0, "empty binary string reading");
r.readAsDataURL(emptyFile);
expectedTestCount++;

Просмотреть файл

@ -40,7 +40,8 @@ using mozilla::Some;
nsFileStreamBase::nsFileStreamBase()
: mFD(nullptr)
, mBehaviorFlags(0)
, mDeferredOpen(false)
, mState(eUnitialized)
, mErrorValue(NS_ERROR_FAILURE)
{
}
@ -59,9 +60,6 @@ nsFileStreamBase::Seek(int32_t whence, int64_t offset)
nsresult rv = DoPendingOpen();
NS_ENSURE_SUCCESS(rv, rv);
if (mFD == nullptr)
return NS_BASE_STREAM_CLOSED;
int64_t cnt = PR_Seek64(mFD, offset, (PRSeekWhence)whence);
if (cnt == int64_t(-1)) {
return NS_ErrorAccordingToNSPR();
@ -75,9 +73,6 @@ nsFileStreamBase::Tell(int64_t *result)
nsresult rv = DoPendingOpen();
NS_ENSURE_SUCCESS(rv, rv);
if (mFD == nullptr)
return NS_BASE_STREAM_CLOSED;
int64_t cnt = PR_Seek64(mFD, 0, PR_SEEK_CUR);
if (cnt == int64_t(-1)) {
return NS_ErrorAccordingToNSPR();
@ -92,9 +87,6 @@ nsFileStreamBase::SetEOF()
nsresult rv = DoPendingOpen();
NS_ENSURE_SUCCESS(rv, rv);
if (mFD == nullptr)
return NS_BASE_STREAM_CLOSED;
#if defined(XP_UNIX) || defined(XP_BEOS)
// Some system calls require an EOF offset.
int64_t offset;
@ -125,10 +117,6 @@ nsFileStreamBase::GetSize(int64_t* _retval)
nsresult rv = DoPendingOpen();
NS_ENSURE_SUCCESS(rv, rv);
if (!mFD) {
return NS_BASE_STREAM_CLOSED;
}
PRFileInfo64 info;
if (PR_GetOpenFileInfo64(mFD, &info) == PR_FAILURE) {
return NS_BASE_STREAM_OSERROR;
@ -145,10 +133,6 @@ nsFileStreamBase::GetLastModified(int64_t* _retval)
nsresult rv = DoPendingOpen();
NS_ENSURE_SUCCESS(rv, rv);
if (!mFD) {
return NS_BASE_STREAM_CLOSED;
}
PRFileInfo64 info;
if (PR_GetOpenFileInfo64(mFD, &info) == PR_FAILURE) {
return NS_BASE_STREAM_OSERROR;
@ -169,13 +153,7 @@ NS_IMETHODIMP
nsFileStreamBase::GetFileDescriptor(PRFileDesc** _retval)
{
nsresult rv = DoPendingOpen();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (!mFD) {
return NS_BASE_STREAM_CLOSED;
}
NS_ENSURE_SUCCESS(rv, rv);
*_retval = mFD;
return NS_OK;
@ -191,6 +169,7 @@ nsFileStreamBase::Close()
if (PR_Close(mFD) == PR_FAILURE)
rv = NS_BASE_STREAM_OSERROR;
mFD = nullptr;
mState = eClosed;
}
return rv;
}
@ -201,10 +180,6 @@ nsFileStreamBase::Available(uint64_t* aResult)
nsresult rv = DoPendingOpen();
NS_ENSURE_SUCCESS(rv, rv);
if (!mFD) {
return NS_BASE_STREAM_CLOSED;
}
// PR_Available with files over 4GB returns an error, so we have to
// use the 64-bit version of PR_Available.
int64_t avail = PR_Available64(mFD);
@ -221,18 +196,15 @@ nsresult
nsFileStreamBase::Read(char* aBuf, uint32_t aCount, uint32_t* aResult)
{
nsresult rv = DoPendingOpen();
if (rv == NS_ERROR_FILE_NOT_FOUND) {
// Don't warn if this is just a deferred file not found.
return rv;
}
NS_ENSURE_SUCCESS(rv, rv);
if (!mFD) {
if (rv == NS_BASE_STREAM_CLOSED) {
*aResult = 0;
return NS_OK;
}
if (NS_FAILED(rv)) {
return rv;
}
int32_t bytesRead = PR_Read(mFD, aBuf, aCount);
if (bytesRead == -1) {
return NS_ErrorAccordingToNSPR();
@ -267,9 +239,6 @@ nsFileStreamBase::Flush(void)
nsresult rv = DoPendingOpen();
NS_ENSURE_SUCCESS(rv, rv);
if (mFD == nullptr)
return NS_BASE_STREAM_CLOSED;
int32_t cnt = PR_Sync(mFD);
if (cnt == -1) {
return NS_ErrorAccordingToNSPR();
@ -283,9 +252,6 @@ nsFileStreamBase::Write(const char *buf, uint32_t count, uint32_t *result)
nsresult rv = DoPendingOpen();
NS_ENSURE_SUCCESS(rv, rv);
if (mFD == nullptr)
return NS_BASE_STREAM_CLOSED;
int32_t cnt = PR_Write(mFD, buf, count);
if (cnt == -1) {
return NS_ErrorAccordingToNSPR();
@ -331,7 +297,7 @@ nsFileStreamBase::MaybeOpen(nsIFile* aFile, int32_t aIoFlags,
mOpenParams.localFile = do_QueryInterface(file);
NS_ENSURE_TRUE(mOpenParams.localFile, NS_ERROR_UNEXPECTED);
mDeferredOpen = true;
mState = eDeferredOpen;
return NS_OK;
}
@ -346,12 +312,13 @@ void
nsFileStreamBase::CleanUpOpen()
{
mOpenParams.localFile = nullptr;
mDeferredOpen = false;
}
nsresult
nsFileStreamBase::DoOpen()
{
MOZ_ASSERT(mState == eDeferredOpen || mState == eUnitialized ||
mState == eClosed);
NS_ASSERTION(!mFD, "Already have a file descriptor!");
NS_ASSERTION(mOpenParams.localFile, "Must have a file to open");
@ -375,9 +342,14 @@ nsFileStreamBase::DoOpen()
}
CleanUpOpen();
if (NS_FAILED(rv))
if (NS_FAILED(rv)) {
mState = eError;
mErrorValue = rv;
return rv;
}
mFD = fd;
mState = eOpened;
return NS_OK;
}
@ -385,13 +357,31 @@ nsFileStreamBase::DoOpen()
nsresult
nsFileStreamBase::DoPendingOpen()
{
if (!mDeferredOpen) {
switch (mState) {
case eUnitialized:
MOZ_CRASH("This should not happen.");
return NS_ERROR_FAILURE;
case eDeferredOpen:
return DoOpen();
case eOpened:
MOZ_ASSERT(mFD);
return NS_OK;
case eClosed:
MOZ_ASSERT(!mFD);
return NS_BASE_STREAM_CLOSED;
case eError:
return mErrorValue;
}
return DoOpen();
MOZ_CRASH("Invalid mState value.");
return NS_ERROR_FAILURE;
}
////////////////////////////////////////////////////////////////////////////////
// nsFileInputStream
@ -475,9 +465,11 @@ nsFileInputStream::Init(nsIFile* aFile, int32_t aIOFlags, int32_t aPerm,
int32_t aBehaviorFlags)
{
NS_ENSURE_TRUE(!mFD, NS_ERROR_ALREADY_INITIALIZED);
NS_ENSURE_TRUE(!mDeferredOpen, NS_ERROR_ALREADY_INITIALIZED);
NS_ENSURE_TRUE(mState == eUnitialized || mState == eClosed,
NS_ERROR_ALREADY_INITIALIZED);
mBehaviorFlags = aBehaviorFlags;
mState = eUnitialized;
mFile = aFile;
mIOFlags = aIOFlags;
@ -550,12 +542,15 @@ nsresult
nsFileInputStream::SeekInternal(int32_t aWhence, int64_t aOffset, bool aClearBuf)
{
nsresult rv = DoPendingOpen();
NS_ENSURE_SUCCESS(rv, rv);
if (rv != NS_OK && rv != NS_BASE_STREAM_CLOSED) {
return rv;
}
if (aClearBuf) {
mLineBuffer = nullptr;
}
if (!mFD) {
if (rv == NS_BASE_STREAM_CLOSED) {
if (mBehaviorFlags & REOPEN_ON_REWIND) {
rv = Open(mFile, mIOFlags, mPerm);
NS_ENSURE_SUCCESS(rv, rv);
@ -593,7 +588,8 @@ nsFileInputStream::Serialize(InputStreamParams& aParams,
{
FileInputStreamParams params;
if (NS_SUCCEEDED(DoPendingOpen()) && mFD) {
if (NS_SUCCEEDED(DoPendingOpen())) {
MOZ_ASSERT(mFD);
FileHandleType fd = FileHandleType(PR_FileDesc2NativeHandle(mFD));
NS_ASSERTION(fd, "This should never be null!");
@ -627,7 +623,7 @@ nsFileInputStream::Deserialize(const InputStreamParams& aParams,
const FileDescriptorArray& aFileDescriptors)
{
NS_ASSERTION(!mFD, "Already have a file descriptor?!");
NS_ASSERTION(!mDeferredOpen, "Deferring open?!");
NS_ASSERTION(mState == nsFileStreamBase::eUnitialized, "Deferring open?!");
NS_ASSERTION(!mFile, "Should never have a file here!");
NS_ASSERTION(!mPerm, "This should always be 0!");
@ -657,6 +653,10 @@ nsFileInputStream::Deserialize(const InputStreamParams& aParams,
return false;
}
mFD = fileDesc;
mState = eOpened;
} else {
mState = eError;
mErrorValue = NS_ERROR_FILE_NOT_FOUND;
}
mBehaviorFlags = params.behaviorFlags();
@ -709,9 +709,11 @@ nsFileOutputStream::Init(nsIFile* file, int32_t ioFlags, int32_t perm,
int32_t behaviorFlags)
{
NS_ENSURE_TRUE(mFD == nullptr, NS_ERROR_ALREADY_INITIALIZED);
NS_ENSURE_TRUE(!mDeferredOpen, NS_ERROR_ALREADY_INITIALIZED);
NS_ENSURE_TRUE(mState == eUnitialized || mState == eClosed,
NS_ERROR_ALREADY_INITIALIZED);
mBehaviorFlags = behaviorFlags;
mState = eUnitialized;
if (ioFlags == -1)
ioFlags = PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE;
@ -911,9 +913,11 @@ nsFileStream::Init(nsIFile* file, int32_t ioFlags, int32_t perm,
int32_t behaviorFlags)
{
NS_ENSURE_TRUE(mFD == nullptr, NS_ERROR_ALREADY_INITIALIZED);
NS_ENSURE_TRUE(!mDeferredOpen, NS_ERROR_ALREADY_INITIALIZED);
NS_ENSURE_TRUE(mState == eUnitialized || mState == eClosed,
NS_ERROR_ALREADY_INITIALIZED);
mBehaviorFlags = behaviorFlags;
mState = eUnitialized;
if (ioFlags == -1)
ioFlags = PR_RDWR;

Просмотреть файл

@ -55,10 +55,19 @@ protected:
*/
int32_t mBehaviorFlags;
/**
* Whether we have a pending open (see DEFER_OPEN in the IDL file).
*/
bool mDeferredOpen;
enum {
// This is the default value. It will be changed by Deserialize or Init.
eUnitialized,
// The opening has been deferred. See DEFER_OPEN.
eDeferredOpen,
// The file has been opened. mFD is not null.
eOpened,
// The file has been closed. mFD is null.
eClosed,
// Something bad happen in the Open() or in Deserialize(). The actual
// error value is stored in mErrorValue.
eError
} mState;
struct OpenParams {
nsCOMPtr<nsIFile> localFile;
@ -71,6 +80,8 @@ protected:
*/
OpenParams mOpenParams;
nsresult mErrorValue;
/**
* Prepares the data we need to open the file, and either does the open now
* by calling DoOpen(), or leaves it to be opened later by a call to
@ -93,8 +104,9 @@ protected:
virtual nsresult DoOpen();
/**
* If there is a pending open, do it now. It's important for this to be
* inline since we do it in almost every stream API call.
* Based on mState, this method does the opening, return an error, or do
* nothing. If the return value is not NS_OK, please, return it back to the
* callee.
*/
inline nsresult DoPendingOpen();
};