1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "perfetto/protozero/message.h"
18
19 #include <limits>
20 #include <memory>
21 #include <utility>
22 #include <vector>
23
24 #include "perfetto/base/logging.h"
25 #include "perfetto/protozero/message_handle.h"
26 #include "perfetto/protozero/root_message.h"
27 #include "src/base/test/utils.h"
28 #include "src/protozero/test/fake_scattered_buffer.h"
29 #include "test/gtest_and_gmock.h"
30
31 namespace protozero {
32
33 namespace {
34
35 constexpr size_t kChunkSize = 16;
36 constexpr uint8_t kTestBytes[] = {0, 0, 0, 0, 0x42, 1, 0x42, 0xff, 0x42, 0};
37 constexpr const char kStartWatermark[] = {'a', 'b', 'c', 'd',
38 '1', '2', '3', '\0'};
39 constexpr const char kEndWatermark[] = {'9', '8', '7', '6',
40 'z', 'w', 'y', '\0'};
41
42 class FakeRootMessage : public RootMessage<Message> {};
43 class FakeChildMessage : public Message {};
44
SimpleHash(const std::string & str)45 uint32_t SimpleHash(const std::string& str) {
46 uint32_t hash = 5381;
47 for (char c : str)
48 hash = 33 * hash + static_cast<uint32_t>(c);
49 return hash;
50 }
51
52 class MessageTest : public ::testing::Test {
53 public:
SetUp()54 void SetUp() override {
55 buffer_.reset(new FakeScatteredBuffer(kChunkSize));
56 stream_writer_.reset(new ScatteredStreamWriter(buffer_.get()));
57 readback_pos_ = 0;
58 }
59
TearDown()60 void TearDown() override {
61 // Check that none of the messages created by the text fixtures below did
62 // under/overflow their heap boundaries.
63 for (std::unique_ptr<uint8_t[]>& mem : messages_) {
64 EXPECT_STREQ(kStartWatermark, reinterpret_cast<char*>(mem.get()));
65 EXPECT_STREQ(kEndWatermark,
66 reinterpret_cast<char*>(mem.get() + sizeof(kStartWatermark) +
67 sizeof(FakeRootMessage)));
68 FakeRootMessage* msg = reinterpret_cast<FakeRootMessage*>(
69 mem.get() + sizeof(kStartWatermark));
70 msg->~FakeRootMessage();
71 mem.reset();
72 }
73 messages_.clear();
74 stream_writer_.reset();
75 buffer_.reset();
76 }
77
ResetMessage(FakeRootMessage * msg)78 void ResetMessage(FakeRootMessage* msg) { msg->Reset(stream_writer_.get()); }
79
NewMessage()80 FakeRootMessage* NewMessage() {
81 std::unique_ptr<uint8_t[]> mem(
82 new uint8_t[sizeof(kStartWatermark) + sizeof(FakeRootMessage) +
83 sizeof(kEndWatermark)]);
84 uint8_t* msg_start = mem.get() + sizeof(kStartWatermark);
85 memcpy(mem.get(), kStartWatermark, sizeof(kStartWatermark));
86 memset(msg_start, 0, sizeof(FakeRootMessage));
87 memcpy(msg_start + sizeof(FakeRootMessage), kEndWatermark,
88 sizeof(kEndWatermark));
89 messages_.push_back(std::move(mem));
90 FakeRootMessage* msg = new (msg_start) FakeRootMessage();
91 msg->Reset(stream_writer_.get());
92 return msg;
93 }
94
GetNumSerializedBytes()95 size_t GetNumSerializedBytes() {
96 if (buffer_->chunks().empty())
97 return 0;
98 return buffer_->chunks().size() * kChunkSize -
99 stream_writer_->bytes_available();
100 }
101
GetNextSerializedBytes(size_t num_bytes)102 std::string GetNextSerializedBytes(size_t num_bytes) {
103 size_t old_readback_pos = readback_pos_;
104 readback_pos_ += num_bytes;
105 return buffer_->GetBytesAsString(old_readback_pos, num_bytes);
106 }
107
BuildNestedMessages(Message * msg,uint32_t max_depth,uint32_t depth=0)108 static void BuildNestedMessages(Message* msg,
109 uint32_t max_depth,
110 uint32_t depth = 0) {
111 for (uint32_t i = 1; i <= 128; ++i)
112 msg->AppendBytes(i, kTestBytes, sizeof(kTestBytes));
113
114 if (depth < max_depth) {
115 auto* nested_msg =
116 msg->BeginNestedMessage<FakeChildMessage>(1 + depth * 10);
117 BuildNestedMessages(nested_msg, max_depth, depth + 1);
118 }
119
120 for (uint32_t i = 129; i <= 256; ++i)
121 msg->AppendVarInt(i, 42);
122
123 if ((depth & 2) == 0)
124 msg->Finalize();
125 }
126
127 private:
128 std::unique_ptr<FakeScatteredBuffer> buffer_;
129 std::unique_ptr<ScatteredStreamWriter> stream_writer_;
130 std::vector<std::unique_ptr<uint8_t[]>> messages_;
131 size_t readback_pos_;
132 };
133
TEST_F(MessageTest,ZeroLengthArraysAndStrings)134 TEST_F(MessageTest, ZeroLengthArraysAndStrings) {
135 Message* msg = NewMessage();
136 msg->AppendBytes(1 /* field_id */, nullptr, 0);
137 msg->AppendString(2 /* field_id */, "");
138
139 EXPECT_EQ(4u, msg->Finalize());
140 EXPECT_EQ(4u, GetNumSerializedBytes());
141
142 // These lines match the serialization of the Append* calls above.
143 ASSERT_EQ("0A00", GetNextSerializedBytes(2));
144 ASSERT_EQ("1200", GetNextSerializedBytes(2));
145 }
146
TEST_F(MessageTest,BasicTypesNoNesting)147 TEST_F(MessageTest, BasicTypesNoNesting) {
148 Message* msg = NewMessage();
149 msg->AppendVarInt(1 /* field_id */, 0);
150 msg->AppendVarInt(2 /* field_id */, std::numeric_limits<uint32_t>::max());
151 msg->AppendVarInt(3 /* field_id */, 42);
152 msg->AppendVarInt(4 /* field_id */, std::numeric_limits<uint64_t>::max());
153 msg->AppendFixed(5 /* field_id */, 3.1415f /* float */);
154 msg->AppendFixed(6 /* field_id */, 3.14159265358979323846 /* double */);
155 msg->AppendBytes(7 /* field_id */, kTestBytes, sizeof(kTestBytes));
156
157 // Field ids > 16 are expected to be varint encoded (preamble > 1 byte)
158 msg->AppendString(257 /* field_id */, "0123456789abcdefABCDEF");
159 msg->AppendSignedVarInt(3 /* field_id */, -21);
160
161 EXPECT_EQ(74u, msg->Finalize());
162 EXPECT_EQ(74u, GetNumSerializedBytes());
163
164 // These lines match the serialization of the Append* calls above.
165 ASSERT_EQ("0800", GetNextSerializedBytes(2));
166 ASSERT_EQ("10FFFFFFFF0F", GetNextSerializedBytes(6));
167 ASSERT_EQ("182A", GetNextSerializedBytes(2));
168 ASSERT_EQ("20FFFFFFFFFFFFFFFFFF01", GetNextSerializedBytes(11));
169 ASSERT_EQ("2D560E4940", GetNextSerializedBytes(5));
170 ASSERT_EQ("31182D4454FB210940", GetNextSerializedBytes(9));
171 ASSERT_EQ("3A0A00000000420142FF4200", GetNextSerializedBytes(12));
172 ASSERT_EQ("8A101630313233343536373839616263646566414243444546",
173 GetNextSerializedBytes(25));
174 ASSERT_EQ("1829", GetNextSerializedBytes(2));
175 }
176
TEST_F(MessageTest,NestedMessagesSimple)177 TEST_F(MessageTest, NestedMessagesSimple) {
178 Message* root_msg = NewMessage();
179 root_msg->AppendVarInt(1 /* field_id */, 1);
180
181 FakeChildMessage* nested_msg =
182 root_msg->BeginNestedMessage<FakeChildMessage>(128 /* field_id */);
183 ASSERT_EQ(0u, reinterpret_cast<uintptr_t>(nested_msg) % sizeof(void*));
184 nested_msg->AppendVarInt(2 /* field_id */, 2);
185
186 nested_msg =
187 root_msg->BeginNestedMessage<FakeChildMessage>(129 /* field_id */);
188 nested_msg->AppendVarInt(4 /* field_id */, 2);
189
190 root_msg->AppendVarInt(5 /* field_id */, 3);
191
192 // The expected size of the root message is supposed to be 20 bytes:
193 // 2 bytes for the varint field (id: 1) (1 for preamble and one for payload)
194 // 6 bytes for the preamble of the 1st nested message (2 for id, 4 for size)
195 // 2 bytes for the varint field (id: 2) of the 1st nested message
196 // 6 bytes for the premable of the 2nd nested message
197 // 2 bytes for the varint field (id: 4) of the 2nd nested message.
198 // 2 bytes for the last varint (id : 5) field of the root message.
199 // Test also that finalization is idempontent and Finalize() can be safely
200 // called more than once without side effects.
201 for (int i = 0; i < 3; ++i) {
202 EXPECT_EQ(20u, root_msg->Finalize());
203 EXPECT_EQ(20u, GetNumSerializedBytes());
204 }
205
206 ASSERT_EQ("0801", GetNextSerializedBytes(2));
207
208 ASSERT_EQ("820882808000", GetNextSerializedBytes(6));
209 ASSERT_EQ("1002", GetNextSerializedBytes(2));
210
211 ASSERT_EQ("8A0882808000", GetNextSerializedBytes(6));
212 ASSERT_EQ("2002", GetNextSerializedBytes(2));
213
214 ASSERT_EQ("2803", GetNextSerializedBytes(2));
215 }
216
217 // Tests using a AppendScatteredBytes to append raw bytes to
218 // a message using multiple individual buffers.
TEST_F(MessageTest,AppendScatteredBytes)219 TEST_F(MessageTest, AppendScatteredBytes) {
220 Message* root_msg = NewMessage();
221
222 uint8_t buffer[42];
223 memset(buffer, 0x42, sizeof(buffer));
224
225 ContiguousMemoryRange ranges[] = {{buffer, buffer + sizeof(buffer)},
226 {buffer, buffer + sizeof(buffer)}};
227 root_msg->AppendScatteredBytes(1 /* field_id */, ranges, 2);
228 EXPECT_EQ(86u, root_msg->Finalize());
229 EXPECT_EQ(86u, GetNumSerializedBytes());
230
231 // field_id
232 EXPECT_EQ("0A", GetNextSerializedBytes(1));
233 // field length
234 EXPECT_EQ("54", GetNextSerializedBytes(1));
235 // start of contents
236 EXPECT_EQ("42424242", GetNextSerializedBytes(4));
237 }
238
239 // Checks that the size field of root and nested messages is properly written
240 // on finalization.
TEST_F(MessageTest,BackfillSizeOnFinalization)241 TEST_F(MessageTest, BackfillSizeOnFinalization) {
242 Message* root_msg = NewMessage();
243 uint8_t root_msg_size[proto_utils::kMessageLengthFieldSize] = {};
244 root_msg->set_size_field(&root_msg_size[0]);
245 root_msg->AppendVarInt(1, 0x42);
246
247 FakeChildMessage* nested_msg_1 =
248 root_msg->BeginNestedMessage<FakeChildMessage>(2);
249 nested_msg_1->AppendVarInt(3, 0x43);
250
251 FakeChildMessage* nested_msg_2 =
252 nested_msg_1->BeginNestedMessage<FakeChildMessage>(4);
253 uint8_t buf200[200];
254 memset(buf200, 0x42, sizeof(buf200));
255 nested_msg_2->AppendBytes(5, buf200, sizeof(buf200));
256
257 root_msg->inc_size_already_written(6);
258
259 // The value returned by Finalize() should be == the full size of |root_msg|.
260 EXPECT_EQ(217u, root_msg->Finalize());
261 EXPECT_EQ(217u, GetNumSerializedBytes());
262
263 // However the size written in the size field should take into account the
264 // inc_size_already_written() call and be equal to 118 - 6 = 112, encoded
265 // in a rendundant varint encoding of kMessageLengthFieldSize bytes.
266 EXPECT_STREQ("\xD3\x81\x80\x00", reinterpret_cast<char*>(root_msg_size));
267
268 // Skip 2 bytes for the 0x42 varint + 1 byte for the |nested_msg_1| preamble.
269 GetNextSerializedBytes(3);
270
271 // Check that the size of |nested_msg_1| was backfilled. Its size is:
272 // 203 bytes for |nest_mesg_2| (see below) + 5 bytes for its preamble +
273 // 2 bytes for the 0x43 varint = 210 bytes.
274 EXPECT_EQ("D2818000", GetNextSerializedBytes(4));
275
276 // Skip 2 bytes for the 0x43 varint + 1 byte for the |nested_msg_2| preamble.
277 GetNextSerializedBytes(3);
278
279 // Check that the size of |nested_msg_2| was backfilled. Its size is:
280 // 200 bytes (for |buf200|) + 3 bytes for its preamble = 203 bytes.
281 EXPECT_EQ("CB818000", GetNextSerializedBytes(4));
282 }
283
TEST_F(MessageTest,StressTest)284 TEST_F(MessageTest, StressTest) {
285 std::vector<Message*> nested_msgs;
286
287 Message* root_msg = NewMessage();
288 BuildNestedMessages(root_msg, /*max_depth=*/10);
289 root_msg->Finalize();
290
291 // The main point of this test is to stress the code paths and test for
292 // unexpected crashes of the production code. The actual serialization is
293 // already covered in the other text fixtures. Keeping just a final smoke test
294 // here on the full buffer hash.
295 std::string full_buf = GetNextSerializedBytes(GetNumSerializedBytes());
296 size_t buf_hash = SimpleHash(full_buf);
297 EXPECT_EQ(0xf9e32b65, buf_hash);
298 }
299
TEST_F(MessageTest,DeeplyNested)300 TEST_F(MessageTest, DeeplyNested) {
301 std::vector<Message*> nested_msgs;
302
303 Message* root_msg = NewMessage();
304 BuildNestedMessages(root_msg, /*max_depth=*/1000);
305 root_msg->Finalize();
306
307 std::string full_buf = GetNextSerializedBytes(GetNumSerializedBytes());
308 size_t buf_hash = SimpleHash(full_buf);
309 EXPECT_EQ(0xc0fde419, buf_hash);
310 }
311
TEST_F(MessageTest,DestructInvalidMessageHandle)312 TEST_F(MessageTest, DestructInvalidMessageHandle) {
313 FakeRootMessage* msg = NewMessage();
314 EXPECT_DCHECK_DEATH({
315 MessageHandle<FakeRootMessage> handle(msg);
316 ResetMessage(msg);
317 });
318 }
319
TEST_F(MessageTest,MessageHandle)320 TEST_F(MessageTest, MessageHandle) {
321 FakeRootMessage* msg1 = NewMessage();
322 FakeRootMessage* msg2 = NewMessage();
323 FakeRootMessage* msg3 = NewMessage();
324 FakeRootMessage* ignored_msg = NewMessage();
325 uint8_t msg1_size[proto_utils::kMessageLengthFieldSize] = {};
326 uint8_t msg2_size[proto_utils::kMessageLengthFieldSize] = {};
327 uint8_t msg3_size[proto_utils::kMessageLengthFieldSize] = {};
328 msg1->set_size_field(&msg1_size[0]);
329 msg2->set_size_field(&msg2_size[0]);
330 msg3->set_size_field(&msg3_size[0]);
331
332 // Test that the handle going out of scope causes the finalization of the
333 // target message and triggers the optional callback.
334 {
335 MessageHandle<FakeRootMessage> handle1(msg1);
336 handle1->AppendBytes(1 /* field_id */, kTestBytes, 1 /* size */);
337 ASSERT_EQ(0u, msg1_size[0]);
338 }
339 ASSERT_EQ(0x83u, msg1_size[0]);
340
341 // Test that the handle can be late initialized.
342 MessageHandle<FakeRootMessage> handle2(ignored_msg);
343 handle2 = MessageHandle<FakeRootMessage>(msg2);
344 handle2->AppendBytes(1 /* field_id */, kTestBytes, 2 /* size */);
345 ASSERT_EQ(0u, msg2_size[0]); // |msg2| should not be finalized yet.
346
347 // Test that std::move works and does NOT cause finalization of the moved
348 // message.
349 MessageHandle<FakeRootMessage> handle_swp(ignored_msg);
350 handle_swp = std::move(handle2);
351 ASSERT_EQ(0u, msg2_size[0]); // msg2 should be NOT finalized yet.
352 handle_swp->AppendBytes(2 /* field_id */, kTestBytes, 3 /* size */);
353
354 MessageHandle<FakeRootMessage> handle3(msg3);
355 handle3->AppendBytes(1 /* field_id */, kTestBytes, 4 /* size */);
356 ASSERT_EQ(0u, msg3_size[0]); // msg2 should be NOT finalized yet.
357
358 // Both |handle3| and |handle_swp| point to a valid message (respectively,
359 // |msg3| and |msg2|). Now move |handle3| into |handle_swp|.
360 handle_swp = std::move(handle3);
361 ASSERT_EQ(0x89u, msg2_size[0]); // |msg2| should be finalized at this point.
362
363 // At this point writing into handle_swp should actually write into |msg3|.
364 ASSERT_EQ(msg3, &*handle_swp);
365 handle_swp->AppendBytes(2 /* field_id */, kTestBytes, 8 /* size */);
366 MessageHandle<FakeRootMessage> another_handle(ignored_msg);
367 handle_swp = std::move(another_handle);
368 ASSERT_EQ(0x90u, msg3_size[0]); // |msg3| should be finalized at this point.
369
370 #if PERFETTO_DCHECK_IS_ON()
371 // In developer builds w/ PERFETTO_DCHECK on a finalized message should
372 // invalidate the handle, in order to early catch bugs in the client code.
373 FakeRootMessage* msg4 = NewMessage();
374 MessageHandle<FakeRootMessage> handle4(msg4);
375 ASSERT_EQ(msg4, &*handle4);
376 msg4->Finalize();
377 ASSERT_EQ(nullptr, &*handle4);
378 #endif
379
380 // Test also the behavior of handle with non-root (nested) messages.
381
382 uint8_t* size_msg_2;
383 {
384 auto* nested_msg_1 = NewMessage()->BeginNestedMessage<FakeChildMessage>(3);
385 MessageHandle<FakeChildMessage> child_handle_1(nested_msg_1);
386 uint8_t* size_msg_1 = nested_msg_1->size_field();
387 memset(size_msg_1, 0, proto_utils::kMessageLengthFieldSize);
388 child_handle_1->AppendVarInt(1, 0x11);
389
390 auto* nested_msg_2 = NewMessage()->BeginNestedMessage<FakeChildMessage>(2);
391 size_msg_2 = nested_msg_2->size_field();
392 memset(size_msg_2, 0, proto_utils::kMessageLengthFieldSize);
393 MessageHandle<FakeChildMessage> child_handle_2(nested_msg_2);
394 child_handle_2->AppendVarInt(2, 0xFF);
395
396 // |nested_msg_1| should not be finalized yet.
397 ASSERT_EQ(0u, size_msg_1[0]);
398
399 // This move should cause |nested_msg_1| to be finalized, but not
400 // |nested_msg_2|, which will be finalized only after the current scope.
401 child_handle_1 = std::move(child_handle_2);
402 ASSERT_EQ(0x82u, size_msg_1[0]);
403 ASSERT_EQ(0u, size_msg_2[0]);
404 }
405 ASSERT_EQ(0x83u, size_msg_2[0]);
406 }
407
TEST_F(MessageTest,MoveMessageHandle)408 TEST_F(MessageTest, MoveMessageHandle) {
409 FakeRootMessage* msg = NewMessage();
410 uint8_t msg_size[proto_utils::kMessageLengthFieldSize] = {};
411 msg->set_size_field(&msg_size[0]);
412
413 // Test that the handle going out of scope causes the finalization of the
414 // target message.
415 {
416 MessageHandle<FakeRootMessage> handle1(msg);
417 MessageHandle<FakeRootMessage> handle2{};
418 handle1->AppendBytes(1 /* field_id */, kTestBytes, 1 /* size */);
419 handle2 = std::move(handle1);
420 ASSERT_EQ(0u, msg_size[0]);
421 }
422 ASSERT_EQ(0x83u, msg_size[0]);
423 }
424
425 } // namespace
426 } // namespace protozero
427