diff --git a/devtools/client/framework/source-map-worker.js b/devtools/client/framework/source-map-worker.js index b6ac2c121f..ec269778b8 100644 --- a/devtools/client/framework/source-map-worker.js +++ b/devtools/client/framework/source-map-worker.js @@ -87,7 +87,8 @@ async function _resolveAndFetch(generatedSource) : SourceMapConsumer { // Fetch the sourcemap over the network and create it. const sourceMapURL = _resolveSourceMapURL(generatedSource); const fetched = await fetch( - sourceMapURL, { loadFromCache: false } + sourceMapURL, { loadFromCache: false, + redirect: error } ); // Create the source map and fix it up. diff --git a/netwerk/mime/nsIMIMEHeaderParam.idl b/netwerk/mime/nsIMIMEHeaderParam.idl index ffe8403d60..84397529fb 100644 --- a/netwerk/mime/nsIMIMEHeaderParam.idl +++ b/netwerk/mime/nsIMIMEHeaderParam.idl @@ -12,7 +12,7 @@ #include "nsISupports.idl" -[scriptable, uuid(9c9252a1-fdaf-40a2-9c2b-a3dc45e28dde)] +[scriptable, uuid(6e8476d5-ba95-4fee-85d9-f96729b387d8)] interface nsIMIMEHeaderParam : nsISupports { /** @@ -132,7 +132,7 @@ interface nsIMIMEHeaderParam : nsISupports { */ [noscript] - string getParameterInternal(in string aHeaderVal, + string getParameterInternal(in ACString aHeaderVal, in string aParamName, out string aCharset, out string aLang); diff --git a/netwerk/mime/nsMIMEHeaderParamImpl.cpp b/netwerk/mime/nsMIMEHeaderParamImpl.cpp index bd5c25ce4b..68e8c86573 100644 --- a/netwerk/mime/nsMIMEHeaderParamImpl.cpp +++ b/netwerk/mime/nsMIMEHeaderParamImpl.cpp @@ -65,6 +65,28 @@ nsMIMEHeaderParamImpl::GetParameterHTTP(const nsACString& aHeaderVal, aFallbackCharset, aTryLocaleCharset, aLang, aResult); } +/* static */ +// Detects the presence of any non-null characters past null in a header. +bool +nsMIMEHeaderParamImpl::ContainsTrailingCharPastNull(const nsACString& aVal) { + nsACString::const_iterator first; + aVal.BeginReading(first); + nsACString::const_iterator end; + aVal.EndReading(end); + + if (FindCharInReadable(L'\0', first, end)) { + while (first != end) { + if (*first != '\0') { + // Header contains trailing characters past the null character + return true; + } + ++first; + } + } + // No stray non-null characters found. + return false; +} + // XXX : aTryLocaleCharset is not yet effective. nsresult nsMIMEHeaderParamImpl::DoGetParameter(const nsACString& aHeaderVal, @@ -81,9 +103,8 @@ nsMIMEHeaderParamImpl::DoGetParameter(const nsACString& aHeaderVal, // aDecoding (5987 being a subset of 2231) and return charset.) nsXPIDLCString med; nsXPIDLCString charset; - rv = DoParameterInternal(PromiseFlatCString(aHeaderVal).get(), aParamName, - aDecoding, getter_Copies(charset), aLang, - getter_Copies(med)); + rv = DoParameterInternal(aHeaderVal, aParamName, aDecoding, + getter_Copies(charset), aLang, getter_Copies(med)); if (NS_FAILED(rv)) return rv; @@ -346,11 +367,11 @@ bool IsValidOctetSequenceForCharset(nsACString& aCharset, const char *aOctets) // The format of these header lines is // [ ';' '=' ]* NS_IMETHODIMP -nsMIMEHeaderParamImpl::GetParameterInternal(const char *aHeaderValue, - const char *aParamName, - char **aCharset, - char **aLang, - char **aResult) +nsMIMEHeaderParamImpl::GetParameterInternal(const nsACString& aHeaderValue, + const char* aParamName, + char** aCharset, + char** aLang, + char** aResult) { return DoParameterInternal(aHeaderValue, aParamName, MIME_FIELD_ENCODING, aCharset, aLang, aResult); @@ -358,16 +379,29 @@ nsMIMEHeaderParamImpl::GetParameterInternal(const char *aHeaderValue, nsresult -nsMIMEHeaderParamImpl::DoParameterInternal(const char *aHeaderValue, - const char *aParamName, +nsMIMEHeaderParamImpl::DoParameterInternal(const nsACString& aHeaderValue, + const char* aParamName, ParamDecoding aDecoding, - char **aCharset, - char **aLang, - char **aResult) + char** aCharset, + char** aLang, + char** aResult) { - if (!aHeaderValue || !*aHeaderValue || !aResult) + if (aHeaderValue.IsEmpty() || !aResult) { return NS_ERROR_INVALID_ARG; + } + + if (ContainsTrailingCharPastNull(aHeaderValue)) { + // See Bug 1784348 + return NS_ERROR_INVALID_ARG; + } + + const nsCString& flat = PromiseFlatCString(aHeaderValue); + const char* str = flat.get(); + + if (!*str) { + return NS_ERROR_INVALID_ARG; + } *aResult = nullptr; @@ -380,8 +414,6 @@ nsMIMEHeaderParamImpl::DoParameterInternal(const char *aHeaderValue, // them for HTTP header fields later on, see bug 776324 bool acceptContinuations = true; - const char *str = aHeaderValue; - // skip leading white space. for (; *str && nsCRT::IsAsciiSpace(*str); ++str) ; diff --git a/netwerk/mime/nsMIMEHeaderParamImpl.h b/netwerk/mime/nsMIMEHeaderParamImpl.h index 8918ee3275..9d157b2609 100644 --- a/netwerk/mime/nsMIMEHeaderParamImpl.h +++ b/netwerk/mime/nsMIMEHeaderParamImpl.h @@ -29,13 +29,14 @@ private: char **aLang, nsAString& aResult); - nsresult DoParameterInternal(const char *aHeaderValue, - const char *aParamName, + nsresult DoParameterInternal(const nsACString& aHeaderValue, + const char* aParamName, ParamDecoding aDecoding, - char **aCharset, - char **aLang, - char **aResult); - + char** aCharset, + char** aLang, + char** aResult); + + static bool ContainsTrailingCharPastNull(const nsACString& aVal); }; #endif diff --git a/netwerk/test/unit/test_MIME_params.js b/netwerk/test/unit/test_MIME_params.js index 2c46a061c2..79b41b552f 100644 --- a/netwerk/test/unit/test_MIME_params.js +++ b/netwerk/test/unit/test_MIME_params.js @@ -432,6 +432,16 @@ var tests = [ // Bug 783502 - xpcshell test netwerk/test/unit/test_MIME_params.js fails on AddressSanitizer ['attachment; filename="\\b\\a\\', "attachment", "ba\\"], + + // Bug 1784348 + ["attachment; filename=foo.exe\0.pdf", + Cr.NS_ERROR_ILLEGAL_VALUE, + Cr.NS_ERROR_INVALID_ARG], + ["attachment; filename=\0\0foo\0", + Cr.NS_ERROR_ILLEGAL_VALUE, + Cr.NS_ERROR_INVALID_ARG], + ["attachment; filename=foo\0\0\0", "attachment", "foo"], + ["attachment; filename=\0\0\0", "attachment", ""], ]; var rfc5987paramtests = [ diff --git a/widget/nsITransferable.idl b/widget/nsITransferable.idl index e580673f5e..e8f6ca6c61 100644 --- a/widget/nsITransferable.idl +++ b/widget/nsITransferable.idl @@ -150,12 +150,6 @@ interface nsITransferable : nsISupports void getAnyTransferData ( out ACString aFlavor, out nsISupports aData, out unsigned long aDataLen ) ; - /** - * Returns true if the data is large. - */ - boolean isLargeDataSet ( ) ; - - /////////////////////////////// // Setter part of interface /////////////////////////////// diff --git a/widget/nsTransferable.cpp b/widget/nsTransferable.cpp index e99d45401d..f0c10dc96b 100644 --- a/widget/nsTransferable.cpp +++ b/widget/nsTransferable.cpp @@ -14,6 +14,7 @@ Notes to self: #include "nsTransferable.h" +#include "nsAnonymousTemporaryFile.h" #include "nsArray.h" #include "nsArrayUtils.h" #include "nsString.h" @@ -27,7 +28,6 @@ Notes to self: #include "nsISupportsPrimitives.h" #include "nsMemory.h" #include "nsPrimitiveHelpers.h" -#include "nsXPIDLString.h" #include "nsDirectoryServiceDefs.h" #include "nsDirectoryService.h" #include "nsCRT.h" @@ -36,7 +36,6 @@ Notes to self: #include "nsIOutputStream.h" #include "nsIInputStream.h" #include "nsIWeakReferenceUtils.h" -#include "nsIFile.h" #include "nsILoadContext.h" #include "mozilla/UniquePtr.h" @@ -56,164 +55,126 @@ size_t GetDataForFlavor (const nsTArray& aArray, //------------------------------------------------------------------------- DataStruct::~DataStruct() { - if (mCacheFileName) free(mCacheFileName); + if (mCacheFD) { + PR_Close(mCacheFD); + } } //------------------------------------------------------------------------- void -DataStruct::SetData ( nsISupports* aData, uint32_t aDataLen, bool aIsPrivateData ) +DataStruct::SetData(nsISupports* aData, uint32_t aDataLen, bool aIsPrivateData) { // Now, check to see if we consider the data to be "too large" // as well as ensuring that private browsing mode is disabled if (aDataLen > kLargeDatasetSize && !aIsPrivateData) { // if so, cache it to disk instead of memory - if ( NS_SUCCEEDED(WriteCache(aData, aDataLen)) ) + if (NS_SUCCEEDED(WriteCache(aData, aDataLen))) { + // Clear previously set small data. + mData = nullptr; + mDataLen = 0; return; - else - NS_WARNING("Oh no, couldn't write data to the cache file"); + } + NS_WARNING("Oh no, couldn't write data to the cache file"); + } + + if (mCacheFD) { + // Clear previously set big data. + PR_Close(mCacheFD); + mCacheFD = nullptr; } mData = aData; mDataLen = aDataLen; } - //------------------------------------------------------------------------- void -DataStruct::GetData ( nsISupports** aData, uint32_t *aDataLen ) +DataStruct::GetData(nsISupports** aData, uint32_t* aDataLen) { // check here to see if the data is cached on disk - if ( !mData && mCacheFileName ) { + if (mCacheFD) { // if so, read it in and pass it back // ReadCache creates memory and copies the data into it. - if ( NS_SUCCEEDED(ReadCache(aData, aDataLen)) ) + if (NS_SUCCEEDED(ReadCache(aData, aDataLen))) return; else { // oh shit, something went horribly wrong here. NS_WARNING("Oh no, couldn't read data in from the cache file"); *aData = nullptr; *aDataLen = 0; + PR_Close(mCacheFD); + mCacheFD = nullptr; return; } } *aData = mData; - if ( mData ) + if (mData) NS_ADDREF(*aData); *aDataLen = mDataLen; } -//------------------------------------------------------------------------- -already_AddRefed -DataStruct::GetFileSpec(const char* aFileName) -{ - nsCOMPtr cacheFile; - NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(cacheFile)); - - if (!cacheFile) - return nullptr; - - // if the param aFileName contains a name we should use that - // because the file probably already exists - // otherwise create a unique name - if (!aFileName) { - cacheFile->AppendNative(NS_LITERAL_CSTRING("clipboardcache")); - nsresult rv = cacheFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600); - if (NS_FAILED(rv)) - return nullptr; - } else { - cacheFile->AppendNative(nsDependentCString(aFileName)); - } - - return cacheFile.forget(); -} - - //------------------------------------------------------------------------- nsresult DataStruct::WriteCache(nsISupports* aData, uint32_t aDataLen) { - // Get a new path and file to the temp directory - nsCOMPtr cacheFile = GetFileSpec(mCacheFileName); - if (cacheFile) { - // remember the file name - if (!mCacheFileName) { - nsXPIDLCString fName; - cacheFile->GetNativeLeafName(fName); - mCacheFileName = strdup(fName); + nsresult rv; + if (!mCacheFD) { + rv = NS_OpenAnonymousTemporaryFile(&mCacheFD); + if (NS_FAILED(rv)) { + return NS_ERROR_FAILURE; } + } else if (PR_Seek64(mCacheFD, 0, PR_SEEK_SET) == -1) { + return NS_ERROR_FAILURE; + } - // write out the contents of the clipboard - // to the file - //uint32_t bytes; - nsCOMPtr outStr; - - NS_NewLocalFileOutputStream(getter_AddRefs(outStr), - cacheFile); - - if (!outStr) return NS_ERROR_FAILURE; - + // write out the contents of the clipboard to the file void* buff = nullptr; - nsPrimitiveHelpers::CreateDataFromPrimitive ( mFlavor.get(), aData, &buff, aDataLen ); + nsPrimitiveHelpers::CreateDataFromPrimitive(mFlavor.get(), aData, &buff, aDataLen); if ( buff ) { - uint32_t ignored; - outStr->Write(reinterpret_cast(buff), aDataLen, &ignored); - free(buff); + int32_t written = PR_Write(mCacheFD, buff, aDataLen); + free(buff); + if (written) { return NS_OK; } } + PR_Close(mCacheFD); + mCacheFD = nullptr; return NS_ERROR_FAILURE; } - //------------------------------------------------------------------------- nsresult DataStruct::ReadCache(nsISupports** aData, uint32_t* aDataLen) { // if we don't have a cache filename we are out of luck - if (!mCacheFileName) + if (!mCacheFD) { return NS_ERROR_FAILURE; - - // get the path and file name - nsCOMPtr cacheFile = GetFileSpec(mCacheFileName); - bool exists; - if ( cacheFile && NS_SUCCEEDED(cacheFile->Exists(&exists)) && exists ) { - // get the size of the file - int64_t fileSize; - int64_t max32 = 0xFFFFFFFF; - cacheFile->GetFileSize(&fileSize); - if (fileSize > max32) - return NS_ERROR_OUT_OF_MEMORY; - - uint32_t size = uint32_t(fileSize); - // create new memory for the large clipboard data - auto data = mozilla::MakeUnique(size); - if ( !data ) - return NS_ERROR_OUT_OF_MEMORY; - - // now read it all in - nsCOMPtr inStr; - NS_NewLocalFileInputStream( getter_AddRefs(inStr), - cacheFile); - - if (!cacheFile) return NS_ERROR_FAILURE; - - nsresult rv = inStr->Read(data.get(), fileSize, aDataLen); - - // make sure we got all the data ok - if (NS_SUCCEEDED(rv) && *aDataLen == size) { - nsPrimitiveHelpers::CreatePrimitiveForData(mFlavor.get(), data.get(), - fileSize, aData); - return *aData ? NS_OK : NS_ERROR_FAILURE; - } - - // zero the return params - *aData = nullptr; - *aDataLen = 0; } - return NS_ERROR_FAILURE; + PRFileInfo fileInfo; + if (PR_GetOpenFileInfo(mCacheFD, &fileInfo) != PR_SUCCESS) { + return NS_ERROR_FAILURE; + } + if (PR_Seek64(mCacheFD, 0, PR_SEEK_SET) == -1) { + return NS_ERROR_FAILURE; + } + uint32_t fileSize = fileInfo.size; + + auto data = mozilla::MakeUnique(fileSize); + if (!data) { + return NS_ERROR_OUT_OF_MEMORY; + } + + uint32_t actual = PR_Read(mCacheFD, data.get(), fileSize); + if (actual != fileSize) { + return NS_ERROR_FAILURE; + } + + nsPrimitiveHelpers::CreatePrimitiveForData(mFlavor.get(), data.get(), fileSize, aData); + *aDataLen = fileSize; + return NS_OK; } @@ -484,22 +445,9 @@ nsTransferable::RemoveDataFlavor(const char *aDataFlavor) * * */ + NS_IMETHODIMP -nsTransferable::IsLargeDataSet(bool *_retval) -{ - MOZ_ASSERT(mInitialized); - - NS_ENSURE_ARG_POINTER(_retval); - *_retval = false; - return NS_OK; -} - - -/** - * - * - */ -NS_IMETHODIMP nsTransferable::SetConverter(nsIFormatConverter * aConverter) +nsTransferable::SetConverter(nsIFormatConverter * aConverter) { MOZ_ASSERT(mInitialized); @@ -512,7 +460,8 @@ NS_IMETHODIMP nsTransferable::SetConverter(nsIFormatConverter * aConverter) * * */ -NS_IMETHODIMP nsTransferable::GetConverter(nsIFormatConverter * *aConverter) +NS_IMETHODIMP +nsTransferable::GetConverter(nsIFormatConverter * *aConverter) { MOZ_ASSERT(mInitialized); @@ -522,7 +471,6 @@ NS_IMETHODIMP nsTransferable::GetConverter(nsIFormatConverter * *aConverter) return NS_OK; } - // // FlavorsTransferableCanImport // diff --git a/widget/nsTransferable.h b/widget/nsTransferable.h index d0db18a46d..841c24004e 100644 --- a/widget/nsTransferable.h +++ b/widget/nsTransferable.h @@ -6,16 +6,15 @@ #ifndef nsTransferable_h__ #define nsTransferable_h__ -#include "nsIContentPolicyBase.h" #include "nsIFormatConverter.h" #include "nsITransferable.h" #include "nsCOMPtr.h" #include "nsString.h" #include "nsTArray.h" #include "nsIPrincipal.h" +#include "prio.h" class nsIMutableArray; -class nsString; // // DataStruct @@ -25,21 +24,20 @@ class nsString; struct DataStruct { explicit DataStruct ( const char* aFlavor ) - : mDataLen(0), mFlavor(aFlavor), mCacheFileName(nullptr) { } + : mDataLen(0), mFlavor(aFlavor), mCacheFD(nullptr) { } ~DataStruct(); const nsCString& GetFlavor() const { return mFlavor; } void SetData( nsISupports* inData, uint32_t inDataLen, bool aIsPrivateData ); void GetData( nsISupports** outData, uint32_t *outDataLen ); - already_AddRefed GetFileSpec(const char* aFileName); - bool IsDataAvailable() const { return (mData && mDataLen > 0) || (!mData && mCacheFileName); } + bool IsDataAvailable() const { return mData ? mDataLen > 0 : mCacheFD != nullptr; } protected: enum { // The size of data over which we write the data to disk rather than // keep it around in memory. - kLargeDatasetSize = 1000000 // 1 million bytes + kLargeDatasetSize = 4194304 // 4 Megabytes }; nsresult WriteCache(nsISupports* aData, uint32_t aDataLen ); @@ -47,8 +45,8 @@ protected: nsCOMPtr mData; // OWNER - some varient of primitive wrapper uint32_t mDataLen; + PRFileDesc* mCacheFD; const nsCString mFlavor; - char * mCacheFileName; };