Bug 1163900 - crash in mozilla::net::nsHttpChannelCacheKey::GetData(unsigned int*, nsACString_internal&), r=jduell

This commit is contained in:
Michal Novotny 2015-05-14 19:05:34 +02:00
parent 14e1cf68d0
commit 813043df3e
9 changed files with 64 additions and 156 deletions

View File

@ -32,11 +32,11 @@ interface nsICacheInfoChannel : nsISupports
* for this channel. Holding a reference to this key does NOT prevent
* the cached data from being removed.
*
* A cache key retrieved from a particular instance of nsICachingChannel
* could be set on another instance of nsICachingChannel provided the
* A cache key retrieved from a particular instance of nsICacheInfoChannel
* could be set on another instance of nsICacheInfoChannel provided the
* underlying implementations are compatible and provided the new
* channel instance was created with the same URI. The implementation of
* nsICachingChannel would be expected to use the cache entry identified
* nsICacheInfoChannel would be expected to use the cache entry identified
* by the cache token. Depending on the value of nsIRequest::loadFlags,
* the cache entry may be validated, overwritten, or simply read.
*

View File

@ -30,18 +30,6 @@ union OptionalHttpResponseHead
nsHttpResponseHead;
};
struct HttpChannelCacheKey
{
uint32_t postId;
nsCString key;
};
union OptionalHttpChannelCacheKey
{
void_t;
HttpChannelCacheKey;
};
struct HttpChannelOpenArgs
{
URIParams uri;
@ -79,7 +67,7 @@ struct HttpChannelOpenArgs
uint32_t contentPolicyType;
uint32_t innerWindowID;
OptionalHttpResponseHead synthesizedResponseHead;
OptionalHttpChannelCacheKey cacheKey;
uint32_t cacheKey;
};
struct HttpChannelConnectArgs

View File

