| 113 | } |
| 114 | |
| 115 | Status ParseMessage(const Slice& buf, |
| 116 | MessageLite* parsed_header, |
| 117 | Slice* parsed_main_message) { |
| 118 | |
| 119 | // First grab the total length |
| 120 | if (PREDICT_FALSE(buf.size() < kMsgLengthPrefixLength)) { |
| 121 | return Status::Corruption("Invalid packet: not enough bytes for length header", |
| 122 | KUDU_REDACT(buf.ToDebugString())); |
| 123 | } |
| 124 | |
| 125 | uint32_t total_len = NetworkByteOrder::Load32(buf.data()); |
| 126 | DCHECK_EQ(total_len, buf.size() - kMsgLengthPrefixLength) |
| 127 | << "Got mis-sized buffer: " << KUDU_REDACT(buf.ToDebugString()); |
| 128 | |
| 129 | if (total_len > std::numeric_limits<int32_t>::max()) { |
| 130 | return Status::Corruption(Substitute("Invalid packet: message had a length of $0, " |
| 131 | "but we only support messages up to $1 bytes\n", |
| 132 | total_len, std::numeric_limits<int32_t>::max())); |
| 133 | } |
| 134 | |
| 135 | CodedInputStream in(buf.data(), buf.size()); |
| 136 | // Protobuf enforces a 64MB total bytes limit on CodedInputStream by default. |
| 137 | // Override this default with the actual size of the buffer to allow messages |
| 138 | // larger than 64MB. |
| 139 | in.SetTotalBytesLimit(buf.size()); |
| 140 | in.Skip(kMsgLengthPrefixLength); |
| 141 | |
| 142 | uint32_t header_len; |
| 143 | if (PREDICT_FALSE(!in.ReadVarint32(&header_len))) { |
| 144 | return Status::Corruption("Invalid packet: missing header delimiter", |
| 145 | KUDU_REDACT(buf.ToDebugString())); |
| 146 | } |
| 147 | |
| 148 | CodedInputStream::Limit l; |
| 149 | l = in.PushLimit(header_len); |
| 150 | if (PREDICT_FALSE(!parsed_header->ParseFromCodedStream(&in))) { |
| 151 | return Status::Corruption("Invalid packet: header too short", |
| 152 | KUDU_REDACT(buf.ToDebugString())); |
| 153 | } |
| 154 | in.PopLimit(l); |
| 155 | |
| 156 | uint32_t main_msg_len; |
| 157 | if (PREDICT_FALSE(!in.ReadVarint32(&main_msg_len))) { |
| 158 | return Status::Corruption("Invalid packet: missing main msg length", |
| 159 | KUDU_REDACT(buf.ToDebugString())); |
| 160 | } |
| 161 | |
| 162 | if (PREDICT_FALSE(!in.Skip(main_msg_len))) { |
| 163 | return Status::Corruption( |
| 164 | StringPrintf("Invalid packet: data too short, expected %d byte main_msg", main_msg_len), |
| 165 | KUDU_REDACT(buf.ToDebugString())); |
| 166 | } |
| 167 | |
| 168 | if (PREDICT_FALSE(in.BytesUntilLimit() > 0)) { |
| 169 | return Status::Corruption( |
| 170 | StringPrintf("Invalid packet: %d extra bytes at end of packet", in.BytesUntilLimit()), |
| 171 | KUDU_REDACT(buf.ToDebugString())); |
| 172 | } |
no test coverage detected