// Caller is responsible for freeing returned buffer. static char* CFStringRefToUTF8Buffer(CFStringRef cfString) { const char* buffer = ::CFStringGetCStringPtr(cfString, kCFStringEncodingUTF8); if (buffer) { return PL_strdup(buffer); } int bufferLength = ::CFStringGetMaximumSizeForEncoding(::CFStringGetLength(cfString), kCFStringEncodingUTF8) + 1; char* newBuffer = static_cast<char*>(moz_xmalloc(bufferLength)); if (!newBuffer) { return nullptr; } if (!::CFStringGetCString(cfString, newBuffer, bufferLength, kCFStringEncodingUTF8)) { free(newBuffer); return nullptr; } newBuffer = static_cast<char*>(moz_xrealloc(newBuffer, strlen(newBuffer) + 1)); return newBuffer; }
void CacheFileMetadata::EnsureBuffer(uint32_t aSize) { if (mBufSize < aSize) { if (mAllocExactSize) { // If this is not the only allocation, use power of two for following // allocations. mAllocExactSize = false; } else { // find smallest power of 2 greater than or equal to aSize --aSize; aSize |= aSize >> 1; aSize |= aSize >> 2; aSize |= aSize >> 4; aSize |= aSize >> 8; aSize |= aSize >> 16; ++aSize; } if (aSize < kInitialBufSize) { aSize = kInitialBufSize; } mBufSize = aSize; mBuf = static_cast<char *>(moz_xrealloc(mBuf, mBufSize)); DoMemoryReport(MemoryUsage()); } }
nsresult CacheFileMetadata::SetHash(uint32_t aIndex, CacheHash::Hash16_t aHash) { LOG(("CacheFileMetadata::SetHash() [this=%p, idx=%d, hash=%x]", this, aIndex, aHash)); MarkDirty(); MOZ_ASSERT(aIndex <= mHashCount); if (aIndex > mHashCount) { return NS_ERROR_INVALID_ARG; } else if (aIndex == mHashCount) { if ((aIndex + 1) * sizeof(CacheHash::Hash16_t) > mHashArraySize) { // reallocate hash array buffer if (mHashArraySize == 0) mHashArraySize = 32 * sizeof(CacheHash::Hash16_t); else mHashArraySize *= 2; mHashArray = static_cast<CacheHash::Hash16_t *>( moz_xrealloc(mHashArray, mHashArraySize)); } mHashCount++; } NetworkEndian::writeUint16(&mHashArray[aIndex], aHash); DoMemoryReport(MemoryUsage()); return NS_OK; }
bool nsSocketTransportService::GrowActiveList() { int32_t toAdd = gMaxCount - mActiveListSize; if (toAdd > 100) { toAdd = 100; } else if (toAdd < 1) { MOZ_ASSERT(false, "CanAttachSocket() should prevent this"); return false; } mActiveListSize += toAdd; mActiveList = (SocketContext *) moz_xrealloc(mActiveList, sizeof(SocketContext) * mActiveListSize); mPollList = (PRPollDesc *) moz_xrealloc(mPollList, sizeof(PRPollDesc) * (mActiveListSize + 1)); return true; }
void* moz_xrealloc(void* ptr, size_t size) { void* newptr = realloc(ptr, size); if (UNLIKELY(!newptr)) { mozalloc_handle_oom(); return moz_xrealloc(ptr, size); } return newptr; }
void CacheFileMetadata::EnsureBuffer(uint32_t aSize) { if (mBufSize < aSize) { mBufSize = aSize; mBuf = static_cast<char *>(moz_xrealloc(mBuf, mBufSize)); } DoMemoryReport(MemoryUsage()); }
char* nsSegmentedBuffer::AppendNewSegment() { if (GetSize() >= mMaxSize) { return nullptr; } if (!mSegmentArray) { uint32_t bytes = mSegmentArrayCount * sizeof(char*); mSegmentArray = (char**)moz_xmalloc(bytes); if (!mSegmentArray) { return nullptr; } memset(mSegmentArray, 0, bytes); } if (IsFull()) { uint32_t newArraySize = mSegmentArrayCount * 2; uint32_t bytes = newArraySize * sizeof(char*); char** newSegArray = (char**)moz_xrealloc(mSegmentArray, bytes); if (!newSegArray) { return nullptr; } mSegmentArray = newSegArray; // copy wrapped content to new extension if (mFirstSegmentIndex > mLastSegmentIndex) { // deal with wrap around case memcpy(&mSegmentArray[mSegmentArrayCount], mSegmentArray, mLastSegmentIndex * sizeof(char*)); memset(mSegmentArray, 0, mLastSegmentIndex * sizeof(char*)); mLastSegmentIndex += mSegmentArrayCount; memset(&mSegmentArray[mLastSegmentIndex], 0, (newArraySize - mLastSegmentIndex) * sizeof(char*)); } else { memset(&mSegmentArray[mLastSegmentIndex], 0, (newArraySize - mLastSegmentIndex) * sizeof(char*)); } mSegmentArrayCount = newArraySize; } char* seg = (char*)malloc(mSegmentSize); if (!seg) { return nullptr; } mSegmentArray[mLastSegmentIndex] = seg; mLastSegmentIndex = ModSegArraySize(mLastSegmentIndex + 1); return seg; }
void* moz_xrealloc(void* ptr, size_t size) { // Ensure that we have reasonable realloc semantics, regardless of the // underlying malloc implementation. if (UNLIKELY(!ptr && !size)) { return nullptr; } void* newptr = realloc(ptr, size); if (UNLIKELY(!newptr && size)) { mozalloc_handle_oom(size); return moz_xrealloc(ptr, size); } return newptr; }
void CacheFileChunk::EnsureBufSize(uint32_t aBufSize) { mFile->AssertOwnsLock(); // EnsureBufSize() is called only when we want to write some data to the chunk // and we never write data anymore once some error occurs. MOZ_ASSERT(mState != ERROR); if (mBufSize >= aBufSize) return; bool copy = false; if (!mBuf && mState == WRITING) { // We need to duplicate the data that is being written on the background // thread, so make sure that all the data fits into the new buffer. copy = true; if (mRWBufSize > aBufSize) aBufSize = mRWBufSize; } // find smallest power of 2 greater than or equal to aBufSize aBufSize--; aBufSize |= aBufSize >> 1; aBufSize |= aBufSize >> 2; aBufSize |= aBufSize >> 4; aBufSize |= aBufSize >> 8; aBufSize |= aBufSize >> 16; aBufSize++; const uint32_t minBufSize = kMinBufSize; const uint32_t maxBufSize = kChunkSize; aBufSize = clamped(aBufSize, minBufSize, maxBufSize); mBuf = static_cast<char *>(moz_xrealloc(mBuf, aBufSize)); mBufSize = aBufSize; if (copy) memcpy(mBuf, mRWBuf, mRWBufSize); DoMemoryReport(MemorySize()); }
NS_IMETHODIMP nsNSSASN1PrintableItem::SetData(char *data, uint32_t len) { if (len > 0) { if (mLen < len) { unsigned char* newData = (unsigned char*)moz_xrealloc(mData, len); if (!newData) return NS_ERROR_OUT_OF_MEMORY; mData = newData; } memcpy(mData, data, len); } else if (len == 0) { if (mData) { free(mData); mData = nullptr; } } mLen = len; return NS_OK; }
nsresult CacheFileMetadata::OnDataRead(CacheFileHandle *aHandle, char *aBuf, nsresult aResult) { LOG(("CacheFileMetadata::OnDataRead() [this=%p, handle=%p, result=0x%08x]", this, aHandle, aResult)); MOZ_ASSERT(mListener); nsresult rv, retval; nsCOMPtr<CacheFileMetadataListener> listener; if (NS_FAILED(aResult)) { LOG(("CacheFileMetadata::OnDataRead() - CacheFileIOManager::Read() failed" ", creating empty metadata. [this=%p, rv=0x%08x]", this, aResult)); InitEmptyMetadata(); retval = NS_OK; mListener.swap(listener); listener->OnMetadataRead(retval); return NS_OK; } // check whether we have read all necessary data uint32_t realOffset = NetworkEndian::readUint32(mBuf + mBufSize - sizeof(uint32_t)); int64_t size = mHandle->FileSize(); MOZ_ASSERT(size != -1); if (realOffset >= size) { LOG(("CacheFileMetadata::OnDataRead() - Invalid realOffset, creating " "empty metadata. [this=%p, realOffset=%d, size=%lld]", this, realOffset, size)); InitEmptyMetadata(); retval = NS_OK; mListener.swap(listener); listener->OnMetadataRead(retval); return NS_OK; } uint32_t usedOffset = size - mBufSize; if (realOffset < usedOffset) { uint32_t missing = usedOffset - realOffset; // we need to read more data mBuf = static_cast<char *>(moz_xrealloc(mBuf, mBufSize + missing)); memmove(mBuf + missing, mBuf, mBufSize); mBufSize += missing; DoMemoryReport(MemoryUsage()); LOG(("CacheFileMetadata::OnDataRead() - We need to read %d more bytes to " "have full metadata. [this=%p]", missing, this)); rv = CacheFileIOManager::Read(mHandle, realOffset, mBuf, missing, true, this); if (NS_FAILED(rv)) { LOG(("CacheFileMetadata::OnDataRead() - CacheFileIOManager::Read() " "failed synchronously, creating empty metadata. [this=%p, " "rv=0x%08x]", this, rv)); InitEmptyMetadata(); retval = NS_OK; mListener.swap(listener); listener->OnMetadataRead(retval); return NS_OK; } return NS_OK; } // We have all data according to offset information at the end of the entry. // Try to parse it. rv = ParseMetadata(realOffset, realOffset - usedOffset, true); if (NS_FAILED(rv)) { LOG(("CacheFileMetadata::OnDataRead() - Error parsing metadata, creating " "empty metadata. [this=%p]", this)); InitEmptyMetadata(); retval = NS_OK; } else { retval = NS_OK; } mListener.swap(listener); listener->OnMetadataRead(retval); return NS_OK; }
NS_Realloc(void* aPtr, size_t aSize) { return moz_xrealloc(aPtr, aSize); }
nsresult CacheFileMetadata::OnDataRead(CacheFileHandle *aHandle, char *aBuf, nsresult aResult) { LOG(("CacheFileMetadata::OnDataRead() [this=%p, handle=%p, result=0x%08x]", this, aHandle, aResult)); MOZ_ASSERT(mListener); nsresult rv; nsCOMPtr<CacheFileMetadataListener> listener; if (NS_FAILED(aResult)) { LOG(("CacheFileMetadata::OnDataRead() - CacheFileIOManager::Read() failed" ", creating empty metadata. [this=%p, rv=0x%08x]", this, aResult)); InitEmptyMetadata(); mListener.swap(listener); listener->OnMetadataRead(NS_OK); return NS_OK; } if (mFirstRead) { Telemetry::AccumulateTimeDelta( Telemetry::NETWORK_CACHE_METADATA_FIRST_READ_TIME_MS, mReadStart); Telemetry::Accumulate( Telemetry::NETWORK_CACHE_METADATA_FIRST_READ_SIZE, mBufSize); } else { Telemetry::AccumulateTimeDelta( Telemetry::NETWORK_CACHE_METADATA_SECOND_READ_TIME_MS, mReadStart); } // check whether we have read all necessary data uint32_t realOffset = NetworkEndian::readUint32(mBuf + mBufSize - sizeof(uint32_t)); int64_t size = mHandle->FileSize(); MOZ_ASSERT(size != -1); if (realOffset >= size) { LOG(("CacheFileMetadata::OnDataRead() - Invalid realOffset, creating " "empty metadata. [this=%p, realOffset=%u, size=%lld]", this, realOffset, size)); InitEmptyMetadata(); mListener.swap(listener); listener->OnMetadataRead(NS_OK); return NS_OK; } uint32_t maxHashCount = size / kChunkSize; uint32_t maxMetadataSize = CalcMetadataSize(kMaxElementsSize, maxHashCount); if (size - realOffset > maxMetadataSize) { LOG(("CacheFileMetadata::OnDataRead() - Invalid realOffset, metadata would " "be too big, creating empty metadata. [this=%p, realOffset=%u, " "maxMetadataSize=%u, size=%lld]", this, realOffset, maxMetadataSize, size)); InitEmptyMetadata(); mListener.swap(listener); listener->OnMetadataRead(NS_OK); return NS_OK; } uint32_t usedOffset = size - mBufSize; if (realOffset < usedOffset) { uint32_t missing = usedOffset - realOffset; // we need to read more data char *newBuf = static_cast<char *>(realloc(mBuf, mBufSize + missing)); if (!newBuf) { LOG(("CacheFileMetadata::OnDataRead() - Error allocating %d more bytes " "for the missing part of the metadata, creating empty metadata. " "[this=%p]", missing, this)); InitEmptyMetadata(); mListener.swap(listener); listener->OnMetadataRead(NS_OK); return NS_OK; } mBuf = newBuf; memmove(mBuf + missing, mBuf, mBufSize); mBufSize += missing; DoMemoryReport(MemoryUsage()); LOG(("CacheFileMetadata::OnDataRead() - We need to read %d more bytes to " "have full metadata. [this=%p]", missing, this)); mFirstRead = false; mReadStart = mozilla::TimeStamp::Now(); rv = CacheFileIOManager::Read(mHandle, realOffset, mBuf, missing, this); if (NS_FAILED(rv)) { LOG(("CacheFileMetadata::OnDataRead() - CacheFileIOManager::Read() " "failed synchronously, creating empty metadata. [this=%p, " "rv=0x%08x]", this, rv)); InitEmptyMetadata(); mListener.swap(listener); listener->OnMetadataRead(NS_OK); return NS_OK; } return NS_OK; } Telemetry::Accumulate(Telemetry::NETWORK_CACHE_METADATA_SIZE, size - realOffset); // We have all data according to offset information at the end of the entry. // Try to parse it. rv = ParseMetadata(realOffset, realOffset - usedOffset, true); if (NS_FAILED(rv)) { LOG(("CacheFileMetadata::OnDataRead() - Error parsing metadata, creating " "empty metadata. [this=%p]", this)); InitEmptyMetadata(); } else { // Shrink elements buffer. mBuf = static_cast<char *>(moz_xrealloc(mBuf, mElementsSize)); mBufSize = mElementsSize; // There is usually no or just one call to SetMetadataElement() when the // metadata is parsed from disk. Avoid allocating power of two sized buffer // which we do in case of newly created metadata. mAllocExactSize = true; } mListener.swap(listener); listener->OnMetadataRead(NS_OK); return NS_OK; }
nsresult CacheFileChunk::OnDataRead(CacheFileHandle *aHandle, char *aBuf, nsresult aResult) { LOG(("CacheFileChunk::OnDataRead() [this=%p, handle=%p, result=0x%08x]", this, aHandle, aResult)); nsCOMPtr<CacheFileChunkListener> listener; { CacheFileAutoLock lock(mFile); MOZ_ASSERT(mState == READING); MOZ_ASSERT(mListener); if (NS_SUCCEEDED(aResult)) { CacheHash::Hash16_t hash = CacheHash::Hash16(mRWBuf, mRWBufSize); if (hash != mReadHash) { LOG(("CacheFileChunk::OnDataRead() - Hash mismatch! Hash of the data is" " %hx, hash in metadata is %hx. [this=%p, idx=%d]", hash, mReadHash, this, mIndex)); aResult = NS_ERROR_FILE_CORRUPTED; } else { if (!mBuf) { // Just swap the buffers if we don't have mBuf yet MOZ_ASSERT(mDataSize == mRWBufSize); mBuf = mRWBuf; mBufSize = mRWBufSize; mRWBuf = nullptr; mRWBufSize = 0; } else { LOG(("CacheFileChunk::OnDataRead() - Merging buffers. [this=%p]", this)); // Merge data with write buffer if (mRWBufSize < mBufSize) { mRWBuf = static_cast<char *>(moz_xrealloc(mRWBuf, mBufSize)); mRWBufSize = mBufSize; } mValidityMap.Log(); for (uint32_t i = 0 ; i < mValidityMap.Length() ; i++) { memcpy(mRWBuf + mValidityMap[i].Offset(), mBuf + mValidityMap[i].Offset(), mValidityMap[i].Len()); } mValidityMap.Clear(); free(mBuf); mBuf = mRWBuf; mBufSize = mRWBufSize; mRWBuf = nullptr; mRWBufSize = 0; DoMemoryReport(MemorySize()); } } } if (NS_FAILED(aResult)) { aResult = mIndex ? NS_ERROR_FILE_CORRUPTED : NS_ERROR_FILE_NOT_FOUND; SetError(aResult); mDataSize = 0; } else { mState = READY; } mListener.swap(listener); } listener->OnChunkRead(aResult, this); return NS_OK; }
NS_INTERFACE_MAP_END_THREADSAFE NS_IMETHODIMP nsCacheEntryDescriptor:: nsDecompressInputStreamWrapper::Read(char * buf, uint32_t count, uint32_t *countRead) { mozilla::MutexAutoLock lock(mLock); int zerr = Z_OK; nsresult rv = NS_OK; if (!mStreamInitialized) { rv = InitZstream(); if (NS_FAILED(rv)) { return rv; } } mZstream.next_out = (Bytef*)buf; mZstream.avail_out = count; if (mReadBufferLen < count) { // Allocate a buffer for reading from the input stream. This will // determine the max number of compressed bytes read from the // input stream at one time. Making the buffer size proportional // to the request size is not necessary, but helps minimize the // number of read requests to the input stream. uint32_t newBufLen = std::max(count, (uint32_t)kMinDecompressReadBufLen); unsigned char* newBuf; newBuf = (unsigned char*)moz_xrealloc(mReadBuffer, newBufLen); if (newBuf) { mReadBuffer = newBuf; mReadBufferLen = newBufLen; } if (!mReadBuffer) { mReadBufferLen = 0; return NS_ERROR_OUT_OF_MEMORY; } } // read and inflate data until the output buffer is full, or // there is no more data to read while (NS_SUCCEEDED(rv) && zerr == Z_OK && mZstream.avail_out > 0 && count > 0) { if (mZstream.avail_in == 0) { rv = nsInputStreamWrapper::Read_Locked((char*)mReadBuffer, mReadBufferLen, &mZstream.avail_in); if (NS_FAILED(rv) || !mZstream.avail_in) { break; } mZstream.next_in = mReadBuffer; } zerr = inflate(&mZstream, Z_NO_FLUSH); if (zerr == Z_STREAM_END) { // The compressed data may have been stored in multiple // chunks/streams. To allow for this case, re-initialize // the inflate stream and continue decompressing from // the next byte. Bytef * saveNextIn = mZstream.next_in; unsigned int saveAvailIn = mZstream.avail_in; Bytef * saveNextOut = mZstream.next_out; unsigned int saveAvailOut = mZstream.avail_out; inflateReset(&mZstream); mZstream.next_in = saveNextIn; mZstream.avail_in = saveAvailIn; mZstream.next_out = saveNextOut; mZstream.avail_out = saveAvailOut; zerr = Z_OK; } else if (zerr != Z_OK) { rv = NS_ERROR_INVALID_CONTENT_ENCODING; } } if (NS_SUCCEEDED(rv)) { *countRead = count - mZstream.avail_out; } return rv; }
NS_Realloc(void* ptr, size_t size) { return moz_xrealloc(ptr, size); }
void* sk_realloc_throw(void* addr, size_t size) { return moz_xrealloc(addr, size); }