@ -324,7 +324,7 @@ class StartRequestEvent : public ChannelEvent
const nsCString& securityInfoSerialization,
const NetAddr& selfAddr,
const NetAddr& peerAddr,
const HttpChannelCacheKey& cacheKey)
const uint32_t& cacheKey)
: mChild(child)
, mChannelStatus(channelStatus)
, mResponseHead(responseHead)
@ -362,7 +362,7 @@ class StartRequestEvent : public ChannelEvent
nsCString mSecurityInfoSerialization;
NetAddr mSelfAddr;
NetAddr mPeerAddr;
HttpChannelCacheKey mCacheKey;
uint32_t mCacheKey;
};
bool
@ -378,7 +378,7 @@ HttpChannelChild::RecvOnStartRequest(const nsresult& channelStatus,
const NetAddr& selfAddr,
const NetAddr& peerAddr,
const int16_t& redirectCount,
const HttpChannelCacheKey& cacheKey)
const uint32_t& cacheKey)
{
LOG(("HttpChannelChild::RecvOnStartRequest [this=%p]\n", this));
// mFlushedForDiversion and mDivertingToParent should NEVER be set at this
@ -419,7 +419,7 @@ HttpChannelChild::OnStartRequest(const nsresult& channelStatus,
const nsCString& securityInfoSerialization,
const NetAddr& selfAddr,
const NetAddr& peerAddr,
const HttpChannelCacheKey& cacheKey)
const uint32_t& cacheKey)
{
LOG(("HttpChannelChild::OnStartRequest [this=%p]\n", this));
@ -447,12 +447,23 @@ HttpChannelChild::OnStartRequest(const nsresult& channelStatus,
mCacheExpirationTime = cacheExpirationTime;
mCachedCharset = cachedCharset;
nsRefPtr<nsHttpChannelCacheKey> tmpKey = new nsHttpChannelCacheKey();
tmpKey->SetData(cacheKey.postId(), cacheKey.key());
CallQueryInterface(tmpKey.get(), getter_AddRefs(mCacheKey));
AutoEventEnqueuer ensureSerialDispatch(mEventQ);
nsresult rv;
nsCOMPtr<nsISupportsPRUint32> container =
do_CreateInstance(NS_SUPPORTS_PRUINT32_CONTRACTID, &rv);
if (NS_FAILED(rv)) {
Cancel(rv);
return;
}
rv = container->SetData(cacheKey);
if (NS_FAILED(rv)) {
Cancel(rv);
return;
}
mCacheKey = container;
// replace our request headers with what actually got sent in the parent
mRequestHead.Headers() = requestHeaders;
@ -1657,19 +1668,19 @@ HttpChannelChild::ContinueAsyncOpen()
openArgs.allowSpdy() = mAllowSpdy;
openArgs.allowAltSvc() = mAllowAltSvc;
uint32_t cacheKey = 0;
if (mCacheKey) {
uint32_t postId;
nsAutoCString key;
nsresult rv = static_cast<nsHttpChannelCacheKey *>(
static_cast<nsISupportsPRUint32 *>(mCacheKey.get()))->GetData(&postId,
key);
nsCOMPtr<nsISupportsPRUint32> container = do_QueryInterface(mCacheKey);
if (!container) {
return NS_ERROR_ILLEGAL_VALUE;
}
nsresult rv = container->GetData(&cacheKey);
if (NS_FAILED(rv)) {
return rv;
}
openArgs.cacheKey() = HttpChannelCacheKey(postId, key);
} else {
openArgs.cacheKey() = mozilla::void_t();
}
openArgs.cacheKey() = cacheKey;
propagateLoadInfo(mLoadInfo, openArgs);

View File

@ -118,7 +118,7 @@ protected:
const NetAddr& selfAddr,
const NetAddr& peerAddr,
const int16_t& redirectCount,
const HttpChannelCacheKey& cacheKey) override;
const uint32_t& cacheKey) override;
bool RecvOnTransportAndData(const nsresult& channelStatus,
const nsresult& status,
const uint64_t& progress,
@ -211,7 +211,7 @@ private:
const nsCString& securityInfoSerialization,
const NetAddr& selfAddr,
const NetAddr& peerAddr,
const HttpChannelCacheKey& cacheKey);
const uint32_t& cacheKey);
void OnTransportAndData(const nsresult& channelStatus,
const nsresult& status,
const uint64_t progress,

View File

@ -268,7 +268,7 @@ HttpChannelParent::DoAsyncOpen( const URIParams& aURI,
const uint32_t& aContentPolicyType,
const uint32_t& aInnerWindowID,
const OptionalHttpResponseHead& aSynthesizedResponseHead,
const OptionalHttpChannelCacheKey& aCacheKey)
const uint32_t& aCacheKey)
{
nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
if (!uri) {
@ -390,15 +390,19 @@ HttpChannelParent::DoAsyncOpen( const URIParams& aURI,
mSynthesizedResponseHead = new nsHttpResponseHead(aSynthesizedResponseHead.get_nsHttpResponseHead());
}
if (aCacheKey.type() == OptionalHttpChannelCacheKey::THttpChannelCacheKey) {
nsRefPtr<nsHttpChannelCacheKey> cacheKey = new nsHttpChannelCacheKey();
cacheKey->SetData(aCacheKey.get_HttpChannelCacheKey().postId(),
aCacheKey.get_HttpChannelCacheKey().key());
nsCOMPtr<nsISupports> cacheKeySupp;
CallQueryInterface(cacheKey.get(), getter_AddRefs(cacheKeySupp));
mChannel->SetCacheKey(cacheKeySupp);
nsCOMPtr<nsISupportsPRUint32> cacheKey =
do_CreateInstance(NS_SUPPORTS_PRUINT32_CONTRACTID, &rv);
if (NS_FAILED(rv)) {
return SendFailedAsyncOpen(rv);
}
rv = cacheKey->SetData(aCacheKey);
if (NS_FAILED(rv)) {
return SendFailedAsyncOpen(rv);
}
mChannel->SetCacheKey(cacheKey);
if (priority != nsISupportsPriority::PRIORITY_NORMAL) {
mChannel->SetPriority(priority);
}
@ -815,19 +819,20 @@ HttpChannelParent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
uint16_t redirectCount = 0;
mChannel->GetRedirectCount(&redirectCount);
nsCOMPtr<nsISupports> cacheKeySupp;
mChannel->GetCacheKey(getter_AddRefs(cacheKeySupp));
uint32_t postId = 0;
nsAutoCString key;
if (cacheKeySupp) {
nsresult rv = static_cast<nsHttpChannelCacheKey *>(
static_cast<nsISupportsPRUint32 *>(cacheKeySupp.get()))->GetData(&postId,
key);
nsCOMPtr<nsISupports> cacheKey;
mChannel->GetCacheKey(getter_AddRefs(cacheKey));
uint32_t cacheKeyValue = 0;
if (cacheKey) {
nsCOMPtr<nsISupportsPRUint32> container = do_QueryInterface(cacheKey);
if (!container) {
return NS_ERROR_ILLEGAL_VALUE;
}
nsresult rv = container->GetData(&cacheKeyValue);
if (NS_FAILED(rv)) {
return rv;
}
}
HttpChannelCacheKey cacheKey = HttpChannelCacheKey(postId, key);
if (mIPCClosed ||
!SendOnStartRequest(channelStatus,
@ -839,7 +844,7 @@ HttpChannelParent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
expirationTime, cachedCharset, secInfoSerialization,
mChannel->GetSelfAddr(), mChannel->GetPeerAddr(),
redirectCount,
cacheKey))
cacheKeyValue))
{
return NS_ERROR_UNEXPECTED;
}

View File

@ -122,7 +122,7 @@ protected:
const uint32_t& aContentPolicyType,
const uint32_t& aInnerWindowID,
const OptionalHttpResponseHead& aSynthesizedResponseHead,
const OptionalHttpChannelCacheKey& aCacheKey);
const uint32_t& aCacheKey);
virtual bool RecvSetPriority(const uint16_t& priority) override;
virtual bool RecvSetClassOfService(const uint32_t& cos) override;

View File

