uint32_t TBinaryProtocol::readStringBody(string& str, int32_t size) { uint32_t result = 0; // Catch error cases if (size < 0) { throw TProtocolException(TProtocolException::NEGATIVE_SIZE); } if (string_limit_ > 0 && size > string_limit_) { throw TProtocolException(TProtocolException::SIZE_LIMIT); } // Catch empty string case if (size == 0) { str = ""; return result; } // Use the heap here to prevent stack overflow for v. large strings if (size > string_buf_size_ || string_buf_ == NULL) { void* new_string_buf = std::realloc(string_buf_, (uint32_t)size); if (new_string_buf == NULL) { throw TProtocolException(TProtocolException::UNKNOWN, "Out of memory in TBinaryProtocol::readString"); } string_buf_ = (uint8_t*)new_string_buf; string_buf_size_ = size; } trans_->readAll(string_buf_, size); str = string((char*)string_buf_, size); return (uint32_t)size; }
uint32_t TBinaryProtocol::readMessageBegin(std::string& name, TMessageType& messageType, int32_t& seqid) { uint32_t result = 0; int32_t sz; result += readI32(sz); if (sz < 0) { // Check for correct version number int32_t version = sz & VERSION_MASK; if (version != VERSION_1) { throw TProtocolException(TProtocolException::BAD_VERSION, "Bad version identifier"); } messageType = (TMessageType)(sz & 0x000000ff); result += readString(name); result += readI32(seqid); } else { if (strict_read_) { throw TProtocolException(TProtocolException::BAD_VERSION, "No version identifier... old protocol client in strict mode?"); } else { // Handle pre-versioned input int8_t type; result += readStringBody(name, sz); result += readByte(type); messageType = (TMessageType)type; result += readI32(seqid); } } return result; }
uint32_t TDebugProtocol::writeIndented(const string& str) { if(str.length() > (std::numeric_limits<uint32_t>::max)()) throw TProtocolException(TProtocolException::SIZE_LIMIT); if(indent_str_.length() > (std::numeric_limits<uint32_t>::max)()) throw TProtocolException(TProtocolException::SIZE_LIMIT); uint64_t total_len = indent_str_.length() + str.length(); if(total_len > (std::numeric_limits<uint32_t>::max)()) throw TProtocolException(TProtocolException::SIZE_LIMIT); trans_->write((uint8_t*)indent_str_.data(), static_cast<uint32_t>(indent_str_.length())); trans_->write((uint8_t*)str.data(), static_cast<uint32_t>(str.length())); return static_cast<uint32_t>(indent_str_.length() + str.length()); }
uint32_t TBinaryProtocol::readSetBegin(TType& elemType, uint32_t& size) { int8_t e; uint32_t result = 0; int32_t sizei; result += readByte(e); elemType = (TType)e; result += readI32(sizei); if (sizei < 0) { throw TProtocolException(TProtocolException::NEGATIVE_SIZE); } else if (container_limit_ && sizei > container_limit_) { throw TProtocolException(TProtocolException::SIZE_LIMIT); } size = (uint32_t)sizei; return result; }
[[noreturn]] void JSONProtocolReaderCommon::throwUnrecognizableAsString( std::string const& s, std::exception const& e) { throw TProtocolException( TProtocolException::INVALID_DATA, s + " is not a valid JSON string: " + e.what()); }
void TEvhttpClientChannel::sendMessage(const VoidCallback& cob, apache::thrift::transport::TMemoryBuffer* message) { (void)cob; (void)message; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "Unexpected call to TEvhttpClientChannel::sendMessage"); }
[[noreturn]] void JSONProtocolReaderCommon::throwUnrecognizableAsIntegral( folly::StringPiece s, std::type_info const& type) { throw TProtocolException( TProtocolException::INVALID_DATA, folly::to<std::string>(s, " is not a valid ", type.name())); }
[[noreturn]] void JSONProtocolReaderCommon::throwInvalidHexChar( char const ch) { throw TProtocolException( TProtocolException::INVALID_DATA, folly::to<std::string>( "Expected hex val ([0-9a-f]); got \'", sp(ch), "\'.")); }
[[noreturn]] void throwExceededSizeLimit( int64_t const size, int64_t const sizeMax) { throw TProtocolException( TProtocolException::SIZE_LIMIT, folly::to<std::string>(size, " is too large (", sizeMax, ")")); }
std::pair<const uint8_t*, size_t> Decoder::ensure(size_t n) { auto p = cursor_.peek(); if (UNLIKELY(p.second < n)) { throw TProtocolException("underflow"); } return p; }
[[noreturn]] void JSONProtocolReaderCommon::throwUnexpectedChar( char const ch, char const expected) { auto const msg = fmt::format( "expected '{0}' (hex {0:#02x}), read '{1}' (hex {1:#02x})", expected, ch); throw TProtocolException(TProtocolException::INVALID_DATA, msg); }
uint32_t TBinaryProtocol::readMapBegin(TType& keyType, TType& valType, uint32_t& size) { int8_t k, v; uint32_t result = 0; int32_t sizei; result += readByte(k); keyType = (TType)k; result += readByte(v); valType = (TType)v; result += readI32(sizei); if (sizei < 0) { throw TProtocolException(TProtocolException::NEGATIVE_SIZE); } else if (container_limit_ && sizei > container_limit_) { throw TProtocolException(TProtocolException::SIZE_LIMIT); } size = (uint32_t)sizei; return result; }
uint32_t TDebugProtocol::writePlain(const string& str) { if(str.length() > (std::numeric_limits<uint32_t>::max)()) throw TProtocolException(TProtocolException::SIZE_LIMIT); trans_->write((uint8_t*)str.data(), static_cast<uint32_t>(str.length())); return static_cast<uint32_t>(str.length()); }
void TDebugProtocol::indentDown() { if (indent_str_.length() < (string::size_type)indent_inc) { throw TProtocolException(TProtocolException::INVALID_DATA); } indent_str_.erase(indent_str_.length() - indent_inc); }
[[noreturn]] void JSONProtocolReader::throwUnrecognizableAsBoolean( int8_t const byte) { throw TProtocolException( TProtocolException::INVALID_DATA, folly::to<std::string>(byte, " is not a valid bool")); }
[[noreturn]] void throwUnrecognizedType() { throw TProtocolException( TProtocolException::NOT_IMPLEMENTED, "Unrecognized type"); }
[[noreturn]] void JSONProtocolReaderCommon::throwBadVersion() { throw TProtocolException( TProtocolException::BAD_VERSION, "Message contained bad version."); }
[[noreturn]] void throwNegativeSize(int64_t const size) { throw TProtocolException( TProtocolException::NEGATIVE_SIZE, folly::to<std::string>(size, " < 0")); }
[[noreturn]] void JSONProtocolReaderCommon:: throwUnrecognizableAsFloatingPoint(std::string const& s) { throw TProtocolException( TProtocolException::INVALID_DATA, s + " is not a valid float/double"); }
[[noreturn]] void JSONProtocolReaderCommon::throwInvalidEscapeChar( char const ch) { throw TProtocolException( TProtocolException::INVALID_DATA, folly::to<std::string>("Expected control char, got '", sp(ch), "'.")); }
[[noreturn]] void JSONProtocolReaderCommon::throwInvalidFieldStart( char const ch) { throw TProtocolException( TProtocolException::INVALID_DATA, std::string(1, ch) + " is not a valid start to a JSON field"); }
[[noreturn]] void JSONProtocolReaderCommon::throwUnrecognizableAsAny( std::string const& s) { throw TProtocolException( TProtocolException::INVALID_DATA, s + " is not valid JSON"); }
void Decoder::read() { auto& s = top(); size_t totalVarIntCount = 0; size_t optionalFieldBits = 0; if (s.state == IN_STRUCT) { size_t nbits = s.dataType->optionalFields.size(); optionalFieldBits = nbits; size_t nbytes = byteCount(nbits); cursor_.gather(nbytes); auto optionalSet = ensure(nbytes).first; // Now we know which optionals are set // Assign by tag. size_t optionalIdx = 0; for (auto& p : s.dataType->fields) { auto tag = p.first; if (!p.second.isRequired && !testBit(optionalSet, optionalIdx++)) { continue; } TypeInfo tinfo(schema_, p.second.type); s.addType(tinfo, p.second, tag, 1); } // Structs encode the bitfield first, so we can use only one bitfield // for both optional fields and bools and strict enums readBoolsAndStrictEnums(nbits); } else { if (s.state == IN_MAP_VALUE) { s.addType(s.list.mapKeyType, StructField(), 0, s.list.remaining); } s.addType(s.list.valueType, StructField(), 0, s.list.remaining); ++totalVarIntCount; // element count } s.ints.values.reserve(s.ints.count); s.int64s.values.reserve(s.int64s.count); s.bytes.values.reserve(s.bytes.count); // Waste some memory. Oh well, the code is simpler :) if (s.bools.count + s.totalStrictEnumBits) { s.bools.values.reserve(byteCount(optionalFieldBits + s.bools.count + s.totalStrictEnumBits)); } s.strictEnums.values.reserve(s.strictEnums.count); s.vars.values.reserve(s.vars.count); s.internedStrings.values.reserve(s.internedStrings.count); // Read ints size_t varIntCount = s.ints.count; size_t varInt64Count = s.int64s.count; size_t varLengthCount = s.vars.count; size_t internCount = s.internedStrings.count; if (s.state == IN_STRUCT) { varIntCount -= (s.str.fixedInt16Tags.size() + s.str.fixedInt32Tags.size()); varInt64Count -= s.str.fixedInt64Tags.size(); } totalVarIntCount += varIntCount + 2 * varInt64Count + varLengthCount + internCount; if (totalVarIntCount) { size_t maxSize = folly::GroupVarint32::maxSize(totalVarIntCount); cursor_.gatherAtMost(maxSize); folly::StringPiece data = SP(cursor_.peek()); folly::GroupVarint32Decoder decoder(data, totalVarIntCount); if (s.state != IN_STRUCT) { uint32_t n; if (!decoder.next(&n)) { throw TProtocolException("too few ints on the wire"); } DCHECK_EQ(n, s.list.remaining); } for (size_t i = 0; i < varIntCount; i++) { uint32_t val; if (!decoder.next(&val)) { throw TProtocolException("too few ints on the wire: int"); } s.ints.values.push_back(val); } for (size_t i = 0; i < varInt64Count; i++) { uint32_t hi; uint32_t lo; if (!decoder.next(&hi) || !decoder.next(&lo)) { throw TProtocolException("too few ints on the wire: int64"); } uint64_t val = ((uint64_t)hi << 32) | lo; s.int64s.values.push_back(val); } for (size_t i = 0; i < varLengthCount; i++) { uint32_t val; if (!decoder.next(&val)) { throw TProtocolException("too few ints on the wire: var"); } s.vars.values.push_back(val); } for (size_t i = 0; i < internCount; i++) { uint32_t val; if (!decoder.next(&val)) { throw TProtocolException("too few ints on the wire: intern"); } auto sp = internTable_->get(val); s.internedStrings.values.push_back(sp); if (s.state == IN_STRUCT) { // fixed size s.str.internedStringTags[i].second.length = sp.size(); } } uint32_t tmp; CHECK(!decoder.next(&tmp)); // or else we have an internal error size_t bytesUsed = data.size() - decoder.rest().size(); cursor_.skip(bytesUsed); s.bytesRead += bytesUsed; } // Read bools and strict enums, already done for structs if (s.state != IN_STRUCT) { readBoolsAndStrictEnums(0); } // Read bytes if (s.bytes.count) { s.bytes.values.resize(s.bytes.count); cursor_.pull(&s.bytes.values.front(), s.bytes.count); s.bytesRead += s.bytes.count; } // Read fixed-size fields, currently only for structs if (s.state == IN_STRUCT) { if (!s.str.fixedInt16Tags.empty()) { for (auto tag : s.str.fixedInt16Tags) { s.ints.values.push_back(cursor_.readBE<uint16_t>()); s.str.intTags.emplace_back(tag); } s.bytesRead += s.str.fixedInt16Tags.size() * sizeof(uint16_t); } if (!s.str.fixedInt32Tags.empty()) { for (auto tag : s.str.fixedInt32Tags) { s.ints.values.push_back(cursor_.readBE<uint32_t>()); s.str.intTags.emplace_back(tag); } s.bytesRead += s.str.fixedInt32Tags.size() * sizeof(uint32_t); } if (!s.str.fixedInt64Tags.empty()) { for (auto tag : s.str.fixedInt64Tags) { s.int64s.values.push_back(cursor_.readBE<uint64_t>()); s.str.int64Tags.push_back(tag); } s.bytesRead += s.str.fixedInt64Tags.size() * sizeof(uint64_t); } } }