mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 03:45:46 +00:00
Bug 273025 - "bad logic results in potential leak xor crash based on flow" (Improve GetURL/PostURL code, v4 (2/2)) [r+sr=jst]
This commit is contained in:
parent
a4d195ce4a
commit
8730dac85f
@ -412,9 +412,9 @@ public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_NSIPLUGININSTANCEOWNER
|
||||
|
||||
NS_IMETHOD GetURL(const char *aURL, const char *aTarget, void *aPostData,
|
||||
PRUint32 aPostDataLen, void *aHeadersData,
|
||||
PRUint32 aHeadersDataLen, PRBool aIsFile = PR_FALSE);
|
||||
NS_IMETHOD GetURL(const char *aURL, const char *aTarget,
|
||||
nsIInputStream *aPostStream,
|
||||
void *aHeadersData, PRUint32 aHeadersDataLen);
|
||||
NS_IMETHOD ShowStatus(const PRUnichar *aStatusMsg);
|
||||
NPError ShowNativeContextMenu(NPMenu* menu, void* event);
|
||||
NPBool ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
|
||||
@ -494,9 +494,8 @@ nsDummyJavaPluginOwner::CreateWidget(void)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDummyJavaPluginOwner::GetURL(const char *aURL, const char *aTarget,
|
||||
void *aPostData, PRUint32 aPostDataLen,
|
||||
void *aHeadersData, PRUint32 aHeadersDataLen,
|
||||
PRBool isFile)
|
||||
nsIInputStream *aPostStream,
|
||||
void *aHeadersData, PRUint32 aHeadersDataLen)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
@ -272,9 +272,9 @@ public:
|
||||
//nsIPluginInstanceOwner interface
|
||||
NS_DECL_NSIPLUGININSTANCEOWNER
|
||||
|
||||
NS_IMETHOD GetURL(const char *aURL, const char *aTarget, void *aPostData,
|
||||
PRUint32 aPostDataLen, void *aHeadersData,
|
||||
PRUint32 aHeadersDataLen, PRBool isFile = PR_FALSE);
|
||||
NS_IMETHOD GetURL(const char *aURL, const char *aTarget,
|
||||
nsIInputStream *aPostStream,
|
||||
void *aHeadersData, PRUint32 aHeadersDataLen);
|
||||
|
||||
NS_IMETHOD ShowStatus(const PRUnichar *aStatusMsg);
|
||||
|
||||
@ -2608,8 +2608,11 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetInstance(nsIPluginInstance *&aInstance)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL, const char *aTarget, void *aPostData, PRUint32 aPostDataLen, void *aHeadersData,
|
||||
PRUint32 aHeadersDataLen, PRBool isFile)
|
||||
NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL,
|
||||
const char *aTarget,
|
||||
nsIInputStream *aPostStream,
|
||||
void *aHeadersData,
|
||||
PRUint32 aHeadersDataLen)
|
||||
{
|
||||
NS_ENSURE_TRUE(mObjectFrame, NS_ERROR_NULL_POINTER);
|
||||
|
||||
@ -2634,29 +2637,18 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL, const char *aTarge
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIInputStream> postDataStream;
|
||||
nsCOMPtr<nsIInputStream> headersDataStream;
|
||||
if (aPostStream && aHeadersData) {
|
||||
if (!aHeadersDataLen)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
// deal with post data, either in a file or raw data, and any headers
|
||||
if (aPostData) {
|
||||
nsCOMPtr<nsIStringInputStream> sis = do_CreateInstance("@mozilla.org/io/string-input-stream;1");
|
||||
if (!sis)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
rv = NS_NewPluginPostDataStream(getter_AddRefs(postDataStream), (const char *)aPostData, aPostDataLen, isFile);
|
||||
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv),"failed in creating plugin post data stream");
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if (aHeadersData) {
|
||||
rv = NS_NewPluginPostDataStream(getter_AddRefs(headersDataStream),
|
||||
(const char *) aHeadersData,
|
||||
aHeadersDataLen,
|
||||
PR_FALSE,
|
||||
PR_TRUE); // last arg says we are headers, no /r/n/r/n fixup!
|
||||
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv),"failed in creating plugin header data stream");
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
rv = sis->SetData((char *)aHeadersData, aHeadersDataLen);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
headersDataStream = do_QueryInterface(sis);
|
||||
}
|
||||
|
||||
PRInt32 blockPopups =
|
||||
@ -2664,7 +2656,7 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL, const char *aTarge
|
||||
nsAutoPopupStatePusher popupStatePusher((PopupControlState)blockPopups);
|
||||
|
||||
rv = lh->OnLinkClick(mContent, uri, unitarget.get(),
|
||||
postDataStream, headersDataStream);
|
||||
aPostStream, headersDataStream);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "nsIStreamListener.idl"
|
||||
#include "nsIStringStream.idl"
|
||||
#include "nsIPluginTag.idl"
|
||||
#include "nsIFile.idl"
|
||||
|
||||
%{C++
|
||||
#include "nsPluginNativeWindow.h"
|
||||
@ -64,7 +65,7 @@ interface nsIPluginStreamListener;
|
||||
[ref] native nsIStreamListenerRef(nsIStreamListener *);
|
||||
[ptr] native nsPluginNativeWindowPtr(nsPluginNativeWindow);
|
||||
|
||||
[scriptable, uuid(33211305-4ABD-4E2E-BD73-A05A7DA0E82E)]
|
||||
[scriptable, uuid(3F3C4952-4877-4D8A-B3CE-A0AFFD2C0785)]
|
||||
interface nsIPluginHost : nsISupports
|
||||
{
|
||||
[noscript] void init();
|
||||
@ -242,9 +243,9 @@ interface nsIPluginHost : nsISupports
|
||||
out unsigned long aOutPostDataLen);
|
||||
|
||||
/**
|
||||
* To create tmp file with Content len header in, it will use by http POST
|
||||
* To create temp file with Content len header in, it will use by http POST
|
||||
*/
|
||||
[noscript] void createTmpFileToPost(in string aPostDataURL, out string aTmpFileName);
|
||||
[noscript] nsIFile createTempFileToPost(in string aPostDataURL);
|
||||
|
||||
/**
|
||||
* Creates a new plugin native window object
|
||||
@ -286,64 +287,3 @@ interface nsIPluginHost : nsISupports
|
||||
virtual void RemoveIdleTimeTarget(nsIPluginInstanceOwner* objectFrame) = 0;
|
||||
%}
|
||||
};
|
||||
|
||||
%{C++
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
/**
|
||||
* Used for creating the correct input stream for plugins
|
||||
* We can either have raw data (with or without \r\n\r\n) or a path to a file (but it must be native!)
|
||||
* When making an nsIInputStream stream for the plugins POST data, be sure to take into
|
||||
* account that it could be binary and full of nulls, see bug 105417. Also, we need
|
||||
* to make a copy of the buffer because the plugin may have allocated it on the stack.
|
||||
* For an example of this, see Shockwave registration or bug 108966
|
||||
* We malloc only for headers here, buffer for data itself is malloced by ParsePostBufferToFixHeaders()
|
||||
*/
|
||||
|
||||
inline nsresult
|
||||
NS_NewPluginPostDataStream(nsIInputStream **result,
|
||||
const char *data,
|
||||
PRUint32 contentLength,
|
||||
PRBool isFile = PR_FALSE,
|
||||
PRBool headers = PR_FALSE)
|
||||
{
|
||||
nsresult rv = NS_ERROR_UNEXPECTED;
|
||||
if (!data)
|
||||
return rv;
|
||||
|
||||
if (!isFile) { // do raw data case first
|
||||
if (contentLength < 1)
|
||||
return rv;
|
||||
|
||||
char *buf = (char*) data;
|
||||
if (headers) {
|
||||
// in assumption we got correctly formated headers just passed in
|
||||
if (!(buf = (char*)nsMemory::Alloc(contentLength)))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
memcpy(buf, data, contentLength);
|
||||
}
|
||||
nsCOMPtr<nsIStringInputStream> sis = do_CreateInstance("@mozilla.org/io/string-input-stream;1",&rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
sis->AdoptData(buf, contentLength); // let the string stream manage our data
|
||||
rv = CallQueryInterface(sis, result);
|
||||
}
|
||||
else if (headers) {
|
||||
nsMemory::Free(buf); // Cleanup the memory if the data was copied.
|
||||
}
|
||||
} else {
|
||||
nsCOMPtr<nsILocalFile> file; // tmp file will be deleted on release of stream
|
||||
nsCOMPtr<nsIInputStream> fileStream;
|
||||
if (NS_SUCCEEDED(rv = NS_NewNativeLocalFile(nsDependentCString(data), PR_FALSE, getter_AddRefs(file))) &&
|
||||
NS_SUCCEEDED(rv = NS_NewLocalFileInputStream(getter_AddRefs(fileStream),
|
||||
file,
|
||||
PR_RDONLY,
|
||||
0600,
|
||||
nsIFileInputStream::DELETE_ON_CLOSE |
|
||||
nsIFileInputStream::CLOSE_ON_EOF))) {
|
||||
// wrap the file stream with a buffered input stream
|
||||
return NS_NewBufferedInputStream(result, fileStream, 8192);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
#endif
|
||||
%}
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "nsISupports.idl"
|
||||
#include "nspluginroot.idl"
|
||||
#include "nsIPlugin.idl"
|
||||
#include "nsIInputStream.idl"
|
||||
|
||||
interface nsIPluginInstance;
|
||||
interface nsIDocument;
|
||||
@ -49,7 +50,7 @@ class nsPluginEvent;
|
||||
|
||||
[ref] native nsIPluginInstanceRef(nsIPluginInstance*);
|
||||
|
||||
[uuid(D8776CDC-00DF-4395-A432-2E78EBCC12B6)]
|
||||
[uuid(B48DC23E-C20B-4292-974E-E8FF97B9F1CC)]
|
||||
interface nsIPluginInstanceOwner : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -88,9 +89,8 @@ interface nsIPluginInstanceOwner : nsISupports
|
||||
*/
|
||||
NS_IMETHOD
|
||||
GetURL(const char *aURL, const char *aTarget,
|
||||
void *aPostData, PRUint32 aPostDataLen,
|
||||
void *aHeadersData, PRUint32 aHeadersDataLen,
|
||||
PRBool aIsFile = PR_FALSE) = 0;
|
||||
nsIInputStream *aPostStream,
|
||||
void *aHeadersData, PRUint32 aHeadersDataLen) = 0;
|
||||
%}
|
||||
|
||||
/**
|
||||
|
@ -141,7 +141,7 @@ nsPluginStreamToFile::Write(const char* aBuf, PRUint32 aCount,
|
||||
{
|
||||
mOutputStream->Write(aBuf, aCount, aWriteCount);
|
||||
mOutputStream->Flush();
|
||||
mOwner->GetURL(mFileURL.get(), mTarget, nsnull, 0, nsnull, 0);
|
||||
mOwner->GetURL(mFileURL.get(), mTarget, nsnull, nsnull, 0);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -173,7 +173,7 @@ NS_IMETHODIMP
|
||||
nsPluginStreamToFile::Close(void)
|
||||
{
|
||||
mOutputStream->Close();
|
||||
mOwner->GetURL(mFileURL.get(), mTarget, nsnull, 0, nsnull, 0);
|
||||
mOwner->GetURL(mFileURL.get(), mTarget, nsnull, nsnull, 0);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2016,13 +2016,13 @@ nsresult nsPluginHost::GetURLWithHeaders(nsISupports* pluginInst,
|
||||
else if (0 == PL_strcmp(target, "_current"))
|
||||
target = "_self";
|
||||
|
||||
rv = owner->GetURL(url, target, nsnull, 0, (void *) getHeaders, getHeadersLength);
|
||||
rv = owner->GetURL(url, target, nsnull, nsnull, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (streamListener)
|
||||
rv = NewPluginURLStream(string, instance, streamListener, nsnull,
|
||||
PR_FALSE, nsnull, getHeaders, getHeadersLength);
|
||||
getHeaders, getHeadersLength);
|
||||
|
||||
return rv;
|
||||
}
|
||||
@ -2059,22 +2059,44 @@ NS_IMETHODIMP nsPluginHost::PostURL(nsISupports* pluginInst,
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
char *dataToPost;
|
||||
nsCOMPtr<nsIInputStream> postStream;
|
||||
if (isFile) {
|
||||
rv = CreateTmpFileToPost(postData, &dataToPost);
|
||||
if (NS_FAILED(rv) || !dataToPost)
|
||||
nsCOMPtr<nsIFile> file;
|
||||
rv = CreateTempFileToPost(postData, getter_AddRefs(file));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsIInputStream> fileStream;
|
||||
rv = NS_NewLocalFileInputStream(getter_AddRefs(fileStream),
|
||||
file,
|
||||
PR_RDONLY,
|
||||
0600,
|
||||
nsIFileInputStream::DELETE_ON_CLOSE |
|
||||
nsIFileInputStream::CLOSE_ON_EOF);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
rv = NS_NewBufferedInputStream(getter_AddRefs(postStream), fileStream, 8192);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
} else {
|
||||
char *dataToPost;
|
||||
PRUint32 newDataToPostLen;
|
||||
ParsePostBufferToFixHeaders(postData, postDataLen, &dataToPost, &newDataToPostLen);
|
||||
if (!dataToPost)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
// we use nsIStringInputStream::adoptDataa()
|
||||
// in NS_NewPluginPostDataStream to set the stream
|
||||
// all new data alloced in ParsePostBufferToFixHeaders()
|
||||
// well be nsMemory::Free()d on destroy the stream
|
||||
nsCOMPtr<nsIStringInputStream> sis = do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv);
|
||||
if (!sis) {
|
||||
NS_Free(dataToPost);
|
||||
return rv;
|
||||
}
|
||||
|
||||
// data allocated by ParsePostBufferToFixHeaders() is managed and
|
||||
// freed by the string stream.
|
||||
postDataLen = newDataToPostLen;
|
||||
sis->AdoptData(dataToPost, postDataLen);
|
||||
postStream = sis;
|
||||
}
|
||||
|
||||
if (target) {
|
||||
@ -2091,8 +2113,8 @@ NS_IMETHODIMP nsPluginHost::PostURL(nsISupports* pluginInst,
|
||||
target = "_self";
|
||||
}
|
||||
}
|
||||
rv = owner->GetURL(url, target, (void*)dataToPost, postDataLen,
|
||||
(void*)postHeaders, postHeadersLength, isFile);
|
||||
rv = owner->GetURL(url, target, postStream,
|
||||
(void*)postHeaders, postHeadersLength);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2100,10 +2122,7 @@ NS_IMETHODIMP nsPluginHost::PostURL(nsISupports* pluginInst,
|
||||
// NS_OpenURI()!
|
||||
if (streamListener)
|
||||
rv = NewPluginURLStream(string, instance, streamListener,
|
||||
(const char*)dataToPost, isFile, postDataLen,
|
||||
postHeaders, postHeadersLength);
|
||||
if (isFile)
|
||||
NS_Free(dataToPost);
|
||||
postStream, postHeaders, postHeadersLength);
|
||||
|
||||
return rv;
|
||||
}
|
||||
@ -4300,9 +4319,7 @@ nsPluginHost::EnsurePrivateDirServiceProvider()
|
||||
nsresult nsPluginHost::NewPluginURLStream(const nsString& aURL,
|
||||
nsIPluginInstance *aInstance,
|
||||
nsIPluginStreamListener* aListener,
|
||||
const char *aPostData,
|
||||
PRBool aIsFile,
|
||||
PRUint32 aPostDataLen,
|
||||
nsIInputStream *aPostStream,
|
||||
const char *aHeadersData,
|
||||
PRUint32 aHeadersDataLen)
|
||||
{
|
||||
@ -4353,16 +4370,13 @@ nsresult nsPluginHost::NewPluginURLStream(const nsString& aURL,
|
||||
return NS_ERROR_CONTENT_BLOCKED;
|
||||
}
|
||||
|
||||
nsPluginStreamListenerPeer *listenerPeer = new nsPluginStreamListenerPeer;
|
||||
nsRefPtr<nsPluginStreamListenerPeer> listenerPeer = new nsPluginStreamListenerPeer();
|
||||
if (listenerPeer == NULL)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(listenerPeer);
|
||||
rv = listenerPeer->Initialize(url, aInstance, aListener);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_RELEASE(listenerPeer);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIInterfaceRequestor> callbacks;
|
||||
if (doc) {
|
||||
@ -4402,36 +4416,25 @@ nsresult nsPluginHost::NewPluginURLStream(const nsString& aURL,
|
||||
// deal with headers and post data
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
|
||||
if (httpChannel) {
|
||||
if (aPostData) {
|
||||
nsCOMPtr<nsIInputStream> postDataStream;
|
||||
rv = NS_NewPluginPostDataStream(getter_AddRefs(postDataStream), (const char*)aPostData,
|
||||
aPostDataLen, aIsFile);
|
||||
|
||||
if (!postDataStream) {
|
||||
NS_RELEASE(aInstance);
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (aPostStream) {
|
||||
// XXX it's a bit of a hack to rewind the postdata stream
|
||||
// here but it has to be done in case the post data is
|
||||
// being reused multiple times.
|
||||
nsCOMPtr<nsISeekableStream>
|
||||
postDataSeekable(do_QueryInterface(postDataStream));
|
||||
postDataSeekable(do_QueryInterface(aPostStream));
|
||||
if (postDataSeekable)
|
||||
postDataSeekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
|
||||
|
||||
nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel));
|
||||
NS_ASSERTION(uploadChannel, "http must support nsIUploadChannel");
|
||||
|
||||
uploadChannel->SetUploadStream(postDataStream, EmptyCString(), -1);
|
||||
uploadChannel->SetUploadStream(aPostStream, EmptyCString(), -1);
|
||||
}
|
||||
|
||||
if (aHeadersData)
|
||||
rv = AddHeadersToChannel(aHeadersData, aHeadersDataLen, httpChannel);
|
||||
}
|
||||
rv = channel->AsyncOpen(listenerPeer, nsnull);
|
||||
|
||||
NS_RELEASE(listenerPeer);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -4919,20 +4922,19 @@ nsPluginHost::ParsePostBufferToFixHeaders(const char *inPostData, PRUint32 inPos
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginHost::CreateTmpFileToPost(const char *postDataURL, char **pTmpFileName)
|
||||
nsPluginHost::CreateTempFileToPost(const char *aPostDataURL, nsIFile **aTmpFile)
|
||||
{
|
||||
*pTmpFileName = 0;
|
||||
nsresult rv;
|
||||
PRInt64 fileSize;
|
||||
nsCAutoString filename;
|
||||
|
||||
// stat file == get size & convert file:///c:/ to c: if needed
|
||||
nsCOMPtr<nsIFile> inFile;
|
||||
rv = NS_GetFileFromURLSpec(nsDependentCString(postDataURL),
|
||||
rv = NS_GetFileFromURLSpec(nsDependentCString(aPostDataURL),
|
||||
getter_AddRefs(inFile));
|
||||
if (NS_FAILED(rv)) {
|
||||
nsCOMPtr<nsILocalFile> localFile;
|
||||
rv = NS_NewNativeLocalFile(nsDependentCString(postDataURL), PR_FALSE,
|
||||
rv = NS_NewNativeLocalFile(nsDependentCString(aPostDataURL), PR_FALSE,
|
||||
getter_AddRefs(localFile));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
inFile = localFile;
|
||||
@ -5014,11 +5016,8 @@ nsPluginHost::CreateTmpFileToPost(const char *postDataURL, char **pTmpFileName)
|
||||
|
||||
inStream->Close();
|
||||
outStream->Close();
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCAutoString path;
|
||||
if (NS_SUCCEEDED(tempFile->GetNativePath(path)))
|
||||
*pTmpFileName = ToNewCString(path);
|
||||
}
|
||||
if (NS_SUCCEEDED(rv))
|
||||
*aTmpFile = tempFile.forget().get();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
@ -117,9 +117,7 @@ public:
|
||||
NewPluginURLStream(const nsString& aURL,
|
||||
nsIPluginInstance *aInstance,
|
||||
nsIPluginStreamListener *aListener,
|
||||
const char *aPostData = nsnull,
|
||||
PRBool isFile = PR_FALSE,
|
||||
PRUint32 aPostDataLen = 0,
|
||||
nsIInputStream *aPostStream = nsnull,
|
||||
const char *aHeadersData = nsnull,
|
||||
PRUint32 aHeadersDataLen = 0);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user