@ -8,13 +8,15 @@
include protocol PNecko;
include InputStreamParams;
include URIParams;
include NeckoChannelParams;
include protocol PBlob; //FIXME: bug #792908
include "mozilla/net/NeckoMessageUtils.h";
using RequestHeaderTuples from "mozilla/net/PHttpChannelParams.h";
using class nsHttpHeaderArray from "nsHttpHeaderArray.h";
using class nsHttpResponseHead from "nsHttpResponseHead.h";
using struct nsHttpAtom from "nsHttp.h";
using mozilla::net::NetAddr from "mozilla/net/DNS.h";
using struct mozilla::net::ResourceTimingStruct from "mozilla/net/TimingStruct.h";
@ -92,7 +94,7 @@ child:
NetAddr selfAddr,
NetAddr peerAddr,
int16_t redirectCount,
HttpChannelCacheKey cacheKey);
uint32_t cacheKey);
// Combines a single OnDataAvailable and its associated OnProgress &
// OnStatus calls into one IPDL message

View File

@ -6037,69 +6037,9 @@ nsHttpChannel::SetOfflineCacheToken(nsISupports *token)
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMPL_ADDREF(nsHttpChannelCacheKey)
NS_IMPL_RELEASE(nsHttpChannelCacheKey)
NS_INTERFACE_TABLE_HEAD(nsHttpChannelCacheKey)
NS_INTERFACE_TABLE_BEGIN
NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(nsHttpChannelCacheKey,
nsISupports, nsISupportsPRUint32)
NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(nsHttpChannelCacheKey,
nsISupportsPrimitive, nsISupportsPRUint32)
NS_INTERFACE_TABLE_ENTRY(nsHttpChannelCacheKey,
nsISupportsPRUint32)
NS_INTERFACE_TABLE_ENTRY(nsHttpChannelCacheKey,
nsISupportsCString)
NS_INTERFACE_TABLE_END
NS_INTERFACE_TABLE_TAIL
NS_IMETHODIMP nsHttpChannelCacheKey::GetType(uint16_t *aType)
{
NS_ENSURE_ARG_POINTER(aType);
*aType = TYPE_PRUINT32;
return NS_OK;
}
nsresult nsHttpChannelCacheKey::SetData(uint32_t aPostID,
const nsACString& aKey)
{
nsresult rv;
mSupportsCString =
do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv;
mSupportsCString->SetData(aKey);
if (NS_FAILED(rv)) return rv;
mSupportsPRUint32 =
do_CreateInstance(NS_SUPPORTS_PRUINT32_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv;
mSupportsPRUint32->SetData(aPostID);
if (NS_FAILED(rv)) return rv;
return NS_OK;
}
nsresult nsHttpChannelCacheKey::GetData(uint32_t *aPostID,
nsACString& aKey)
{
nsresult rv;
rv = mSupportsPRUint32->GetData(aPostID);
if (NS_FAILED(rv)) {
return rv;
}
return mSupportsCString->GetData(aKey);
}
NS_IMETHODIMP
nsHttpChannel::GetCacheKey(nsISupports **key)
{
// mayhemer: TODO - do we need this API?
nsresult rv;
NS_ENSURE_ARG_POINTER(key);
@ -6107,17 +6047,13 @@ nsHttpChannel::GetCacheKey(nsISupports **key)
*key = nullptr;
nsRefPtr<nsHttpChannelCacheKey> container =
new nsHttpChannelCacheKey();
nsCOMPtr<nsISupportsPRUint32> container =
do_CreateInstance(NS_SUPPORTS_PRUINT32_CONTRACTID, &rv);
if (!container)
return NS_ERROR_OUT_OF_MEMORY;
nsAutoCString cacheKey;
rv = GenerateCacheKey(mPostID, cacheKey);
if (NS_FAILED(rv)) return rv;
rv = container->SetData(mPostID, cacheKey);
rv = container->SetData(mPostID);
if (NS_FAILED(rv)) return rv;
return CallQueryInterface(container.get(), key);

View File

@ -40,40 +40,6 @@ public:
const nsAString& aMessageCategory) = 0;
};
//-----------------------------------------------------------------------------
// nsHttpChannelCacheKey
//-----------------------------------------------------------------------------
class nsHttpChannelCacheKey final : public nsISupportsPRUint32,
public nsISupportsCString
{
NS_DECL_ISUPPORTS
NS_DECL_NSISUPPORTSPRIMITIVE
NS_FORWARD_NSISUPPORTSPRUINT32(mSupportsPRUint32->)
// Both interfaces declares toString method with the same signature.
// Thus we have to delegate only to nsISupportsPRUint32 implementation.
NS_IMETHOD GetData(nsACString & aData) override
{
return mSupportsCString->GetData(aData);
}
NS_IMETHOD SetData(const nsACString & aData) override
{
return mSupportsCString->SetData(aData);
}
public:
nsresult SetData(uint32_t aPostID, const nsACString& aKey);
nsresult GetData(uint32_t *aPostID, nsACString& aKey);
protected:
~nsHttpChannelCacheKey() {}
nsCOMPtr<nsISupportsPRUint32> mSupportsPRUint32;
nsCOMPtr<nsISupportsCString> mSupportsCString;
};
//-----------------------------------------------------------------------------
// nsHttpChannel
//-----------------------------------------------------------------------------