Esempio n. 1
0
// 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;
}
Esempio n. 2
0
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());
    }
}
Esempio n. 3
0
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;
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
void
CacheFileMetadata::EnsureBuffer(uint32_t aSize)
{
  if (mBufSize < aSize) {
    mBufSize = aSize;
    mBuf = static_cast<char *>(moz_xrealloc(mBuf, mBufSize));
  }

  DoMemoryReport(MemoryUsage());
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
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());
}
Esempio n. 10
0
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;  
}
Esempio n. 11
0
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;
}
Esempio n. 12
0
NS_Realloc(void* aPtr, size_t aSize)
{
  return moz_xrealloc(aPtr, aSize);
}
Esempio n. 13
0
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;
}
Esempio n. 14
0
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;
}
Esempio n. 16
0
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);
}