Guard against re-entrancy in nsStringStream.

This commit is contained in:
wolfbeast 2019-03-22 13:28:32 +01:00 committed by Roy Tam
commit c7295cf476

View file

@ -22,6 +22,7 @@
#include "nsIClassInfoImpl.h"
#include "mozilla/Attributes.h"
#include "mozilla/ipc/InputStreamUtils.h"
#include "mozilla/ReentrantMonitor.h"
#include "nsIIPCSerializableInputStream.h"
using namespace mozilla::ipc;
@ -50,6 +51,7 @@ public:
NS_DECL_NSICLONEABLEINPUTSTREAM
nsStringInputStream()
: mMon("nsStringInputStream")
{
Clear();
}
@ -89,6 +91,8 @@ private:
nsDependentCSubstring mData;
uint32_t mOffset;
mozilla::ReentrantMonitor mMon;
};
// This class needs to support threadsafe refcounting since people often
@ -126,6 +130,8 @@ nsStringInputStream::GetType(uint16_t* aType)
NS_IMETHODIMP
nsStringInputStream::GetData(nsACString& data)
{
ReentrantMonitorAutoEnter lock(mMon);
// The stream doesn't have any data when it is closed. We could fake it
// and return an empty string here, but it seems better to keep this return
// value consistent with the behavior of the other 'getter' methods.
@ -140,6 +146,8 @@ nsStringInputStream::GetData(nsACString& data)
NS_IMETHODIMP
nsStringInputStream::SetData(const nsACString& aData)
{
ReentrantMonitorAutoEnter lock(mMon);
mData.Assign(aData);
mOffset = 0;
return NS_OK;
@ -159,6 +167,8 @@ nsStringInputStream::ToString(char** aResult)
NS_IMETHODIMP
nsStringInputStream::SetData(const char* aData, int32_t aDataLen)
{
ReentrantMonitorAutoEnter lock(mMon);
if (NS_WARN_IF(!aData)) {
return NS_ERROR_INVALID_ARG;
}
@ -170,6 +180,8 @@ nsStringInputStream::SetData(const char* aData, int32_t aDataLen)
NS_IMETHODIMP
nsStringInputStream::AdoptData(char* aData, int32_t aDataLen)
{
ReentrantMonitorAutoEnter lock(mMon);
if (NS_WARN_IF(!aData)) {
return NS_ERROR_INVALID_ARG;
}
@ -181,6 +193,8 @@ nsStringInputStream::AdoptData(char* aData, int32_t aDataLen)
NS_IMETHODIMP
nsStringInputStream::ShareData(const char* aData, int32_t aDataLen)
{
ReentrantMonitorAutoEnter lock(mMon);
if (NS_WARN_IF(!aData)) {
return NS_ERROR_INVALID_ARG;
}
@ -197,6 +211,8 @@ nsStringInputStream::ShareData(const char* aData, int32_t aDataLen)
NS_IMETHODIMP_(size_t)
nsStringInputStream::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf)
{
ReentrantMonitorAutoEnter lock(mMon);
size_t n = aMallocSizeOf(this);
n += mData.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
return n;
@ -209,6 +225,8 @@ nsStringInputStream::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf)
NS_IMETHODIMP
nsStringInputStream::Close()
{
ReentrantMonitorAutoEnter lock(mMon);
Clear();
return NS_OK;
}
@ -216,6 +234,8 @@ nsStringInputStream::Close()
NS_IMETHODIMP
nsStringInputStream::Available(uint64_t* aLength)
{
ReentrantMonitorAutoEnter lock(mMon);
NS_ASSERTION(aLength, "null ptr");
if (Closed()) {
@ -237,6 +257,8 @@ NS_IMETHODIMP
nsStringInputStream::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
uint32_t aCount, uint32_t* aResult)
{
ReentrantMonitorAutoEnter lock(mMon);
NS_ASSERTION(aResult, "null ptr");
NS_ASSERTION(Length() >= mOffset, "bad stream state");
@ -280,6 +302,8 @@ nsStringInputStream::IsNonBlocking(bool* aNonBlocking)
NS_IMETHODIMP
nsStringInputStream::Seek(int32_t aWhence, int64_t aOffset)
{
ReentrantMonitorAutoEnter lock(mMon);
if (Closed()) {
return NS_BASE_STREAM_CLOSED;
}
@ -312,6 +336,8 @@ nsStringInputStream::Seek(int32_t aWhence, int64_t aOffset)
NS_IMETHODIMP
nsStringInputStream::Tell(int64_t* aOutWhere)
{
ReentrantMonitorAutoEnter lock(mMon);
if (Closed()) {
return NS_BASE_STREAM_CLOSED;
}
@ -323,6 +349,8 @@ nsStringInputStream::Tell(int64_t* aOutWhere)
NS_IMETHODIMP
nsStringInputStream::SetEOF()
{
ReentrantMonitorAutoEnter lock(mMon);
if (Closed()) {
return NS_BASE_STREAM_CLOSED;
}
@ -339,6 +367,8 @@ void
nsStringInputStream::Serialize(InputStreamParams& aParams,
FileDescriptorArray& /* aFDs */)
{
ReentrantMonitorAutoEnter lock(mMon);
StringInputStreamParams params;
params.data() = PromiseFlatCString(mData);
aParams = params;
@ -367,6 +397,8 @@ nsStringInputStream::Deserialize(const InputStreamParams& aParams,
Maybe<uint64_t>
nsStringInputStream::ExpectedSerializedLength()
{
ReentrantMonitorAutoEnter lock(mMon);
return Some(static_cast<uint64_t>(Length()));
}
@ -384,6 +416,8 @@ nsStringInputStream::GetCloneable(bool* aCloneableOut)
NS_IMETHODIMP
nsStringInputStream::Clone(nsIInputStream** aCloneOut)
{
ReentrantMonitorAutoEnter lock(mMon);
RefPtr<nsIInputStream> ref = new nsStringInputStream(*this);
ref.forget(aCloneOut);
return NS_OK;