From 541453729c45887883d20f251c088a62e43d7d46 Mon Sep 17 00:00:00 2001 From: Honza Bambas Date: Fri, 10 Aug 2012 22:44:11 -0400 Subject: [PATCH] Bug 215450: Allow uploading of files greater than 2gb in size. Involves making input streams 64-bit capable. Significant work done by Makoto Kato, finished by Honza Bambas. r=hbambas,bsmedberg,jdrew,sicking --- content/base/src/nsFrameMessageManager.cpp | 8 +++- content/base/src/nsSyncLoadService.cpp | 10 +++-- content/base/src/nsXMLHttpRequest.cpp | 2 +- .../html/content/src/nsHTMLCanvasElement.cpp | 12 +++--- content/media/MediaResource.cpp | 12 +++--- .../xul/document/src/nsXULPrototypeCache.cpp | 13 +++++- dom/base/nsJSEnvironment.cpp | 4 +- dom/devicestorage/nsDeviceStorage.cpp | 18 +++++--- dom/file/ArchiveZipFile.cpp | 2 +- dom/file/FileStreamWrappers.cpp | 2 +- dom/indexedDB/FileStream.cpp | 2 +- dom/indexedDB/FileStream.h | 2 +- dom/ipc/Blob.cpp | 2 +- dom/src/json/nsJSON.cpp | 11 +++-- extensions/gio/nsGIOProtocolHandler.cpp | 11 ++--- .../gnomevfs/nsGnomeVFSProtocolHandler.cpp | 16 ++++--- .../pref/autoconfig/src/nsReadConfig.cpp | 13 ++++-- gfx/thebes/gfxASurface.cpp | 9 +++- image/encoders/bmp/nsBMPEncoder.cpp | 2 +- image/encoders/ico/nsICOEncoder.cpp | 2 +- image/encoders/jpeg/nsJPEGEncoder.cpp | 2 +- image/encoders/png/nsPNGEncoder.cpp | 2 +- image/src/imgTools.cpp | 5 ++- js/xpconnect/loader/mozJSComponentLoader.cpp | 9 ++-- layout/base/nsPresShell.cpp | 9 +++- layout/style/nsFontFaceLoader.cpp | 9 +++- modules/libjar/nsJAR.cpp | 8 ++-- modules/libjar/nsJARChannel.cpp | 7 ++- modules/libjar/nsJARInputStream.cpp | 2 +- modules/libpref/src/Preferences.cpp | 9 ++-- netwerk/base/public/nsNetUtil.h | 2 +- netwerk/base/src/nsBaseContentStream.cpp | 2 +- netwerk/base/src/nsBufferedStreams.cpp | 2 +- netwerk/base/src/nsDirectoryIndexStream.cpp | 2 +- netwerk/base/src/nsFileStreams.cpp | 10 ++--- netwerk/base/src/nsFileStreams.h | 10 ++--- netwerk/base/src/nsInputStreamChannel.cpp | 2 +- netwerk/base/src/nsInputStreamPump.cpp | 28 ++++++------ netwerk/base/src/nsMIMEInputStream.cpp | 6 +-- netwerk/base/src/nsPreloadedStream.cpp | 4 +- netwerk/base/src/nsSocketTransport2.cpp | 2 +- netwerk/base/src/nsStreamTransportService.cpp | 2 +- netwerk/base/src/nsSyncStreamListener.cpp | 14 +++--- netwerk/cache/nsCacheEntryDescriptor.cpp | 2 +- netwerk/cache/nsDiskCacheStreams.cpp | 2 +- netwerk/ipc/NeckoMessageUtils.h | 11 +++-- .../device/AndroidCaptureProvider.cpp | 2 +- .../protocol/device/GonkCaptureProvider.cpp | 2 +- netwerk/protocol/file/nsFileChannel.cpp | 5 ++- .../protocol/ftp/nsFtpConnectionThread.cpp | 2 +- netwerk/protocol/ftp/nsFtpConnectionThread.h | 2 +- .../protocol/ftp/nsFtpControlConnection.cpp | 8 ++-- netwerk/protocol/http/HttpBaseChannel.cpp | 43 +++++++------------ netwerk/protocol/http/NullHttpTransaction.cpp | 2 +- netwerk/protocol/http/SpdySession2.cpp | 2 +- netwerk/protocol/http/SpdySession3.cpp | 2 +- netwerk/protocol/http/nsAHttpTransaction.h | 4 +- netwerk/protocol/http/nsHttpConnection.cpp | 4 +- netwerk/protocol/http/nsHttpPipeline.cpp | 14 +++--- netwerk/protocol/http/nsHttpTransaction.cpp | 4 +- netwerk/protocol/http/nsHttpTransaction.h | 2 +- .../protocol/websocket/WebSocketChannel.cpp | 2 +- .../converters/nsFTPDirListingConv.cpp | 4 +- netwerk/streamconv/test/Converters.cpp | 20 ++++++++- netwerk/streamconv/test/TestStreamConv.cpp | 27 +++++++++--- parser/xml/src/nsSAXXMLReader.cpp | 11 +++-- rdf/base/src/nsRDFXMLDataSource.cpp | 9 ++-- security/manager/ssl/src/nsNSSComponent.cpp | 22 +++++----- startupcache/StartupCacheUtils.cpp | 9 ++-- .../components/places/nsFaviconService.cpp | 16 ++++--- widget/windows/WinUtils.cpp | 7 ++- xpcom/io/Base64.cpp | 8 +++- xpcom/io/nsBinaryStream.cpp | 2 +- xpcom/io/nsIInputStream.idl | 7 ++- xpcom/io/nsIScriptableInputStream.idl | 4 +- xpcom/io/nsInputStreamTee.cpp | 2 +- xpcom/io/nsMultiplexInputStream.cpp | 8 ++-- xpcom/io/nsPipe3.cpp | 5 ++- xpcom/io/nsScriptableInputStream.cpp | 8 ++-- xpcom/io/nsStorageStream.cpp | 2 +- xpcom/io/nsStreamUtils.cpp | 13 +++--- xpcom/io/nsStringStream.cpp | 2 +- xpcom/tests/TestBase64.cpp | 2 +- 83 files changed, 363 insertions(+), 241 deletions(-) diff --git a/content/base/src/nsFrameMessageManager.cpp b/content/base/src/nsFrameMessageManager.cpp index 4d4891577c0..c4c50facb3e 100644 --- a/content/base/src/nsFrameMessageManager.cpp +++ b/content/base/src/nsFrameMessageManager.cpp @@ -808,9 +808,13 @@ nsFrameScriptExecutor::LoadFrameScriptInternal(const nsAString& aURL) nsCOMPtr input; channel->Open(getter_AddRefs(input)); nsString dataString; - PRUint32 avail = 0; - if (input && NS_SUCCEEDED(input->Available(&avail)) && avail) { + PRUint64 avail64 = 0; + if (input && NS_SUCCEEDED(input->Available(&avail64)) && avail64) { + if (avail64 > PR_UINT32_MAX) { + return; + } nsCString buffer; + PRUint32 avail = (PRUint32)NS_MIN(avail64, (PRUint64)PR_UINT32_MAX); if (NS_FAILED(NS_ReadInputStreamToString(input, buffer, avail))) { return; } diff --git a/content/base/src/nsSyncLoadService.cpp b/content/base/src/nsSyncLoadService.cpp index b8e7ebe2de8..5cb3bf0b7d0 100644 --- a/content/base/src/nsSyncLoadService.cpp +++ b/content/base/src/nsSyncLoadService.cpp @@ -352,9 +352,9 @@ nsSyncLoadService::PushSyncStreamToListener(nsIInputStream* aIn, // Load rv = aListener->OnStartRequest(aChannel, nullptr); if (NS_SUCCEEDED(rv)) { - PRUint32 sourceOffset = 0; + PRUint64 sourceOffset = 0; while (1) { - PRUint32 readCount = 0; + PRUint64 readCount = 0; rv = aIn->Available(&readCount); if (NS_FAILED(rv) || !readCount) { if (rv == NS_BASE_STREAM_CLOSED) { @@ -364,8 +364,12 @@ nsSyncLoadService::PushSyncStreamToListener(nsIInputStream* aIn, break; } + if (readCount > PR_UINT32_MAX) + readCount = PR_UINT32_MAX; + rv = aListener->OnDataAvailable(aChannel, nullptr, aIn, - sourceOffset, readCount); + (PRUint32)NS_MIN(sourceOffset, (PRUint64)PR_UINT32_MAX), + (PRUint32)readCount); if (NS_FAILED(rv)) { break; } diff --git a/content/base/src/nsXMLHttpRequest.cpp b/content/base/src/nsXMLHttpRequest.cpp index 8db6b159e41..602ff70316b 100644 --- a/content/base/src/nsXMLHttpRequest.cpp +++ b/content/base/src/nsXMLHttpRequest.cpp @@ -2962,7 +2962,7 @@ nsXMLHttpRequest::Send(nsIVariant* aVariant, const Nullable& aBody) } mUploadComplete = false; - PRUint32 uploadTotal = 0; + PRUint64 uploadTotal = 0; postDataStream->Available(&uploadTotal); mUploadTotal = uploadTotal; diff --git a/content/html/content/src/nsHTMLCanvasElement.cpp b/content/html/content/src/nsHTMLCanvasElement.cpp index f40a7ad6e16..0d605096b3d 100644 --- a/content/html/content/src/nsHTMLCanvasElement.cpp +++ b/content/html/content/src/nsHTMLCanvasElement.cpp @@ -359,11 +359,12 @@ nsHTMLCanvasElement::ToDataURLImpl(const nsAString& aMimeType, aDataURL = NS_LITERAL_STRING("data:") + type + NS_LITERAL_STRING(";base64,"); - PRUint32 count; + PRUint64 count; rv = stream->Available(&count); NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_TRUE(count <= PR_UINT32_MAX, NS_ERROR_FILE_TOO_BIG); - return Base64EncodeInputStream(stream, aDataURL, count, aDataURL.Length()); + return Base64EncodeInputStream(stream, aDataURL, (PRUint32)count, aDataURL.Length()); } NS_IMETHODIMP @@ -398,17 +399,18 @@ nsHTMLCanvasElement::MozGetAsFileImpl(const nsAString& aName, type.AssignLiteral("image/png"); } - PRUint32 imgSize; + PRUint64 imgSize; rv = stream->Available(&imgSize); NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_TRUE(imgSize <= PR_UINT32_MAX, NS_ERROR_FILE_TOO_BIG); void* imgData = nullptr; - rv = NS_ReadInputStreamToBuffer(stream, &imgData, imgSize); + rv = NS_ReadInputStreamToBuffer(stream, &imgData, (PRUint32)imgSize); NS_ENSURE_SUCCESS(rv, rv); // The DOMFile takes ownership of the buffer nsRefPtr file = - new nsDOMMemoryFile(imgData, imgSize, aName, type); + new nsDOMMemoryFile(imgData, (PRUint32)imgSize, aName, type); file.forget(aResult); return NS_OK; diff --git a/content/media/MediaResource.cpp b/content/media/MediaResource.cpp index db01f70d8b6..cdeed07cb8a 100644 --- a/content/media/MediaResource.cpp +++ b/content/media/MediaResource.cpp @@ -1053,13 +1053,13 @@ nsresult FileMediaResource::Open(nsIStreamListener** aStreamListener) return NS_ERROR_FAILURE; } - // Get the file size and inform the decoder. Only files up to 4GB are - // supported here. - PRUint32 size; + // Get the file size and inform the decoder. + PRUint64 size; rv = mInput->Available(&size); - if (NS_SUCCEEDED(rv)) { - mSize = size; - } + NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_TRUE(size <= PR_INT64_MAX, NS_ERROR_FILE_TOO_BIG); + + mSize = (PRInt64)size; nsCOMPtr event = new LoadedEvent(mDecoder); NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); diff --git a/content/xul/document/src/nsXULPrototypeCache.cpp b/content/xul/document/src/nsXULPrototypeCache.cpp index 58e1752051c..d66aafd559d 100644 --- a/content/xul/document/src/nsXULPrototypeCache.cpp +++ b/content/xul/document/src/nsXULPrototypeCache.cpp @@ -646,8 +646,17 @@ nsXULPrototypeCache::BeginCaching(nsIURI* aURI) rv = tmp; } } - if (NS_SUCCEEDED(rv)) - rv = inputStream->Available(&len); + + if (NS_SUCCEEDED(rv)) { + PRUint64 len64; + rv = inputStream->Available(&len64); + if (NS_SUCCEEDED(rv)) { + if (len64 <= PR_UINT32_MAX) + len = (PRUint32)len64; + else + rv = NS_ERROR_FILE_TOO_BIG; + } + } if (NS_SUCCEEDED(rv)) { buf = new char[len]; diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index e84f7c248ec..56cc73def99 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -3897,11 +3897,13 @@ ReadSourceFromFilename(JSContext *cx, const char *filename, jschar **src, PRUint rv = scriptChannel->Open(getter_AddRefs(scriptStream)); NS_ENSURE_SUCCESS(rv, rv); - PRUint32 rawLen; + PRUint64 rawLen; rv = scriptStream->Available(&rawLen); NS_ENSURE_SUCCESS(rv, rv); if (!rawLen) return NS_ERROR_FAILURE; + if (rawLen > PR_UINT32_MAX) + return NS_ERROR_FILE_TOO_BIG; // Allocate an internal buf the size of the file. nsAutoArrayPtr buf(new unsigned char[rawLen]); diff --git a/dom/devicestorage/nsDeviceStorage.cpp b/dom/devicestorage/nsDeviceStorage.cpp index 0c78017804c..1a8c963114b 100644 --- a/dom/devicestorage/nsDeviceStorage.cpp +++ b/dom/devicestorage/nsDeviceStorage.cpp @@ -158,7 +158,7 @@ DeviceStorageFile::Write(nsIInputStream* aInputStream) return rv; } - PRUint32 bufSize; + PRUint64 bufSize = 0; aInputStream->Available(&bufSize); nsCOMPtr outputStream; @@ -177,12 +177,20 @@ DeviceStorageFile::Write(nsIInputStream* aInputStream) return NS_ERROR_FAILURE; } - PRUint32 wrote; - bufferedOutputStream->WriteFrom(aInputStream, bufSize, &wrote); + rv = NS_OK; + while (bufSize) { + PRUint32 wrote; + rv = bufferedOutputStream->WriteFrom(aInputStream, static_cast(NS_MIN(bufSize, PR_UINT32_MAX)), &wrote); + if (NS_FAILED(rv)) { + break; + } + bufSize -= wrote; + } + bufferedOutputStream->Close(); outputStream->Close(); - if (bufSize != wrote) { - return NS_ERROR_FAILURE; + if (NS_FAILED(rv)) { + return rv; } return NS_OK; } diff --git a/dom/file/ArchiveZipFile.cpp b/dom/file/ArchiveZipFile.cpp index d543218875d..d1c99a1889e 100644 --- a/dom/file/ArchiveZipFile.cpp +++ b/dom/file/ArchiveZipFile.cpp @@ -169,7 +169,7 @@ ArchiveInputStream::Close() } NS_IMETHODIMP -ArchiveInputStream::Available(PRUint32* _retval) +ArchiveInputStream::Available(PRUint64* _retval) { *_retval = mLength - mZs.total_out - mStart; return NS_OK; diff --git a/dom/file/FileStreamWrappers.cpp b/dom/file/FileStreamWrappers.cpp index 1f457ba17f3..ac7bd03d0ce 100644 --- a/dom/file/FileStreamWrappers.cpp +++ b/dom/file/FileStreamWrappers.cpp @@ -139,7 +139,7 @@ FileInputStreamWrapper::Close() } NS_IMETHODIMP -FileInputStreamWrapper::Available(PRUint32* _retval) +FileInputStreamWrapper::Available(PRUint64* _retval) { // Performing sync IO on the main thread is generally not allowed. // However, the input stream wrapper is also used to track reads performed by diff --git a/dom/indexedDB/FileStream.cpp b/dom/indexedDB/FileStream.cpp index a6f47f67aee..7cf8ff1fb0a 100644 --- a/dom/indexedDB/FileStream.cpp +++ b/dom/indexedDB/FileStream.cpp @@ -114,7 +114,7 @@ FileStream::Close() } NS_IMETHODIMP -FileStream::Available(PRUint32* aResult) +FileStream::Available(PRUint64* aResult) { nsresult rv = DoPendingOpen(); NS_ENSURE_SUCCESS(rv, rv); diff --git a/dom/indexedDB/FileStream.h b/dom/indexedDB/FileStream.h index 84fb5b95fae..a5b8686afde 100644 --- a/dom/indexedDB/FileStream.h +++ b/dom/indexedDB/FileStream.h @@ -48,7 +48,7 @@ public: Close(); NS_IMETHOD - Available(PRUint32* _retval); + Available(PRUint64* _retval); NS_IMETHOD Read(char* aBuf, PRUint32 aCount, PRUint32* _retval); diff --git a/dom/ipc/Blob.cpp b/dom/ipc/Blob.cpp index 5c239aa6a09..a50044ecac4 100644 --- a/dom/ipc/Blob.cpp +++ b/dom/ipc/Blob.cpp @@ -84,7 +84,7 @@ public: } NS_IMETHOD - Available(PRUint32* aAvailable) MOZ_OVERRIDE + Available(PRUint64* aAvailable) MOZ_OVERRIDE { // See large comment in FileInputStreamWrapper::Available. if (NS_IsMainThread()) { diff --git a/dom/src/json/nsJSON.cpp b/dom/src/json/nsJSON.cpp index 660185dde0e..f9fcf79ce23 100644 --- a/dom/src/json/nsJSON.cpp +++ b/dom/src/json/nsJSON.cpp @@ -438,9 +438,9 @@ nsJSON::DecodeInternal(JSContext* cx, nsresult status; jsonChannel->GetStatus(&status); - PRUint32 offset = 0; + PRUint64 offset = 0; while (NS_SUCCEEDED(status)) { - PRUint32 available; + PRUint64 available; rv = aStream->Available(&available); if (rv == NS_BASE_STREAM_CLOSED) { rv = NS_OK; @@ -453,8 +453,13 @@ nsJSON::DecodeInternal(JSContext* cx, if (!available) break; // blocking input stream has none available when done + if (available > PR_UINT32_MAX) + available = PR_UINT32_MAX; + rv = jsonListener->OnDataAvailable(jsonChannel, nullptr, - aStream, offset, available); + aStream, + (PRUint32)NS_MIN(offset, (PRUint64)PR_UINT32_MAX), + (PRUint32)available); if (NS_FAILED(rv)) { jsonChannel->Cancel(rv); break; diff --git a/extensions/gio/nsGIOProtocolHandler.cpp b/extensions/gio/nsGIOProtocolHandler.cpp index 45928ceb792..c8ebcea3c62 100644 --- a/extensions/gio/nsGIOProtocolHandler.cpp +++ b/extensions/gio/nsGIOProtocolHandler.cpp @@ -145,7 +145,7 @@ class nsGIOInputStream : public nsIInputStream , mChannel(nullptr) , mHandle(nullptr) , mStream(nullptr) - , mBytesRemaining(PR_UINT32_MAX) + , mBytesRemaining(PR_UINT64_MAX) , mStatus(NS_OK) , mDirList(nullptr) , mDirListPtr(nullptr) @@ -634,17 +634,12 @@ nsGIOInputStream::Close() * @param aResult remaining bytes */ NS_IMETHODIMP -nsGIOInputStream::Available(PRUint32 *aResult) +nsGIOInputStream::Available(PRUint64 *aResult) { if (NS_FAILED(mStatus)) return mStatus; - /* When remaining bytes are bigger than max PRUint32 value an aResult must - be set to PRUint32 maximum */ - if (mBytesRemaining > PR_UINT32_MAX) - *aResult = PR_UINT32_MAX; - else - *aResult = mBytesRemaining; + *aResult = mBytesRemaining; return NS_OK; } diff --git a/extensions/gnomevfs/nsGnomeVFSProtocolHandler.cpp b/extensions/gnomevfs/nsGnomeVFSProtocolHandler.cpp index 2a5b86f20de..eaa55469bf9 100644 --- a/extensions/gnomevfs/nsGnomeVFSProtocolHandler.cpp +++ b/extensions/gnomevfs/nsGnomeVFSProtocolHandler.cpp @@ -319,7 +319,7 @@ class nsGnomeVFSInputStream MOZ_FINAL : public nsIInputStream : mSpec(uriSpec) , mChannel(nullptr) , mHandle(nullptr) - , mBytesRemaining(PR_UINT32_MAX) + , mBytesRemaining(PR_UINT64_MAX) , mStatus(NS_OK) , mDirList(nullptr) , mDirListPtr(nullptr) @@ -355,7 +355,7 @@ class nsGnomeVFSInputStream MOZ_FINAL : public nsIInputStream nsCString mSpec; nsIChannel *mChannel; // manually refcounted GnomeVFSHandle *mHandle; - PRUint32 mBytesRemaining; + PRUint64 mBytesRemaining; nsresult mStatus; GList *mDirList; GList *mDirListPtr; @@ -429,13 +429,14 @@ nsGnomeVFSInputStream::DoOpen() if (info.mime_type && (strcmp(info.mime_type, APPLICATION_OCTET_STREAM) != 0)) SetContentTypeOfChannel(info.mime_type); - // XXX truncates size from 64-bit to 32-bit - mBytesRemaining = (PRUint32) info.size; + mBytesRemaining = info.size; // Update the content length attribute on the channel. We do this // synchronously without proxying. This hack is not as bad as it looks! - if (mBytesRemaining != PR_UINT32_MAX) - mChannel->SetContentLength(mBytesRemaining); + if (mBytesRemaining != PR_UINT64_MAX) { + // XXX 64-bit + mChannel->SetContentLength(NS_MAX((PRInt32)mBytesRemaining, PR_INT32_MAX)); + } } else { @@ -478,6 +479,7 @@ nsGnomeVFSInputStream::DoRead(char *aBuf, PRUint32 aCount, PRUint32 *aCountRead) rv = gnome_vfs_read(mHandle, aBuf, aCount, &bytesRead); if (rv == GNOME_VFS_OK) { + // aCount is 32-bit, so aCountRead is under 32-bit value. *aCountRead = (PRUint32) bytesRead; mBytesRemaining -= *aCountRead; } @@ -668,7 +670,7 @@ nsGnomeVFSInputStream::Close() } NS_IMETHODIMP -nsGnomeVFSInputStream::Available(PRUint32 *aResult) +nsGnomeVFSInputStream::Available(PRUint64 *aResult) { if (NS_FAILED(mStatus)) return mStatus; diff --git a/extensions/pref/autoconfig/src/nsReadConfig.cpp b/extensions/pref/autoconfig/src/nsReadConfig.cpp index fa69ccd0f9a..3afd3e18080 100644 --- a/extensions/pref/autoconfig/src/nsReadConfig.cpp +++ b/extensions/pref/autoconfig/src/nsReadConfig.cpp @@ -278,14 +278,21 @@ nsresult nsReadConfig::openAndEvaluateJSFile(const char *aFileName, PRInt32 obsc return rv; } - PRUint32 fs, amt = 0; - inStr->Available(&fs); + PRUint64 fs64; + PRUint32 amt = 0; + rv = inStr->Available(&fs64); + if (NS_FAILED(rv)) + return rv; + // PR_Malloc dones't support over 4GB + if (fs64 > PR_UINT32_MAX) + return NS_ERROR_FILE_TOO_BIG; + PRUint32 fs = (PRUint32)fs64; char *buf = (char *)PR_Malloc(fs * sizeof(char)); if (!buf) return NS_ERROR_OUT_OF_MEMORY; - rv = inStr->Read(buf, fs, &amt); + rv = inStr->Read(buf, (PRUint32)fs, &amt); NS_ASSERTION((amt == fs), "failed to read the entire configuration file!!"); if (NS_SUCCEEDED(rv)) { if (obscureValue > 0) { diff --git a/gfx/thebes/gfxASurface.cpp b/gfx/thebes/gfxASurface.cpp index c171513dc94..04a4a1e51a0 100644 --- a/gfx/thebes/gfxASurface.cpp +++ b/gfx/thebes/gfxASurface.cpp @@ -749,11 +749,16 @@ gfxASurface::WriteAsPNG_internal(FILE* aFile, bool aBinary) if (!imgStream) return; - PRUint32 bufSize; - rv = imgStream->Available(&bufSize); + PRUint64 bufSize64; + rv = imgStream->Available(&bufSize64); if (NS_FAILED(rv)) return; + if (bufSize64 > PR_UINT32_MAX - 16) + return; + + PRUint32 bufSize = (PRUint32)bufSize64; + // ...leave a little extra room so we can call read again and make sure we // got everything. 16 bytes for better padding (maybe) bufSize += 16; diff --git a/image/encoders/bmp/nsBMPEncoder.cpp b/image/encoders/bmp/nsBMPEncoder.cpp index c218e084a46..99ec29d4bdc 100644 --- a/image/encoders/bmp/nsBMPEncoder.cpp +++ b/image/encoders/bmp/nsBMPEncoder.cpp @@ -321,7 +321,7 @@ NS_IMETHODIMP nsBMPEncoder::Close() } // Obtains the available bytes to read -NS_IMETHODIMP nsBMPEncoder::Available(PRUint32 *_retval) +NS_IMETHODIMP nsBMPEncoder::Available(PRUint64 *_retval) { if (!mImageBufferStart || !mImageBufferCurr) { return NS_BASE_STREAM_CLOSED; diff --git a/image/encoders/ico/nsICOEncoder.cpp b/image/encoders/ico/nsICOEncoder.cpp index 9e92865e863..c19f7603af0 100644 --- a/image/encoders/ico/nsICOEncoder.cpp +++ b/image/encoders/ico/nsICOEncoder.cpp @@ -334,7 +334,7 @@ NS_IMETHODIMP nsICOEncoder::Close() } // Obtains the available bytes to read -NS_IMETHODIMP nsICOEncoder::Available(PRUint32 *_retval) +NS_IMETHODIMP nsICOEncoder::Available(PRUint64 *_retval) { if (!mImageBufferStart || !mImageBufferCurr) { return NS_BASE_STREAM_CLOSED; diff --git a/image/encoders/jpeg/nsJPEGEncoder.cpp b/image/encoders/jpeg/nsJPEGEncoder.cpp index d0158b50c2d..572976a791d 100644 --- a/image/encoders/jpeg/nsJPEGEncoder.cpp +++ b/image/encoders/jpeg/nsJPEGEncoder.cpp @@ -236,7 +236,7 @@ NS_IMETHODIMP nsJPEGEncoder::Close() } /* unsigned long available (); */ -NS_IMETHODIMP nsJPEGEncoder::Available(PRUint32 *_retval) +NS_IMETHODIMP nsJPEGEncoder::Available(PRUint64 *_retval) { if (!mImageBuffer) return NS_BASE_STREAM_CLOSED; diff --git a/image/encoders/png/nsPNGEncoder.cpp b/image/encoders/png/nsPNGEncoder.cpp index 9224bf2c968..a26ca211fa7 100644 --- a/image/encoders/png/nsPNGEncoder.cpp +++ b/image/encoders/png/nsPNGEncoder.cpp @@ -492,7 +492,7 @@ NS_IMETHODIMP nsPNGEncoder::Close() } /* unsigned long available (); */ -NS_IMETHODIMP nsPNGEncoder::Available(PRUint32 *_retval) +NS_IMETHODIMP nsPNGEncoder::Available(PRUint64 *_retval) { if (!mImageBuffer) return NS_BASE_STREAM_CLOSED; diff --git a/image/src/imgTools.cpp b/image/src/imgTools.cpp index 44bc6bf0a72..63bbb84d420 100644 --- a/image/src/imgTools.cpp +++ b/image/src/imgTools.cpp @@ -74,16 +74,17 @@ NS_IMETHODIMP imgTools::DecodeImageData(nsIInputStream* aInStr, } // Figure out how much data we've been passed - PRUint32 length; + PRUint64 length; rv = inStream->Available(&length); NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_TRUE(length <= PR_UINT32_MAX, NS_ERROR_FILE_TOO_BIG); // Send the source data to the Image. WriteToRasterImage always // consumes everything it gets if it doesn't run out of memory. PRUint32 bytesRead; rv = inStream->ReadSegments(RasterImage::WriteToRasterImage, static_cast(image), - length, &bytesRead); + (PRUint32)length, &bytesRead); NS_ENSURE_SUCCESS(rv, rv); NS_ABORT_IF_FALSE(bytesRead == length || image->HasError(), "WriteToRasterImage should consume everything or the image must be in error!"); diff --git a/js/xpconnect/loader/mozJSComponentLoader.cpp b/js/xpconnect/loader/mozJSComponentLoader.cpp index 4b28921a2ab..546c167726c 100644 --- a/js/xpconnect/loader/mozJSComponentLoader.cpp +++ b/js/xpconnect/loader/mozJSComponentLoader.cpp @@ -855,12 +855,15 @@ mozJSComponentLoader::GlobalForLocation(nsIFile *aComponentFile, rv = scriptChannel->Open(getter_AddRefs(scriptStream)); NS_ENSURE_SUCCESS(rv, rv); - PRUint32 len, bytesRead; + PRUint64 len64; + PRUint32 bytesRead; - rv = scriptStream->Available(&len); + rv = scriptStream->Available(&len64); NS_ENSURE_SUCCESS(rv, rv); - if (!len) + NS_ENSURE_TRUE(len64 < PR_UINT32_MAX, NS_ERROR_FILE_TOO_BIG); + if (!len64) return NS_ERROR_FAILURE; + PRUint32 len = (PRUint32)len64; /* malloc an internal buf the size of the file */ nsAutoArrayPtr buf(new char[len + 1]); diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 0e0c4597271..b60e9d06705 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -8143,8 +8143,13 @@ DumpToPNG(nsIPresShell* shell, nsAString& name) { rv = file->InitWithPath(name); NS_ENSURE_SUCCESS(rv, rv); - PRUint32 length; - encoder->Available(&length); + PRUint64 length64; + rv = encoder->Available(&length64); + NS_ENSURE_SUCCESS(rv, rv); + if (length64 > PR_UINT32_MAX) + return NS_ERROR_FILE_TOO_BIG; + + PRUint32 length = (PRUint32)length64; nsCOMPtr outputStream; rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), file); diff --git a/layout/style/nsFontFaceLoader.cpp b/layout/style/nsFontFaceLoader.cpp index 052bc984e6a..8a68296c883 100644 --- a/layout/style/nsFontFaceLoader.cpp +++ b/layout/style/nsFontFaceLoader.cpp @@ -873,11 +873,16 @@ nsUserFontSet::SyncLoadFontData(gfxProxyFontEntry *aFontToLoad, rv = channel->Open(getter_AddRefs(stream)); NS_ENSURE_SUCCESS(rv, rv); - rv = stream->Available(&aBufferLength); + PRUint64 bufferLength64; + rv = stream->Available(&bufferLength64); NS_ENSURE_SUCCESS(rv, rv); - if (aBufferLength == 0) { + if (bufferLength64 == 0) { return NS_ERROR_FAILURE; } + if (bufferLength64 > PR_UINT32_MAX) { + return NS_ERROR_FILE_TOO_BIG; + } + aBufferLength = static_cast(bufferLength64); // read all the decoded data aBuffer = static_cast (NS_Alloc(sizeof(PRUint8) * aBufferLength)); diff --git a/modules/libjar/nsJAR.cpp b/modules/libjar/nsJAR.cpp index a18b012cc82..c565441f920 100644 --- a/modules/libjar/nsJAR.cpp +++ b/modules/libjar/nsJAR.cpp @@ -422,11 +422,11 @@ nsJAR::LoadEntry(const nsACString &aFilename, char** aBuf, PRUint32* aBufLen) //-- Read the manifest file into memory char* buf; - PRUint32 len; - rv = manifestStream->Available(&len); + PRUint64 len64; + rv = manifestStream->Available(&len64); if (NS_FAILED(rv)) return rv; - if (len == PRUint32(-1)) - return NS_ERROR_FILE_CORRUPTED; // bug 164695 + NS_ENSURE_TRUE(len64 < PR_UINT32_MAX, NS_ERROR_FILE_CORRUPTED); // bug 164695 + PRUint32 len = (PRUint32)len64; buf = (char*)malloc(len+1); if (!buf) return NS_ERROR_OUT_OF_MEMORY; PRUint32 bytesRead; diff --git a/modules/libjar/nsJARChannel.cpp b/modules/libjar/nsJARChannel.cpp index 837db08da34..1b0551ffb9a 100644 --- a/modules/libjar/nsJARChannel.cpp +++ b/modules/libjar/nsJARChannel.cpp @@ -132,9 +132,12 @@ nsJARInputThunk::EnsureJarStream() } // ask the JarStream for the content length - rv = mJarStream->Available((PRUint32 *) &mContentLength); + PRUint64 avail; + rv = mJarStream->Available((PRUint64 *) &avail); if (NS_FAILED(rv)) return rv; + mContentLength = avail < PR_INT32_MAX ? (PRInt32) avail : -1; + return NS_OK; } @@ -148,7 +151,7 @@ nsJARInputThunk::Close() } NS_IMETHODIMP -nsJARInputThunk::Available(PRUint32 *avail) +nsJARInputThunk::Available(PRUint64 *avail) { nsresult rv = EnsureJarStream(); if (NS_FAILED(rv)) return rv; diff --git a/modules/libjar/nsJARInputStream.cpp b/modules/libjar/nsJARInputStream.cpp index cc53765305c..59d95e9eb9e 100644 --- a/modules/libjar/nsJARInputStream.cpp +++ b/modules/libjar/nsJARInputStream.cpp @@ -146,7 +146,7 @@ nsJARInputStream::InitDirectory(nsJAR* aJar, } NS_IMETHODIMP -nsJARInputStream::Available(PRUint32 *_retval) +nsJARInputStream::Available(PRUint64 *_retval) { // A lot of callers don't check the error code. // They just use the _retval value. diff --git a/modules/libpref/src/Preferences.cpp b/modules/libpref/src/Preferences.cpp index 746557160fc..e24db67b230 100644 --- a/modules/libpref/src/Preferences.cpp +++ b/modules/libpref/src/Preferences.cpp @@ -450,7 +450,8 @@ ReadExtensionPrefs(nsIFile *aFile) rv = reader->GetInputStream(entry, getter_AddRefs(stream)); NS_ENSURE_SUCCESS(rv, rv); - PRUint32 avail, read; + PRUint64 avail; + PRUint32 read; PrefParseState ps; PREF_InitParseState(&ps, PREF_ReaderCallback, NULL); @@ -759,11 +760,13 @@ static nsresult openPrefFile(nsIFile* aFile) if (NS_FAILED(rv)) return rv; - PRUint32 fileSize; - rv = inStr->Available(&fileSize); + PRUint64 fileSize64; + rv = inStr->Available(&fileSize64); if (NS_FAILED(rv)) return rv; + NS_ENSURE_TRUE(fileSize64 <= PR_UINT32_MAX, NS_ERROR_FILE_TOO_BIG); + PRUint32 fileSize = (PRUint32)fileSize64; nsAutoArrayPtr fileBuffer(new char[fileSize]); if (fileBuffer == nullptr) return NS_ERROR_OUT_OF_MEMORY; diff --git a/netwerk/base/public/nsNetUtil.h b/netwerk/base/public/nsNetUtil.h index 8af2d437c6e..3ecbf4a9624 100644 --- a/netwerk/base/public/nsNetUtil.h +++ b/netwerk/base/public/nsNetUtil.h @@ -639,7 +639,7 @@ NS_ImplementChannelOpen(nsIChannel *channel, if (NS_SUCCEEDED(rv)) { rv = channel->AsyncOpen(listener, nullptr); if (NS_SUCCEEDED(rv)) { - PRUint32 n; + PRUint64 n; // block until the initial response is received or an error occurs. rv = stream->Available(&n); if (NS_SUCCEEDED(rv)) { diff --git a/netwerk/base/src/nsBaseContentStream.cpp b/netwerk/base/src/nsBaseContentStream.cpp index 3e4ba6889ca..a278ff4472c 100644 --- a/netwerk/base/src/nsBaseContentStream.cpp +++ b/netwerk/base/src/nsBaseContentStream.cpp @@ -55,7 +55,7 @@ nsBaseContentStream::Close() } NS_IMETHODIMP -nsBaseContentStream::Available(PRUint32 *result) +nsBaseContentStream::Available(PRUint64 *result) { *result = 0; return mStatus; diff --git a/netwerk/base/src/nsBufferedStreams.cpp b/netwerk/base/src/nsBufferedStreams.cpp index e0c9326a79b..10ea3a101da 100644 --- a/netwerk/base/src/nsBufferedStreams.cpp +++ b/netwerk/base/src/nsBufferedStreams.cpp @@ -297,7 +297,7 @@ nsBufferedInputStream::Close() } NS_IMETHODIMP -nsBufferedInputStream::Available(PRUint32 *result) +nsBufferedInputStream::Available(PRUint64 *result) { nsresult rv = NS_OK; *result = 0; diff --git a/netwerk/base/src/nsDirectoryIndexStream.cpp b/netwerk/base/src/nsDirectoryIndexStream.cpp index 3ac82d0cee4..149515f4374 100644 --- a/netwerk/base/src/nsDirectoryIndexStream.cpp +++ b/netwerk/base/src/nsDirectoryIndexStream.cpp @@ -200,7 +200,7 @@ nsDirectoryIndexStream::Close() } NS_IMETHODIMP -nsDirectoryIndexStream::Available(PRUint32* aLength) +nsDirectoryIndexStream::Available(PRUint64* aLength) { if (NS_FAILED(mStatus)) return mStatus; diff --git a/netwerk/base/src/nsFileStreams.cpp b/netwerk/base/src/nsFileStreams.cpp index b388c42ecd8..4b705c30558 100644 --- a/netwerk/base/src/nsFileStreams.cpp +++ b/netwerk/base/src/nsFileStreams.cpp @@ -134,7 +134,7 @@ nsFileStreamBase::Close() } nsresult -nsFileStreamBase::Available(PRUint32* aResult) +nsFileStreamBase::Available(PRUint64* aResult) { nsresult rv = DoPendingOpen(); NS_ENSURE_SUCCESS(rv, rv); @@ -151,7 +151,7 @@ nsFileStreamBase::Available(PRUint32* aResult) } // If available is greater than 4GB, return 4GB - *aResult = avail > PR_UINT32_MAX ? PR_UINT32_MAX : (PRUint32)avail; + *aResult = (PRUint64)avail; return NS_OK; } @@ -573,9 +573,9 @@ nsPartialFileInputStream::Tell(PRInt64 *aResult) } NS_IMETHODIMP -nsPartialFileInputStream::Available(PRUint32* aResult) +nsPartialFileInputStream::Available(PRUint64* aResult) { - PRUint32 available; + PRUint64 available; nsresult rv = nsFileInputStream::Available(&available); if (NS_SUCCEEDED(rv)) { *aResult = TruncateSize(available); @@ -586,7 +586,7 @@ nsPartialFileInputStream::Available(PRUint32* aResult) NS_IMETHODIMP nsPartialFileInputStream::Read(char* aBuf, PRUint32 aCount, PRUint32* aResult) { - PRUint32 readsize = TruncateSize(aCount); + PRUint32 readsize = (PRUint32) TruncateSize(aCount); if (readsize == 0 && mBehaviorFlags & CLOSE_ON_EOF) { Close(); *aResult = 0; diff --git a/netwerk/base/src/nsFileStreams.h b/netwerk/base/src/nsFileStreams.h index 391f9f88634..c3b4d2438ab 100644 --- a/netwerk/base/src/nsFileStreams.h +++ b/netwerk/base/src/nsFileStreams.h @@ -34,7 +34,7 @@ public: protected: nsresult Close(); - nsresult Available(PRUint32* _retval); + nsresult Available(PRUint64* _retval); nsresult Read(char* aBuf, PRUint32 aCount, PRUint32* _retval); nsresult ReadSegments(nsWriteSegmentFun aWriter, void* aClosure, PRUint32 aCount, PRUint32* _retval); @@ -111,7 +111,7 @@ public: NS_DECL_NSIIPCSERIALIZABLE NS_IMETHOD Close(); - NS_IMETHOD Available(PRUint32* _retval) + NS_IMETHOD Available(PRUint64* _retval) { return nsFileStreamBase::Available(_retval); } @@ -182,7 +182,7 @@ public: NS_DECL_NSIIPCSERIALIZABLE NS_IMETHOD Tell(PRInt64 *aResult); - NS_IMETHOD Available(PRUint32 *aResult); + NS_IMETHOD Available(PRUint64 *aResult); NS_IMETHOD Read(char* aBuf, PRUint32 aCount, PRUint32* aResult); NS_IMETHOD Seek(PRInt32 aWhence, PRInt64 aOffset); @@ -190,8 +190,8 @@ public: Create(nsISupports *aOuter, REFNSIID aIID, void **aResult); private: - PRUint32 TruncateSize(PRUint32 aSize) { - return (PRUint32)NS_MIN(mLength - mPosition, aSize); + PRUint64 TruncateSize(PRUint64 aSize) { + return NS_MIN(mLength - mPosition, aSize); } PRUint64 mStart; diff --git a/netwerk/base/src/nsInputStreamChannel.cpp b/netwerk/base/src/nsInputStreamChannel.cpp index f5b6d7ad8c3..c67d04998a6 100644 --- a/netwerk/base/src/nsInputStreamChannel.cpp +++ b/netwerk/base/src/nsInputStreamChannel.cpp @@ -19,7 +19,7 @@ nsInputStreamChannel::OpenContentStream(bool async, nsIInputStream **result, PRInt64 len = ContentLength64(); if (len < 0) { - PRUint32 avail; + PRUint64 avail; nsresult rv = mContentStream->Available(&avail); if (rv == NS_BASE_STREAM_CLOSED) { // This just means there's nothing in the stream diff --git a/netwerk/base/src/nsInputStreamPump.cpp b/netwerk/base/src/nsInputStreamPump.cpp index 2af7092196a..a66fa6fb1b9 100644 --- a/netwerk/base/src/nsInputStreamPump.cpp +++ b/netwerk/base/src/nsInputStreamPump.cpp @@ -101,10 +101,11 @@ nsInputStreamPump::PeekStream(PeekSegmentFun callback, void* closure) NS_ASSERTION(mAsyncStream, "PeekStream called without stream"); // See if the pipe is closed by checking the return of Available. - PRUint32 dummy; - nsresult rv = mAsyncStream->Available(&dummy); + PRUint64 dummy64; + nsresult rv = mAsyncStream->Available(&dummy64); if (NS_FAILED(rv)) return rv; + PRUint32 dummy = (PRUint32)NS_MIN(dummy64, (PRUint64)PR_UINT32_MAX); PeekData data(callback, closure); return mAsyncStream->ReadSegments(CallPeekFunc, @@ -407,7 +408,7 @@ nsInputStreamPump::OnStateStart() // so our listener can check our status from OnStartRequest. // XXX async streams should have a GetStatus method! if (NS_SUCCEEDED(mStatus)) { - PRUint32 avail; + PRUint64 avail; rv = mAsyncStream->Available(&avail); if (NS_FAILED(rv) && rv != NS_BASE_STREAM_CLOSED) mStatus = rv; @@ -435,9 +436,9 @@ nsInputStreamPump::OnStateTransfer() nsresult rv; - PRUint32 avail; + PRUint64 avail; rv = mAsyncStream->Available(&avail); - LOG((" Available returned [stream=%x rv=%x avail=%u]\n", mAsyncStream.get(), rv, avail)); + LOG((" Available returned [stream=%x rv=%x avail=%llu]\n", mAsyncStream.get(), rv, avail)); if (rv == NS_BASE_STREAM_CLOSED) { rv = NS_OK; @@ -445,8 +446,8 @@ nsInputStreamPump::OnStateTransfer() } else if (NS_SUCCEEDED(rv) && avail) { // figure out how much data to report (XXX detect overflow??) - if (PRUint64(avail) + mStreamOffset > mStreamLength) - avail = PRUint32(mStreamLength - mStreamOffset); + if (avail > mStreamLength - mStreamOffset) + avail = mStreamLength - mStreamOffset; if (avail) { // we used to limit avail to 16K - we were afraid some ODA handlers @@ -478,12 +479,15 @@ nsInputStreamPump::OnStateTransfer() PRUint32 odaOffset = mStreamOffset > PR_UINT32_MAX ? PR_UINT32_MAX : PRUint32(mStreamOffset); + PRUint32 odaAvail = + avail > PR_UINT32_MAX ? + PR_UINT32_MAX : PRUint32(avail); - LOG((" calling OnDataAvailable [offset=%lld(%u) count=%u]\n", - mStreamOffset, odaOffset, avail)); + LOG((" calling OnDataAvailable [offset=%lld(%u) count=%llu(%u)]\n", + mStreamOffset, odaOffset, avail, odaAvail)); rv = mListener->OnDataAvailable(this, mListenerContext, mAsyncStream, - odaOffset, avail); + odaOffset, odaAvail); // don't enter this code if ODA failed or called Cancel if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(mStatus)) { @@ -493,7 +497,7 @@ nsInputStreamPump::OnStateTransfer() // now closed, then we assume that everything was read. PRInt64 offsetAfter; if (NS_FAILED(seekable->Tell(&offsetAfter))) - offsetAfter = offsetBefore + avail; + offsetAfter = offsetBefore + odaAvail; if (offsetAfter > offsetBefore) mStreamOffset += (offsetAfter - offsetBefore); else if (mSuspendCount == 0) { @@ -509,7 +513,7 @@ nsInputStreamPump::OnStateTransfer() } } else - mStreamOffset += avail; // assume ODA behaved well + mStreamOffset += odaAvail; // assume ODA behaved well } } } diff --git a/netwerk/base/src/nsMIMEInputStream.cpp b/netwerk/base/src/nsMIMEInputStream.cpp index 4e5c461fcd8..0878df32fa3 100644 --- a/netwerk/base/src/nsMIMEInputStream.cpp +++ b/netwerk/base/src/nsMIMEInputStream.cpp @@ -170,12 +170,12 @@ void nsMIMEInputStream::InitStreams() // We'll use the content-length stream to add the final \r\n if (mAddContentLength) { - PRUint32 cl = 0; + PRUint64 cl = 0; if (mData) { mData->Available(&cl); } mContentLength.AssignLiteral("Content-Length: "); - mContentLength.AppendInt((PRInt32)cl); + mContentLength.AppendInt(cl); mContentLength.AppendLiteral("\r\n\r\n"); } else { @@ -245,7 +245,7 @@ nsMIMEInputStream::ReadSegCb(nsIInputStream* aIn, void* aClosure, // nsIInputStream NS_IMETHODIMP nsMIMEInputStream::Close(void) { INITSTREAMS; return mStream->Close(); } -NS_IMETHODIMP nsMIMEInputStream::Available(PRUint32 *_retval) { INITSTREAMS; return mStream->Available(_retval); } +NS_IMETHODIMP nsMIMEInputStream::Available(PRUint64 *_retval) { INITSTREAMS; return mStream->Available(_retval); } NS_IMETHODIMP nsMIMEInputStream::Read(char * buf, PRUint32 count, PRUint32 *_retval) { INITSTREAMS; return mStream->Read(buf, count, _retval); } NS_IMETHODIMP nsMIMEInputStream::IsNonBlocking(bool *aNonBlocking) { INITSTREAMS; return mStream->IsNonBlocking(aNonBlocking); } diff --git a/netwerk/base/src/nsPreloadedStream.cpp b/netwerk/base/src/nsPreloadedStream.cpp index 937721de464..611c2aeb7b6 100644 --- a/netwerk/base/src/nsPreloadedStream.cpp +++ b/netwerk/base/src/nsPreloadedStream.cpp @@ -41,9 +41,9 @@ nsPreloadedStream::Close() NS_IMETHODIMP -nsPreloadedStream::Available(PRUint32 *_retval) +nsPreloadedStream::Available(PRUint64 *_retval) { - PRUint32 avail = 0; + PRUint64 avail = 0; nsresult rv = mStream->Available(&avail); if (NS_FAILED(rv)) diff --git a/netwerk/base/src/nsSocketTransport2.cpp b/netwerk/base/src/nsSocketTransport2.cpp index 80954a21df8..05a658b8cef 100644 --- a/netwerk/base/src/nsSocketTransport2.cpp +++ b/netwerk/base/src/nsSocketTransport2.cpp @@ -249,7 +249,7 @@ nsSocketInputStream::Close() } NS_IMETHODIMP -nsSocketInputStream::Available(PRUint32 *avail) +nsSocketInputStream::Available(PRUint64 *avail) { SOCKET_LOG(("nsSocketInputStream::Available [this=%x]\n", this)); diff --git a/netwerk/base/src/nsStreamTransportService.cpp b/netwerk/base/src/nsStreamTransportService.cpp index e69975a27ee..dc1381d17f3 100644 --- a/netwerk/base/src/nsStreamTransportService.cpp +++ b/netwerk/base/src/nsStreamTransportService.cpp @@ -163,7 +163,7 @@ nsInputStreamTransport::Close() } NS_IMETHODIMP -nsInputStreamTransport::Available(PRUint32 *result) +nsInputStreamTransport::Available(PRUint64 *result) { return NS_ERROR_NOT_IMPLEMENTED; } diff --git a/netwerk/base/src/nsSyncStreamListener.cpp b/netwerk/base/src/nsSyncStreamListener.cpp index 27518ce3b77..720f5e6a230 100644 --- a/netwerk/base/src/nsSyncStreamListener.cpp +++ b/netwerk/base/src/nsSyncStreamListener.cpp @@ -118,7 +118,7 @@ nsSyncStreamListener::Close() } NS_IMETHODIMP -nsSyncStreamListener::Available(PRUint32 *result) +nsSyncStreamListener::Available(PRUint64 *result) { if (NS_FAILED(mStatus)) return mStatus; @@ -142,11 +142,11 @@ nsSyncStreamListener::Read(char *buf, return NS_OK; } - PRUint32 avail; - if (NS_FAILED(Available(&avail))) + PRUint64 avail64; + if (NS_FAILED(Available(&avail64))) return mStatus; - avail = NS_MIN(avail, bufLen); + PRUint32 avail = (PRUint32)NS_MIN(avail64, (PRUint64)bufLen); mStatus = mPipeIn->Read(buf, avail, result); return mStatus; } @@ -162,11 +162,11 @@ nsSyncStreamListener::ReadSegments(nsWriteSegmentFun writer, return NS_OK; } - PRUint32 avail; - if (NS_FAILED(Available(&avail))) + PRUint64 avail64; + if (NS_FAILED(Available(&avail64))) return mStatus; - avail = NS_MIN(avail, count); + PRUint32 avail = (PRUint32)NS_MIN(avail64, (PRUint64)count); mStatus = mPipeIn->ReadSegments(writer, closure, avail, result); return mStatus; } diff --git a/netwerk/cache/nsCacheEntryDescriptor.cpp b/netwerk/cache/nsCacheEntryDescriptor.cpp index 96ad8806edf..e17f6c6fa93 100644 --- a/netwerk/cache/nsCacheEntryDescriptor.cpp +++ b/netwerk/cache/nsCacheEntryDescriptor.cpp @@ -562,7 +562,7 @@ nsInputStreamWrapper::Close() } nsresult nsCacheEntryDescriptor:: -nsInputStreamWrapper::Available(PRUint32 *avail) +nsInputStreamWrapper::Available(PRUint64 *avail) { nsresult rv = EnsureInit(); if (NS_FAILED(rv)) return rv; diff --git a/netwerk/cache/nsDiskCacheStreams.cpp b/netwerk/cache/nsDiskCacheStreams.cpp index 851ce7eeab7..b0a37cf09da 100644 --- a/netwerk/cache/nsDiskCacheStreams.cpp +++ b/netwerk/cache/nsDiskCacheStreams.cpp @@ -93,7 +93,7 @@ nsDiskCacheInputStream::Close() NS_IMETHODIMP -nsDiskCacheInputStream::Available(PRUint32 * bytesAvailable) +nsDiskCacheInputStream::Available(PRUint64 * bytesAvailable) { if (mClosed) return NS_BASE_STREAM_CLOSED; if (mStreamEnd < mPos) return NS_ERROR_UNEXPECTED; diff --git a/netwerk/ipc/NeckoMessageUtils.h b/netwerk/ipc/NeckoMessageUtils.h index 12cc188f4e4..1473bbb0dd9 100644 --- a/netwerk/ipc/NeckoMessageUtils.h +++ b/netwerk/ipc/NeckoMessageUtils.h @@ -178,12 +178,15 @@ struct ParamTraits NS_WARNING("nsIInputStream implementation doesn't support nsIIPCSerializable; falling back to copying data"); nsCString streamString; - PRUint32 bytes; + PRUint64 bytes; - aParam.mStream->Available(&bytes); - if (bytes > 0) { + nsresult rv = aParam.mStream->Available(&bytes); + if (NS_SUCCEEDED(rv) && bytes > 0) { + // Also, on 64-bit system, for an interoperability for 32-bit process + // and 64-bit process, we shouldn't handle over 4GB message. + NS_ABORT_IF_FALSE(bytes < PR_UINT32_MAX, "nsIInputStream has over 4GB data"); mozilla::DebugOnly rv = - NS_ReadInputStreamToString(aParam.mStream, streamString, bytes); + NS_ReadInputStreamToString(aParam.mStream, streamString, (PRUint32)bytes); NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "Can't read input stream into a string!"); } diff --git a/netwerk/protocol/device/AndroidCaptureProvider.cpp b/netwerk/protocol/device/AndroidCaptureProvider.cpp index 0acf733b26d..609669f95c8 100644 --- a/netwerk/protocol/device/AndroidCaptureProvider.cpp +++ b/netwerk/protocol/device/AndroidCaptureProvider.cpp @@ -102,7 +102,7 @@ void AndroidCameraInputStream::ReceiveFrame(char* frame, PRUint32 length) { } NS_IMETHODIMP -AndroidCameraInputStream::Available(PRUint32 *aAvailable) +AndroidCameraInputStream::Available(PRUint64 *aAvailable) { mozilla::ReentrantMonitorAutoEnter autoMonitor(mMonitor); diff --git a/netwerk/protocol/device/GonkCaptureProvider.cpp b/netwerk/protocol/device/GonkCaptureProvider.cpp index c8f4f5e143b..662e7476315 100644 --- a/netwerk/protocol/device/GonkCaptureProvider.cpp +++ b/netwerk/protocol/device/GonkCaptureProvider.cpp @@ -393,7 +393,7 @@ GonkCameraInputStream::ReceiveFrame(char* frame, PRUint32 length) { } NS_IMETHODIMP -GonkCameraInputStream::Available(PRUint32 *aAvailable) +GonkCameraInputStream::Available(PRUint64 *aAvailable) { ReentrantMonitorAutoEnter enter(mMonitor); diff --git a/netwerk/protocol/file/nsFileChannel.cpp b/netwerk/protocol/file/nsFileChannel.cpp index 9a47d98887a..4b3260a1394 100644 --- a/netwerk/protocol/file/nsFileChannel.cpp +++ b/netwerk/protocol/file/nsFileChannel.cpp @@ -422,11 +422,12 @@ nsFileChannel::SetUploadStream(nsIInputStream *stream, mUploadLength = contentLength; if (mUploadLength < 0) { // Make sure we know how much data we are uploading. - PRUint32 avail; + PRUint64 avail; nsresult rv = mUploadStream->Available(&avail); if (NS_FAILED(rv)) return rv; - mUploadLength = avail; + if (avail < PR_INT64_MAX) + mUploadLength = avail; } } else { mUploadLength = -1; diff --git a/netwerk/protocol/ftp/nsFtpConnectionThread.cpp b/netwerk/protocol/ftp/nsFtpConnectionThread.cpp index aa8ec5541e3..4bf82167ed6 100644 --- a/netwerk/protocol/ftp/nsFtpConnectionThread.cpp +++ b/netwerk/protocol/ftp/nsFtpConnectionThread.cpp @@ -2099,7 +2099,7 @@ nsFtpState::OnStopRequest(nsIRequest *request, nsISupports *context, //----------------------------------------------------------------------------- NS_IMETHODIMP -nsFtpState::Available(PRUint32 *result) +nsFtpState::Available(PRUint64 *result) { if (mDataStream) return mDataStream->Available(result); diff --git a/netwerk/protocol/ftp/nsFtpConnectionThread.h b/netwerk/protocol/ftp/nsFtpConnectionThread.h index 51efb3798a3..60aa895d3d2 100644 --- a/netwerk/protocol/ftp/nsFtpConnectionThread.h +++ b/netwerk/protocol/ftp/nsFtpConnectionThread.h @@ -98,7 +98,7 @@ public: // Override input stream methods: NS_IMETHOD CloseWithStatus(nsresult status); - NS_IMETHOD Available(PRUint32 *result); + NS_IMETHOD Available(PRUint64 *result); NS_IMETHOD ReadSegments(nsWriteSegmentFun fun, void *closure, PRUint32 count, PRUint32 *result); diff --git a/netwerk/protocol/ftp/nsFtpControlConnection.cpp b/netwerk/protocol/ftp/nsFtpControlConnection.cpp index d3ae063fdda..2fcba737494 100644 --- a/netwerk/protocol/ftp/nsFtpControlConnection.cpp +++ b/netwerk/protocol/ftp/nsFtpControlConnection.cpp @@ -34,15 +34,15 @@ nsFtpControlConnection::OnInputStreamReady(nsIAsyncInputStream *stream) char data[4096]; // Consume data whether we have a listener or not. + PRUint64 avail64; PRUint32 avail; - nsresult rv = stream->Available(&avail); + nsresult rv = stream->Available(&avail64); if (NS_SUCCEEDED(rv)) { - if (avail > sizeof(data)) - avail = sizeof(data); + avail = (PRUint32)NS_MIN(avail64, (PRUint64)sizeof(data)); PRUint32 n; rv = stream->Read(data, avail, &n); - if (NS_SUCCEEDED(rv) && n != avail) + if (NS_SUCCEEDED(rv)) avail = n; } diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp index fcc554aa9a9..1f702d273a2 100644 --- a/netwerk/protocol/http/HttpBaseChannel.cpp +++ b/netwerk/protocol/http/HttpBaseChannel.cpp @@ -445,33 +445,24 @@ HttpBaseChannel::SetUploadStream(nsIInputStream *stream, // contentLength are unspecified. if (stream) { + nsCAutoString method; + bool hasHeaders; + if (contentType.IsEmpty()) { - mUploadStreamHasHeaders = true; - mRequestHead.SetMethod(nsHttp::Post); // POST request + method = nsHttp::Post; + hasHeaders = true; } else { - if (contentLength < 0) { - // Not really kosher to assume Available == total length of - // stream, but apparently works for the streams we see here. - stream->Available((PRUint32 *) &contentLength); - if (contentLength < 0) { - NS_ERROR("unable to determine content length"); - return NS_ERROR_FAILURE; - } - } - // SetRequestHeader propagates headers to chrome if HttpChannelChild - nsCAutoString contentLengthStr; - contentLengthStr.AppendInt(PRInt64(contentLength)); - SetRequestHeader(NS_LITERAL_CSTRING("Content-Length"), contentLengthStr, - false); - SetRequestHeader(NS_LITERAL_CSTRING("Content-Type"), contentType, - false); - mUploadStreamHasHeaders = false; - mRequestHead.SetMethod(nsHttp::Put); // PUT request + method = nsHttp::Put; + hasHeaders = false; } - } else { - mUploadStreamHasHeaders = false; - mRequestHead.SetMethod(nsHttp::Get); // revert to GET request + return ExplicitSetUploadStream(stream, contentType, contentLength, + method, hasHeaders); } + + // if stream is null, ExplicitSetUploadStream returns error. + // So we need special case for GET method. + mUploadStreamHasHeaders = false; + mRequestHead.SetMethod(nsHttp::Get); // revert to GET request mUploadStream = stream; return NS_OK; } @@ -491,10 +482,8 @@ HttpBaseChannel::ExplicitSetUploadStream(nsIInputStream *aStream, NS_ENSURE_TRUE(aStream, NS_ERROR_FAILURE); if (aContentLength < 0 && !aStreamHasHeaders) { - PRUint32 streamLength; - aStream->Available(&streamLength); - aContentLength = streamLength; - if (aContentLength < 0) { + nsresult rv = aStream->Available(reinterpret_cast(&aContentLength)); + if (NS_FAILED(rv) || aContentLength < 0) { NS_ERROR("unable to determine content length"); return NS_ERROR_FAILURE; } diff --git a/netwerk/protocol/http/NullHttpTransaction.cpp b/netwerk/protocol/http/NullHttpTransaction.cpp index e1a369dfc8d..cf815f2aade 100644 --- a/netwerk/protocol/http/NullHttpTransaction.cpp +++ b/netwerk/protocol/http/NullHttpTransaction.cpp @@ -89,7 +89,7 @@ NullHttpTransaction::Caps() return mCaps; } -PRUint32 +PRUint64 NullHttpTransaction::Available() { return 0; diff --git a/netwerk/protocol/http/SpdySession2.cpp b/netwerk/protocol/http/SpdySession2.cpp index 2f2b02e4a57..b31fcb69a4a 100644 --- a/netwerk/protocol/http/SpdySession2.cpp +++ b/netwerk/protocol/http/SpdySession2.cpp @@ -2201,7 +2201,7 @@ SpdySession2::Caps() return 0; } -PRUint32 +PRUint64 SpdySession2::Available() { NS_ABORT_IF_FALSE(false, "SpdySession2::Available()"); diff --git a/netwerk/protocol/http/SpdySession3.cpp b/netwerk/protocol/http/SpdySession3.cpp index 8687a5c5640..fa0c62255f4 100644 --- a/netwerk/protocol/http/SpdySession3.cpp +++ b/netwerk/protocol/http/SpdySession3.cpp @@ -2258,7 +2258,7 @@ SpdySession3::Caps() return 0; } -PRUint32 +PRUint64 SpdySession3::Available() { NS_ABORT_IF_FALSE(false, "SpdySession3::Available()"); diff --git a/netwerk/protocol/http/nsAHttpTransaction.h b/netwerk/protocol/http/nsAHttpTransaction.h index 50d3814c15c..07774c27b10 100644 --- a/netwerk/protocol/http/nsAHttpTransaction.h +++ b/netwerk/protocol/http/nsAHttpTransaction.h @@ -50,7 +50,7 @@ public: virtual PRUint8 Caps() = 0; // called to find out how much request data is available for writing. - virtual PRUint32 Available() = 0; + virtual PRUint64 Available() = 0; // called to read request data from the transaction. virtual nsresult ReadSegments(nsAHttpSegmentReader *reader, @@ -145,7 +145,7 @@ public: bool IsDone(); \ nsresult Status(); \ PRUint8 Caps(); \ - PRUint32 Available(); \ + PRUint64 Available(); \ nsresult ReadSegments(nsAHttpSegmentReader *, PRUint32, PRUint32 *); \ nsresult WriteSegments(nsAHttpSegmentWriter *, PRUint32, PRUint32 *); \ void Close(nsresult reason); \ diff --git a/netwerk/protocol/http/nsHttpConnection.cpp b/netwerk/protocol/http/nsHttpConnection.cpp index e81952a18b4..17a07e3de2d 100644 --- a/netwerk/protocol/http/nsHttpConnection.cpp +++ b/netwerk/protocol/http/nsHttpConnection.cpp @@ -562,11 +562,11 @@ nsHttpConnection::CanReuse() // which we would deal with later on through the restart logic, but that // path is more expensive than just closing the socket now. - PRUint32 dataSize; + PRUint64 dataSize; if (canReuse && mSocketIn && !mUsingSpdyVersion && mHttp1xTransactionCount && NS_SUCCEEDED(mSocketIn->Available(&dataSize)) && dataSize) { LOG(("nsHttpConnection::CanReuse %p %s" - "Socket not reusable because read data pending (%d) on it.\n", + "Socket not reusable because read data pending (%llu) on it.\n", this, mConnInfo->Host(), dataSize)); canReuse = false; } diff --git a/netwerk/protocol/http/nsHttpPipeline.cpp b/netwerk/protocol/http/nsHttpPipeline.cpp index 23be74ea601..60fd2d510f1 100644 --- a/netwerk/protocol/http/nsHttpPipeline.cpp +++ b/netwerk/protocol/http/nsHttpPipeline.cpp @@ -559,10 +559,10 @@ nsHttpPipeline::Caps() return trans ? trans->Caps() : 0; } -PRUint32 +PRUint64 nsHttpPipeline::Available() { - PRUint32 result = 0; + PRUint64 result = 0; PRInt32 i, count = mRequestQ.Length(); for (i=0; iAvailable(&avail); if (NS_FAILED(rv)) return rv; @@ -623,7 +623,8 @@ nsHttpPipeline::ReadSegments(nsAHttpSegmentReader *reader, mReader = reader; - rv = mSendBufIn->ReadSegments(ReadFromPipe, this, avail, countRead); + // avail is under 4GB, so casting to PRUint32 is safe + rv = mSendBufIn->ReadSegments(ReadFromPipe, this, (PRUint32)avail, countRead); mReader = nullptr; return rv; @@ -835,7 +836,8 @@ nsHttpPipeline::FillSendBuf() if (NS_FAILED(rv)) return rv; } - PRUint32 n, avail; + PRUint32 n; + PRUint64 avail; nsAHttpTransaction *trans; nsITransport *transport = Transport(); @@ -849,7 +851,7 @@ nsHttpPipeline::FillSendBuf() nsAHttpTransaction *response = Response(0); if (response && !response->PipelinePosition()) response->SetPipelinePosition(1); - rv = trans->ReadSegments(this, avail, &n); + rv = trans->ReadSegments(this, (PRUint32)NS_MIN(avail, (PRUint64)PR_UINT32_MAX), &n); if (NS_FAILED(rv)) return rv; if (n == 0) { diff --git a/netwerk/protocol/http/nsHttpTransaction.cpp b/netwerk/protocol/http/nsHttpTransaction.cpp index 1a12f98c7ab..f92d5bcda8b 100644 --- a/netwerk/protocol/http/nsHttpTransaction.cpp +++ b/netwerk/protocol/http/nsHttpTransaction.cpp @@ -491,10 +491,10 @@ nsHttpTransaction::Caps() return mCaps; } -PRUint32 +PRUint64 nsHttpTransaction::Available() { - PRUint32 size; + PRUint64 size; if (NS_FAILED(mRequestStream->Available(&size))) size = 0; return size; diff --git a/netwerk/protocol/http/nsHttpTransaction.h b/netwerk/protocol/http/nsHttpTransaction.h index 9e894067548..8bb9fb5aec3 100644 --- a/netwerk/protocol/http/nsHttpTransaction.h +++ b/netwerk/protocol/http/nsHttpTransaction.h @@ -141,7 +141,7 @@ private: nsCString mReqHeaderBuf; // flattened request headers nsCOMPtr mRequestStream; - PRUint32 mRequestSize; + PRUint64 mRequestSize; nsAHttpConnection *mConnection; // hard ref nsHttpConnectionInfo *mConnInfo; // hard ref diff --git a/netwerk/protocol/websocket/WebSocketChannel.cpp b/netwerk/protocol/websocket/WebSocketChannel.cpp index 6ccf7309d2e..b78046268d2 100644 --- a/netwerk/protocol/websocket/WebSocketChannel.cpp +++ b/netwerk/protocol/websocket/WebSocketChannel.cpp @@ -721,7 +721,7 @@ public: #ifdef DEBUG // Make sure we got correct length from Blob - PRUint32 bytes; + PRUint64 bytes; mMsg.pStream->Available(&bytes); NS_ASSERTION(bytes == mLength, "Stream length != blob length!"); #endif diff --git a/netwerk/streamconv/converters/nsFTPDirListingConv.cpp b/netwerk/streamconv/converters/nsFTPDirListingConv.cpp index a6c40ac5440..f1725ad2c90 100644 --- a/netwerk/streamconv/converters/nsFTPDirListingConv.cpp +++ b/netwerk/streamconv/converters/nsFTPDirListingConv.cpp @@ -87,8 +87,10 @@ nsFTPDirListingConv::OnDataAvailable(nsIRequest* request, nsISupports *ctxt, PRUint32 read, streamLen; - rv = inStr->Available(&streamLen); + PRUint64 streamLen64; + rv = inStr->Available(&streamLen64); NS_ENSURE_SUCCESS(rv, rv); + streamLen = (PRUint32)NS_MIN(streamLen64, PRUint64(PR_UINT32_MAX - 1)); nsAutoArrayPtr buffer(new char[streamLen + 1]); NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY); diff --git a/netwerk/streamconv/test/Converters.cpp b/netwerk/streamconv/test/Converters.cpp index df946550357..2f2ff7d6087 100644 --- a/netwerk/streamconv/test/Converters.cpp +++ b/netwerk/streamconv/test/Converters.cpp @@ -78,6 +78,12 @@ TestConverter::AsyncConvertData(const char *aFromType, return NS_OK; } +static inline PRUint32 +saturated(PRUint64 aValue) +{ + return (PRUint32) NS_MIN(aValue, (PRUint64) PR_UINT32_MAX); +} + // nsIStreamListener method /* This method handles asyncronous conversion of data. */ NS_IMETHODIMP @@ -94,9 +100,19 @@ TestConverter::OnDataAvailable(nsIRequest* request, rv = Convert(inStr, fromType.get(), toType.get(), ctxt, getter_AddRefs(convertedStream)); if (NS_FAILED(rv)) return rv; - PRUint32 len; + PRUint64 len = 0; convertedStream->Available(&len); - return mListener->OnDataAvailable(request, ctxt, convertedStream, sourceOffset, len); + + PRUint64 offset = sourceOffset; + while (len > 0) { + PRUint32 count = saturated(len); + rv = mListener->OnDataAvailable(request, ctxt, convertedStream, saturated(offset), count); + if (NS_FAILED(rv)) return rv; + + offset += count; + len -= count; + } + return NS_OK; } // nsIRequestObserver methods diff --git a/netwerk/streamconv/test/TestStreamConv.cpp b/netwerk/streamconv/test/TestStreamConv.cpp index fa4e0bb6575..adab557690b 100644 --- a/netwerk/streamconv/test/TestStreamConv.cpp +++ b/netwerk/streamconv/test/TestStreamConv.cpp @@ -62,9 +62,11 @@ public: PRUint32 sourceOffset, PRUint32 count) { nsresult rv; - PRUint32 read, len; - rv = inStr->Available(&len); + PRUint32 read; + PRUint64 len64; + rv = inStr->Available(&len64); if (NS_FAILED(rv)) return rv; + PRUint32 len = (PRUint32)NS_MIN(len64, (PRUint64)(PR_UINT32_MAX - 1)); char *buffer = (char*)nsMemory::Alloc(len + 1); if (!buffer) return NS_ERROR_OUT_OF_MEMORY; @@ -95,7 +97,12 @@ NS_IMPL_ISUPPORTS2(EndListener, // EndListener END //////////////////////////////////////////////////////////////////////// - +static PRUint32 +saturated(PRUint64 aValue) +{ + return (PRUint32)NS_MIN(aValue, (PRUint64)PR_UINT32_MAX); +} + nsresult SendData(const char * aData, nsIStreamListener* aListener, nsIRequest* request) { nsresult rv; @@ -106,10 +113,20 @@ nsresult SendData(const char * aData, nsIStreamListener* aListener, nsIRequest* rv = dataStream->SetData(aData, strlen(aData)); NS_ENSURE_SUCCESS(rv, rv); - PRUint32 avail; + PRUint64 avail = 0; dataStream->Available(&avail); - return aListener->OnDataAvailable(request, nullptr, dataStream, 0, avail); + PRUint64 offset = 0; + while (avail > 0) { + PRUint32 count = saturated(avail); + rv = aListener->OnDataAvailable(request, nullptr, dataStream, + saturated(offset), count); + if (NS_FAILED(rv)) return rv; + + offset += count; + avail -= count; + } + return NS_OK; } #define SEND_DATA(x) SendData(x, converterListener, request) diff --git a/parser/xml/src/nsSAXXMLReader.cpp b/parser/xml/src/nsSAXXMLReader.cpp index 0bb14c9b0ae..1b86a964a59 100644 --- a/parser/xml/src/nsSAXXMLReader.cpp +++ b/parser/xml/src/nsSAXXMLReader.cpp @@ -501,9 +501,9 @@ nsSAXXMLReader::ParseFromStream(nsIInputStream *aStream, nsresult status; parserChannel->GetStatus(&status); - PRUint32 offset = 0; + PRUint64 offset = 0; while (NS_SUCCEEDED(rv) && NS_SUCCEEDED(status)) { - PRUint32 available; + PRUint64 available; rv = aStream->Available(&available); if (rv == NS_BASE_STREAM_CLOSED) { rv = NS_OK; @@ -516,8 +516,13 @@ nsSAXXMLReader::ParseFromStream(nsIInputStream *aStream, if (! available) break; // blocking input stream has none available when done + if (available > PR_UINT32_MAX) + available = PR_UINT32_MAX; + rv = mListener->OnDataAvailable(parserChannel, nullptr, - aStream, offset, available); + aStream, + (PRUint32)NS_MIN(offset, (PRUint64)PR_UINT32_MAX), + (PRUint32)available); if (NS_SUCCEEDED(rv)) offset += available; else diff --git a/rdf/base/src/nsRDFXMLDataSource.cpp b/rdf/base/src/nsRDFXMLDataSource.cpp index 921430090f4..099fb39e601 100644 --- a/rdf/base/src/nsRDFXMLDataSource.cpp +++ b/rdf/base/src/nsRDFXMLDataSource.cpp @@ -519,21 +519,24 @@ RDFXMLDataSourceImpl::BlockingParse(nsIURI* aURL, nsIStreamListener* aConsumer) rv = aConsumer->OnStartRequest(channel, nullptr); - PRUint32 offset = 0; + PRUint64 offset = 0; while (NS_SUCCEEDED(rv)) { // Skip ODA if the channel is canceled channel->GetStatus(&rv); if (NS_FAILED(rv)) break; - PRUint32 avail; + PRUint64 avail; if (NS_FAILED(rv = bufStream->Available(&avail))) break; // error if (avail == 0) break; // eof - rv = aConsumer->OnDataAvailable(channel, nullptr, bufStream, offset, avail); + if (avail > PR_UINT32_MAX) + avail = PR_UINT32_MAX; + + rv = aConsumer->OnDataAvailable(channel, nullptr, bufStream, (PRUint32)NS_MIN(offset, (PRUint64)PR_UINT32_MAX), (PRUint32)avail); if (NS_SUCCEEDED(rv)) offset += avail; } diff --git a/security/manager/ssl/src/nsNSSComponent.cpp b/security/manager/ssl/src/nsNSSComponent.cpp index a018b81e385..f5d1998894c 100644 --- a/security/manager/ssl/src/nsNSSComponent.cpp +++ b/security/manager/ssl/src/nsNSSComponent.cpp @@ -2775,7 +2775,7 @@ nsCryptoHash::Update(const PRUint8 *data, PRUint32 len) } NS_IMETHODIMP -nsCryptoHash::UpdateFromStream(nsIInputStream *data, PRUint32 len) +nsCryptoHash::UpdateFromStream(nsIInputStream *data, PRUint32 aLen) { if (!mInitialized) return NS_ERROR_NOT_INITIALIZED; @@ -2783,7 +2783,7 @@ nsCryptoHash::UpdateFromStream(nsIInputStream *data, PRUint32 len) if (!data) return NS_ERROR_INVALID_ARG; - PRUint32 n; + PRUint64 n; nsresult rv = data->Available(&n); if (NS_FAILED(rv)) return rv; @@ -2791,7 +2791,8 @@ nsCryptoHash::UpdateFromStream(nsIInputStream *data, PRUint32 len) // if the user has passed PR_UINT32_MAX, then read // everything in the stream - if (len == PR_UINT32_MAX) + PRUint64 len = aLen; + if (aLen == PR_UINT32_MAX) len = n; // So, if the stream has NO data available for the hash, @@ -2809,7 +2810,7 @@ nsCryptoHash::UpdateFromStream(nsIInputStream *data, PRUint32 len) while(NS_SUCCEEDED(rv) && len>0) { - readLimit = NS_MIN(PRUint32(NS_CRYPTO_HASH_BUFFER_SIZE), len); + readLimit = (PRUint32)NS_MIN(NS_CRYPTO_HASH_BUFFER_SIZE, len); rv = data->Read(buffer, readLimit, &read); @@ -2975,7 +2976,7 @@ NS_IMETHODIMP nsCryptoHMAC::UpdateFromStream(nsIInputStream *aStream, PRUint32 a if (!aStream) return NS_ERROR_INVALID_ARG; - PRUint32 n; + PRUint64 n; nsresult rv = aStream->Available(&n); if (NS_FAILED(rv)) return rv; @@ -2983,8 +2984,9 @@ NS_IMETHODIMP nsCryptoHMAC::UpdateFromStream(nsIInputStream *aStream, PRUint32 a // if the user has passed PR_UINT32_MAX, then read // everything in the stream + PRUint64 len = aLen; if (aLen == PR_UINT32_MAX) - aLen = n; + len = n; // So, if the stream has NO data available for the hash, // or if the data available is less then what the caller @@ -2993,15 +2995,15 @@ NS_IMETHODIMP nsCryptoHMAC::UpdateFromStream(nsIInputStream *aStream, PRUint32 a // that there is not enough data in the stream to satisify // the request. - if (n == 0 || n < aLen) + if (n == 0 || n < len) return NS_ERROR_NOT_AVAILABLE; char buffer[NS_CRYPTO_HASH_BUFFER_SIZE]; PRUint32 read, readLimit; - while(NS_SUCCEEDED(rv) && aLen > 0) + while(NS_SUCCEEDED(rv) && len > 0) { - readLimit = NS_MIN(PRUint32(NS_CRYPTO_HASH_BUFFER_SIZE), aLen); + readLimit = (PRUint32)NS_MIN(NS_CRYPTO_HASH_BUFFER_SIZE, len); rv = aStream->Read(buffer, readLimit, &read); if (read == 0) @@ -3010,7 +3012,7 @@ NS_IMETHODIMP nsCryptoHMAC::UpdateFromStream(nsIInputStream *aStream, PRUint32 a if (NS_SUCCEEDED(rv)) rv = Update((const PRUint8*)buffer, read); - aLen -= read; + len -= read; } return rv; diff --git a/startupcache/StartupCacheUtils.cpp b/startupcache/StartupCacheUtils.cpp index 07046e73ecd..681d80581b0 100644 --- a/startupcache/StartupCacheUtils.cpp +++ b/startupcache/StartupCacheUtils.cpp @@ -79,11 +79,14 @@ NewBufferFromStorageStream(nsIStorageStream *storageStream, rv = storageStream->NewInputStream(0, getter_AddRefs(inputStream)); NS_ENSURE_SUCCESS(rv, rv); - PRUint32 avail, read; - rv = inputStream->Available(&avail); + PRUint64 avail64; + rv = inputStream->Available(&avail64); NS_ENSURE_SUCCESS(rv, rv); - + NS_ENSURE_TRUE(avail64 <= PR_UINT32_MAX, NS_ERROR_FILE_TOO_BIG); + + PRUint32 avail = (PRUint32)avail64; nsAutoArrayPtr temp (new char[avail]); + PRUint32 read; rv = inputStream->Read(temp, avail, &read); if (NS_SUCCEEDED(rv) && avail != read) rv = NS_ERROR_UNEXPECTED; diff --git a/toolkit/components/places/nsFaviconService.cpp b/toolkit/components/places/nsFaviconService.cpp index dd41b74c357..7909f7faaba 100644 --- a/toolkit/components/places/nsFaviconService.cpp +++ b/toolkit/components/places/nsFaviconService.cpp @@ -599,11 +599,12 @@ nsFaviconService::ReplaceFaviconDataFromDataURL(nsIURI* aFaviconURI, rv = channel->Open(getter_AddRefs(stream)); NS_ENSURE_SUCCESS(rv, rv); - PRUint32 available; - rv = stream->Available(&available); + PRUint64 available64; + rv = stream->Available(&available64); NS_ENSURE_SUCCESS(rv, rv); - if (available == 0) - return NS_ERROR_FAILURE; + if (available64 == 0 || available64 > PR_UINT32_MAX / sizeof(PRUint8)) + return NS_ERROR_FILE_TOO_BIG; + PRUint32 available = (PRUint32)available64; // Read all the decoded data. PRUint8* buffer = static_cast @@ -661,11 +662,12 @@ nsFaviconService::SetFaviconDataFromDataURL(nsIURI* aFaviconURI, rv = channel->Open(getter_AddRefs(stream)); NS_ENSURE_SUCCESS(rv, rv); - PRUint32 available; - rv = stream->Available(&available); + PRUint64 available64; + rv = stream->Available(&available64); NS_ENSURE_SUCCESS(rv, rv); - if (available == 0) + if (available64 == 0 || available64 > PR_UINT32_MAX / sizeof(PRUint8)) return NS_ERROR_FAILURE; + PRUint32 available = (PRUint32)available64; // read all the decoded data PRUint8* buffer = static_cast diff --git a/widget/windows/WinUtils.cpp b/widget/windows/WinUtils.cpp index 81c2f89cc69..f03837c5d3c 100644 --- a/widget/windows/WinUtils.cpp +++ b/widget/windows/WinUtils.cpp @@ -590,9 +590,12 @@ NS_IMETHODIMP AsyncWriteIconToDisk::Run() NS_ENSURE_SUCCESS(rv, rv); // Obtain the ICO buffer size from the re-encoded ICO stream - PRUint32 bufSize; - rv = iconStream->Available(&bufSize); + PRUint64 bufSize64; + rv = iconStream->Available(&bufSize64); NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_TRUE(bufSize64 <= PR_UINT32_MAX, NS_ERROR_FILE_TOO_BIG); + + PRUint32 bufSize = (PRUint32)bufSize64; // Setup a buffered output stream from the stream object // so that we can simply use WriteFrom with the stream object diff --git a/xpcom/io/Base64.cpp b/xpcom/io/Base64.cpp index 79740b9ad11..1b6490990e3 100644 --- a/xpcom/io/Base64.cpp +++ b/xpcom/io/Base64.cpp @@ -159,14 +159,18 @@ EncodeInputStream(nsIInputStream *aInputStream, PRUint32 aOffset) { nsresult rv; + PRUint64 count64 = aCount; if (!aCount) { - rv = aInputStream->Available(&aCount); + rv = aInputStream->Available(&count64); NS_ENSURE_SUCCESS(rv, rv); + // if count64 is over 4GB, it will be failed at the below condition, + // then will return NS_ERROR_OUT_OF_MEMORY + aCount = (PRUint32)count64; } PRUint64 countlong = - (PRUint64(aCount) + 2) / 3 * 4; // +2 due to integer math. + (count64 + 2) / 3 * 4; // +2 due to integer math. if (countlong + aOffset > PR_UINT32_MAX) return NS_ERROR_OUT_OF_MEMORY; diff --git a/xpcom/io/nsBinaryStream.cpp b/xpcom/io/nsBinaryStream.cpp index 9a22f211a48..5c973287f7f 100644 --- a/xpcom/io/nsBinaryStream.cpp +++ b/xpcom/io/nsBinaryStream.cpp @@ -304,7 +304,7 @@ nsBinaryOutputStream::PutBuffer(char* aBuffer, PRUint32 aLength) NS_IMPL_ISUPPORTS3(nsBinaryInputStream, nsIObjectInputStream, nsIBinaryInputStream, nsIInputStream) NS_IMETHODIMP -nsBinaryInputStream::Available(PRUint32* aResult) +nsBinaryInputStream::Available(PRUint64* aResult) { NS_ENSURE_STATE(mInputStream); return mInputStream->Available(aResult); diff --git a/xpcom/io/nsIInputStream.idl b/xpcom/io/nsIInputStream.idl index 10537c824b5..df8c7362f4f 100644 --- a/xpcom/io/nsIInputStream.idl +++ b/xpcom/io/nsIInputStream.idl @@ -56,7 +56,7 @@ native nsWriteSegmentFun(nsWriteSegmentFun); * the case that a blocking input stream should be implemented using thread- * safe AddRef and Release. */ -[scriptable, uuid(fa9c7f6c-61b3-11d4-9877-00c04fa0cf4a)] +[scriptable, uuid(53cdbc97-c2d7-4e30-b2c3-45b2ee79db18)] interface nsIInputStream : nsISupports { /** @@ -80,14 +80,13 @@ interface nsIInputStream : nsISupports * this method returns 0 bytes available. (Note: some nsIInputStream * implementations automatically close when eof is reached; some do not). * - * @return number of bytes currently available in the stream, or - * PR_UINT32_MAX if the size of the stream exceeds PR_UINT32_MAX. + * @return number of bytes currently available in the stream. * * @throws NS_BASE_STREAM_CLOSED if the stream is closed normally. * @throws if the stream is closed due to some error * condition */ - unsigned long available(); + unsigned long long available(); /** * Read data from the stream. diff --git a/xpcom/io/nsIScriptableInputStream.idl b/xpcom/io/nsIScriptableInputStream.idl index 1fa3f23a3f0..d9248f4258a 100644 --- a/xpcom/io/nsIScriptableInputStream.idl +++ b/xpcom/io/nsIScriptableInputStream.idl @@ -11,7 +11,7 @@ interface nsIInputStream; * nsIScriptableInputStream provides scriptable access to an nsIInputStream * instance. */ -[scriptable, uuid(e546afd6-1248-4deb-8940-4b000b618a58)] +[scriptable, uuid(3fce9015-472a-4080-ac3e-cd875dbe361e)] interface nsIScriptableInputStream : nsISupports { /** @@ -33,7 +33,7 @@ interface nsIScriptableInputStream : nsISupports * * @throws NS_BASE_STREAM_CLOSED if called after the stream has been closed */ - unsigned long available(); + unsigned long long available(); /** * Read data from the stream. diff --git a/xpcom/io/nsInputStreamTee.cpp b/xpcom/io/nsInputStreamTee.cpp index f127790b706..26b8835f8a8 100644 --- a/xpcom/io/nsInputStreamTee.cpp +++ b/xpcom/io/nsInputStreamTee.cpp @@ -212,7 +212,7 @@ nsInputStreamTee::Close() } NS_IMETHODIMP -nsInputStreamTee::Available(PRUint32 *avail) +nsInputStreamTee::Available(PRUint64 *avail) { NS_ENSURE_TRUE(mSource, NS_ERROR_NOT_INITIALIZED); return mSource->Available(avail); diff --git a/xpcom/io/nsMultiplexInputStream.cpp b/xpcom/io/nsMultiplexInputStream.cpp index 0581aa76615..735ede5a08f 100644 --- a/xpcom/io/nsMultiplexInputStream.cpp +++ b/xpcom/io/nsMultiplexInputStream.cpp @@ -148,19 +148,19 @@ nsMultiplexInputStream::Close() return rv; } -/* unsigned long available (); */ +/* unsigned long long available (); */ NS_IMETHODIMP -nsMultiplexInputStream::Available(PRUint32 *_retval) +nsMultiplexInputStream::Available(PRUint64 *_retval) { if (NS_FAILED(mStatus)) return mStatus; nsresult rv; - PRUint32 avail = 0; + PRUint64 avail = 0; PRUint32 len = mStreams.Count(); for (PRUint32 i = mCurrentStream; i < len; i++) { - PRUint32 streamAvail; + PRUint64 streamAvail; rv = mStreams[i]->Available(&streamAvail); NS_ENSURE_SUCCESS(rv, rv); avail += streamAvail; diff --git a/xpcom/io/nsPipe3.cpp b/xpcom/io/nsPipe3.cpp index 651a343df2b..365745943b1 100644 --- a/xpcom/io/nsPipe3.cpp +++ b/xpcom/io/nsPipe3.cpp @@ -704,15 +704,16 @@ nsPipeInputStream::Close() } NS_IMETHODIMP -nsPipeInputStream::Available(PRUint32 *result) +nsPipeInputStream::Available(PRUint64 *result) { + // nsPipeInputStream supports under 4GB stream only ReentrantMonitorAutoEnter mon(mPipe->mReentrantMonitor); // return error if pipe closed if (!mAvailable && NS_FAILED(mPipe->mStatus)) return mPipe->mStatus; - *result = mAvailable; + *result = (PRUint64)mAvailable; return NS_OK; } diff --git a/xpcom/io/nsScriptableInputStream.cpp b/xpcom/io/nsScriptableInputStream.cpp index 8cc4c19f569..51079b278eb 100644 --- a/xpcom/io/nsScriptableInputStream.cpp +++ b/xpcom/io/nsScriptableInputStream.cpp @@ -24,7 +24,7 @@ nsScriptableInputStream::Init(nsIInputStream *aInputStream) { } NS_IMETHODIMP -nsScriptableInputStream::Available(PRUint32 *_retval) { +nsScriptableInputStream::Available(PRUint64 *_retval) { if (!mInputStream) return NS_ERROR_NOT_INITIALIZED; return mInputStream->Available(_retval); } @@ -32,16 +32,16 @@ nsScriptableInputStream::Available(PRUint32 *_retval) { NS_IMETHODIMP nsScriptableInputStream::Read(PRUint32 aCount, char **_retval) { nsresult rv = NS_OK; - PRUint32 count = 0; + PRUint64 count64 = 0; char *buffer = nullptr; if (!mInputStream) return NS_ERROR_NOT_INITIALIZED; - rv = mInputStream->Available(&count); + rv = mInputStream->Available(&count64); if (NS_FAILED(rv)) return rv; // bug716556 - Ensure count+1 doesn't overflow - count = NS_MIN(NS_MIN(count, aCount), PR_UINT32_MAX - 1); + PRUint32 count = NS_MIN((PRUint32)NS_MIN(count64, aCount), PR_UINT32_MAX - 1); buffer = (char*)nsMemory::Alloc(count+1); // make room for '\0' if (!buffer) return NS_ERROR_OUT_OF_MEMORY; diff --git a/xpcom/io/nsStorageStream.cpp b/xpcom/io/nsStorageStream.cpp index 7b744bd5f84..18669d2b9f7 100644 --- a/xpcom/io/nsStorageStream.cpp +++ b/xpcom/io/nsStorageStream.cpp @@ -373,7 +373,7 @@ nsStorageInputStream::Close() } NS_IMETHODIMP -nsStorageInputStream::Available(PRUint32 *aAvailable) +nsStorageInputStream::Available(PRUint64 *aAvailable) { if (NS_FAILED(mStatus)) return mStatus; diff --git a/xpcom/io/nsStreamUtils.cpp b/xpcom/io/nsStreamUtils.cpp index 4bfded5d33e..e5dcc1899ff 100644 --- a/xpcom/io/nsStreamUtils.cpp +++ b/xpcom/io/nsStreamUtils.cpp @@ -611,20 +611,23 @@ NS_ConsumeStream(nsIInputStream *stream, PRUint32 maxCount, nsACString &result) result.Truncate(); while (maxCount) { - PRUint32 avail; - rv = stream->Available(&avail); + PRUint64 avail64; + rv = stream->Available(&avail64); if (NS_FAILED(rv)) { if (rv == NS_BASE_STREAM_CLOSED) rv = NS_OK; break; } - if (avail == 0) + if (avail64 == 0) break; - if (avail > maxCount) - avail = maxCount; + + PRUint32 avail = (PRUint32)NS_MIN(avail64, maxCount); // resize result buffer PRUint32 length = result.Length(); + if (avail > PR_UINT32_MAX - length) + return NS_ERROR_FILE_TOO_BIG; + result.SetLength(length + avail); if (result.Length() != (length + avail)) return NS_ERROR_OUT_OF_MEMORY; diff --git a/xpcom/io/nsStringStream.cpp b/xpcom/io/nsStringStream.cpp index 881f2f4ceb8..716dccdc727 100644 --- a/xpcom/io/nsStringStream.cpp +++ b/xpcom/io/nsStringStream.cpp @@ -178,7 +178,7 @@ nsStringInputStream::Close() } NS_IMETHODIMP -nsStringInputStream::Available(PRUint32 *aLength) +nsStringInputStream::Available(PRUint64 *aLength) { NS_ASSERTION(aLength, "null ptr"); diff --git a/xpcom/tests/TestBase64.cpp b/xpcom/tests/TestBase64.cpp index cf77ecaeee1..ffcfd9b8a22 100644 --- a/xpcom/tests/TestBase64.cpp +++ b/xpcom/tests/TestBase64.cpp @@ -177,7 +177,7 @@ FakeInputStream::Close() } NS_IMETHODIMP -FakeInputStream::Available(PRUint32* aAvailable) +FakeInputStream::Available(PRUint64* aAvailable) { *aAvailable = 0;