Example #1
0
void CompressionCorruptionTest::runSimpleTest(const DataHolder& dh) {
  constexpr uint64_t uncompressedLength = 42;
  auto original = IOBuf::wrapBuffer(dh.data(uncompressedLength));
  auto compressed = codec_->compress(original.get());

  if (!codec_->needsUncompressedLength()) {
    auto uncompressed = codec_->uncompress(compressed.get());
    EXPECT_EQ(uncompressedLength, uncompressed->computeChainDataLength());
    EXPECT_EQ(dh.hash(uncompressedLength), hashIOBuf(uncompressed.get()));
  }
  {
    auto uncompressed = codec_->uncompress(compressed.get(),
                                           uncompressedLength);
    EXPECT_EQ(uncompressedLength, uncompressed->computeChainDataLength());
    EXPECT_EQ(dh.hash(uncompressedLength), hashIOBuf(uncompressed.get()));
  }

  EXPECT_THROW(codec_->uncompress(compressed.get(), uncompressedLength + 1),
               std::runtime_error);

  // Corrupt the first character
  ++(compressed->writableData()[0]);

  if (!codec_->needsUncompressedLength()) {
    EXPECT_THROW(codec_->uncompress(compressed.get()),
                 std::runtime_error);
  }

  EXPECT_THROW(codec_->uncompress(compressed.get(), uncompressedLength),
               std::runtime_error);
}
Example #2
0
fbstring IOBuf::moveToFbString() {
  // malloc-allocated buffers are just fine, everything else needs
  // to be turned into one.
  if (!sharedInfo() ||         // user owned, not ours to give up
      sharedInfo()->freeFn ||  // not malloc()-ed
      headroom() != 0 ||       // malloc()-ed block doesn't start at beginning
      tailroom() == 0 ||       // no room for NUL terminator
      isShared() ||            // shared
      isChained()) {           // chained
    // We might as well get rid of all head and tailroom if we're going
    // to reallocate; we need 1 byte for NUL terminator.
    coalesceAndReallocate(0, computeChainDataLength(), this, 1);
  }

  // Ensure NUL terminated
  *writableTail() = 0;
  fbstring str(reinterpret_cast<char*>(writableData()),
               length(),  capacity(),
               AcquireMallocatedString());

  if (flags() & kFlagFreeSharedInfo) {
    delete sharedInfo();
  }

  // Reset to a state where we can be deleted cleanly
  flagsAndSharedInfo_ = 0;
  buf_ = nullptr;
  clear();
  return str;
}
Example #3
0
IOBuf IOBuf::cloneCoalescedAsValue() const {
  if (!isChained()) {
    return cloneOneAsValue();
  }
  // Coalesce into newBuf
  const uint64_t newLength = computeChainDataLength();
  const uint64_t newHeadroom = headroom();
  const uint64_t newTailroom = prev()->tailroom();
  const uint64_t newCapacity = newLength + newHeadroom + newTailroom;
  IOBuf newBuf{CREATE, newCapacity};
  newBuf.advance(newHeadroom);

  auto current = this;
  do {
    if (current->length() > 0) {
      DCHECK_NOTNULL(current->data());
      DCHECK_LE(current->length(), newBuf.tailroom());
      memcpy(newBuf.writableTail(), current->data(), current->length());
      newBuf.append(current->length());
    }
    current = current->next();
  } while (current != this);

  DCHECK_EQ(newLength, newBuf.length());
  DCHECK_EQ(newHeadroom, newBuf.headroom());
  DCHECK_LE(newTailroom, newBuf.tailroom());

  return newBuf;
}
Example #4
0
void CompressionVarintTest::runSimpleTest(const DataHolder& dh) {
  auto original = IOBuf::wrapBuffer(dh.data(uncompressedLength_));
  auto compressed = codec_->compress(original.get());
  auto breakPoint =
      1UL +
      Random::rand64(std::max(9UL, oneBasedMsbPos(uncompressedLength_)) / 9UL);
  auto tinyBuf = IOBuf::copyBuffer(compressed->data(),
                                   std::min(compressed->length(), breakPoint));
  compressed->trimStart(breakPoint);
  tinyBuf->prependChain(std::move(compressed));
  compressed = std::move(tinyBuf);

  auto uncompressed = codec_->uncompress(compressed.get());

  EXPECT_EQ(uncompressedLength_, uncompressed->computeChainDataLength());
  EXPECT_EQ(dh.hash(uncompressedLength_), hashIOBuf(uncompressed.get()));
}
Example #5
0
unique_ptr<IOBuf> HPACKCodec::encode(vector<Header>& headers,
                                     bool& eviction) noexcept {
  // convert to HPACK API format
  vector<HPACKHeader> converted;
  converted.reserve(headers.size());
  uint32_t uncompressed = 0;
  for (const auto& h : headers) {
    // HPACKHeader automatically lowercases
    converted.emplace_back(*h.name, *h.value);
    auto& header = converted.back();
    uncompressed += header.name.size() + header.value.size() + 2;
  }
  auto buf = encoder_.encode(converted, encodeHeadroom_, &eviction);
  encodedSize_.compressed = 0;
  if (buf) {
    encodedSize_.compressed = buf->computeChainDataLength();
  }
  encodedSize_.uncompressed = uncompressed;
  if (stats_) {
    stats_->recordEncode(Type::HPACK, encodedSize_);
  }
  return buf;
}
Example #6
0
unique_ptr<IOBuf> HPACKCodec::encode(vector<Header>& headers) noexcept {
  vector<HPACKHeader> converted;
  // convert to HPACK API format
  uint32_t uncompressed = 0;
  for (const auto& h : headers) {
    HPACKHeader header(*h.name, *h.value);
    // This is ugly but since we're not changing the size
    // of the string I'm assuming this is OK
    char* mutableName = const_cast<char*>(header.name.data());
    folly::toLowerAscii(mutableName, header.name.size());
    converted.push_back(header);
    uncompressed += header.name.size() + header.value.size() + 2;
  }
  auto buf = encoder_->encode(converted, encodeHeadroom_);
  encodedSize_.compressed = 0;
  if (buf) {
    encodedSize_.compressed = buf->computeChainDataLength();
  }
  encodedSize_.uncompressed = uncompressed;
  if (stats_) {
    stats_->recordEncode(Type::HPACK, encodedSize_);
  }
  return std::move(buf);
}