OLD | NEW |
1 // Copyright 2014 Google Inc. All Rights Reserved. | 1 // Copyright 2014 Google Inc. All Rights Reserved. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
6 // | 6 // |
7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 block.RawTrailerPadding()); | 60 block.RawTrailerPadding()); |
61 EXPECT_EQ(block.RawTrailerPadding() + block.trailer_padding_size, | 61 EXPECT_EQ(block.RawTrailerPadding() + block.trailer_padding_size, |
62 block.RawTrailer()); | 62 block.RawTrailer()); |
63 EXPECT_EQ(block.RawHeader() + block.block_size, | 63 EXPECT_EQ(block.RawHeader() + block.block_size, |
64 block.RawTrailer() + sizeof(BlockTrailer)); | 64 block.RawTrailer() + sizeof(BlockTrailer)); |
65 | 65 |
66 // Validate the actual contents of the various parts of the block. | 66 // Validate the actual contents of the various parts of the block. |
67 | 67 |
68 // Check the header. | 68 // Check the header. |
69 EXPECT_EQ(kBlockHeaderMagic, block.header->magic); | 69 EXPECT_EQ(kBlockHeaderMagic, block.header->magic); |
70 EXPECT_FALSE(block.header->is_nested); | |
71 EXPECT_LT(0u, block.header->body_size); | 70 EXPECT_LT(0u, block.header->body_size); |
72 EXPECT_EQ(block.header->body_size, block.body_size); | 71 EXPECT_EQ(block.header->body_size, block.body_size); |
73 if (just_initialized) { | 72 if (just_initialized) { |
74 EXPECT_EQ(0u, block.header->checksum); | 73 EXPECT_EQ(0u, block.header->checksum); |
75 EXPECT_EQ(NULL, block.header->alloc_stack); | 74 EXPECT_EQ(NULL, block.header->alloc_stack); |
76 EXPECT_EQ(NULL, block.header->free_stack); | 75 EXPECT_EQ(NULL, block.header->free_stack); |
77 EXPECT_EQ(ALLOCATED_BLOCK, block.header->state); | 76 EXPECT_EQ(ALLOCATED_BLOCK, block.header->state); |
78 } | 77 } |
79 | 78 |
80 // By default we assume the blocks to not be nested. | |
81 EXPECT_FALSE(block.header->is_nested); | |
82 EXPECT_EQ(static_cast<bool>(block.header->is_nested), block.is_nested); | |
83 | |
84 // Check the header padding. | 79 // Check the header padding. |
85 if (block.header->has_header_padding) { | 80 if (block.header->has_header_padding) { |
86 EXPECT_LE(kShadowRatio, block.header_padding_size); | 81 EXPECT_LE(kShadowRatio, block.header_padding_size); |
87 EXPECT_EQ(block.header_padding_size, | 82 EXPECT_EQ(block.header_padding_size, |
88 *reinterpret_cast<const uint32_t*>(block.header_padding)); | 83 *reinterpret_cast<const uint32_t*>(block.header_padding)); |
89 EXPECT_EQ(block.header_padding_size, | 84 EXPECT_EQ(block.header_padding_size, |
90 *reinterpret_cast<const uint32_t*>(block.RawHeaderPadding() + | 85 *reinterpret_cast<const uint32_t*>(block.RawHeaderPadding() + |
91 block.header_padding_size - | 86 block.header_padding_size - |
92 sizeof(uint32_t))); | 87 sizeof(uint32_t))); |
93 for (uint32_t i = sizeof(uint32_t); | 88 for (uint32_t i = sizeof(uint32_t); |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
200 // Plan a layout with an invalid size, this should fail. | 195 // Plan a layout with an invalid size, this should fail. |
201 EXPECT_FALSE(BlockPlanLayout(8, 8, 0xffffffff, 0, 0, &layout)); | 196 EXPECT_FALSE(BlockPlanLayout(8, 8, 0xffffffff, 0, 0, &layout)); |
202 } | 197 } |
203 | 198 |
204 TEST_F(BlockTest, EndToEnd) { | 199 TEST_F(BlockTest, EndToEnd) { |
205 BlockLayout layout = {}; | 200 BlockLayout layout = {}; |
206 BlockInfo block_info = {}; | 201 BlockInfo block_info = {}; |
207 | 202 |
208 EXPECT_TRUE(BlockPlanLayout(8, 8, 4, 0, 0, &layout)); | 203 EXPECT_TRUE(BlockPlanLayout(8, 8, 4, 0, 0, &layout)); |
209 std::vector<uint8_t> block_data(layout.block_size); | 204 std::vector<uint8_t> block_data(layout.block_size); |
210 BlockInitialize(layout, block_data.data(), false, &block_info); | 205 BlockInitialize(layout, block_data.data(), &block_info); |
211 EXPECT_NO_FATAL_FAILURE(IsValidInitializedBlock(block_info)); | 206 EXPECT_NO_FATAL_FAILURE(IsValidInitializedBlock(block_info)); |
212 block_data.clear(); | 207 block_data.clear(); |
213 | 208 |
214 EXPECT_TRUE(BlockPlanLayout(8, 8, 61, 0, 0, &layout)); | 209 EXPECT_TRUE(BlockPlanLayout(8, 8, 61, 0, 0, &layout)); |
215 block_data.resize(layout.block_size); | 210 block_data.resize(layout.block_size); |
216 BlockInitialize(layout, block_data.data(), false, &block_info); | 211 BlockInitialize(layout, block_data.data(), &block_info); |
217 EXPECT_NO_FATAL_FAILURE(IsValidInitializedBlock(block_info)); | 212 EXPECT_NO_FATAL_FAILURE(IsValidInitializedBlock(block_info)); |
218 block_data.clear(); | 213 block_data.clear(); |
219 | 214 |
220 EXPECT_TRUE(BlockPlanLayout(8, 8, 60, 32, 32, &layout)); | 215 EXPECT_TRUE(BlockPlanLayout(8, 8, 60, 32, 32, &layout)); |
221 block_data.resize(layout.block_size); | 216 block_data.resize(layout.block_size); |
222 BlockInitialize(layout, block_data.data(), false, &block_info); | 217 BlockInitialize(layout, block_data.data(), &block_info); |
223 EXPECT_NO_FATAL_FAILURE(IsValidInitializedBlock(block_info)); | 218 EXPECT_NO_FATAL_FAILURE(IsValidInitializedBlock(block_info)); |
224 block_data.clear(); | 219 block_data.clear(); |
225 | 220 |
226 // Do an allocation that uses entire pages. | 221 // Do an allocation that uses entire pages. |
227 EXPECT_TRUE(BlockPlanLayout(4096, 8, 100, 4096, 4096, &layout)); | 222 EXPECT_TRUE(BlockPlanLayout(4096, 8, 100, 4096, 4096, &layout)); |
228 void* data = ::VirtualAlloc(NULL, layout.block_size, MEM_COMMIT, | 223 void* data = ::VirtualAlloc(NULL, layout.block_size, MEM_COMMIT, |
229 PAGE_READWRITE); | 224 PAGE_READWRITE); |
230 ::memset(data, 0, layout.block_size); | 225 ::memset(data, 0, layout.block_size); |
231 BlockInitialize(layout, data, false, &block_info); | 226 BlockInitialize(layout, data, &block_info); |
232 EXPECT_NO_FATAL_FAILURE(IsValidInitializedBlock(block_info)); | 227 EXPECT_NO_FATAL_FAILURE(IsValidInitializedBlock(block_info)); |
233 ASSERT_EQ(TRUE, ::VirtualFree(data, 0, MEM_RELEASE)); | 228 ASSERT_EQ(TRUE, ::VirtualFree(data, 0, MEM_RELEASE)); |
234 } | 229 } |
235 | 230 |
236 TEST_F(BlockTest, GetHeaderFromBody) { | 231 TEST_F(BlockTest, GetHeaderFromBody) { |
237 // Plan two layouts, one with header padding and another without. | 232 // Plan two layouts, one with header padding and another without. |
238 BlockLayout layout1 = {}; | 233 BlockLayout layout1 = {}; |
239 BlockLayout layout2 = {}; | 234 BlockLayout layout2 = {}; |
240 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 10, 0, 0, &layout1)); | 235 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 10, 0, 0, &layout1)); |
241 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 10, 32, 0, &layout2)); | 236 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 10, 32, 0, &layout2)); |
242 | 237 |
243 std::unique_ptr<uint8_t[]> data(new uint8_t[layout2.block_size]); | 238 std::unique_ptr<uint8_t[]> data(new uint8_t[layout2.block_size]); |
244 ::memset(data.get(), 0, layout2.block_size); | 239 ::memset(data.get(), 0, layout2.block_size); |
245 | 240 |
246 // First try navigating a block without header padding. | 241 // First try navigating a block without header padding. |
247 BlockInfo info = {}; | 242 BlockInfo info = {}; |
248 BlockInitialize(layout1, data.get(), false, &info); | 243 BlockInitialize(layout1, data.get(), &info); |
249 // This should succeed as expected. | 244 // This should succeed as expected. |
250 EXPECT_EQ(info.header, BlockGetHeaderFromBody(info.body)); | 245 EXPECT_EQ(info.header, BlockGetHeaderFromBody(info.body)); |
251 // This fails because of invalid alignment. | 246 // This fails because of invalid alignment. |
252 EXPECT_TRUE(BlockGetHeaderFromBody( | 247 EXPECT_TRUE(BlockGetHeaderFromBody( |
253 reinterpret_cast<BlockBody*>(info.RawBody() + 1)) == nullptr); | 248 reinterpret_cast<BlockBody*>(info.RawBody() + 1)) == nullptr); |
254 // This fails because the pointer is not at the beginning of the | 249 // This fails because the pointer is not at the beginning of the |
255 // body. | 250 // body. |
256 EXPECT_TRUE(BlockGetHeaderFromBody( | 251 EXPECT_TRUE(BlockGetHeaderFromBody( |
257 reinterpret_cast<BlockBody*>(info.RawBody() + kShadowRatio)) == nullptr); | 252 reinterpret_cast<BlockBody*>(info.RawBody() + kShadowRatio)) == nullptr); |
258 // This fails because of invalid header magic. | 253 // This fails because of invalid header magic. |
259 ++info.header->magic; | 254 ++info.header->magic; |
260 EXPECT_TRUE(BlockGetHeaderFromBody(info.body) == nullptr); | 255 EXPECT_TRUE(BlockGetHeaderFromBody(info.body) == nullptr); |
261 // This fails because the header indicates there's padding. | 256 // This fails because the header indicates there's padding. |
262 --info.header->magic; | 257 --info.header->magic; |
263 info.header->has_header_padding = 1; | 258 info.header->has_header_padding = 1; |
264 EXPECT_TRUE(BlockGetHeaderFromBody(info.body) == nullptr); | 259 EXPECT_TRUE(BlockGetHeaderFromBody(info.body) == nullptr); |
265 | 260 |
266 // Now navigate a block with header padding. | 261 // Now navigate a block with header padding. |
267 BlockInitialize(layout2, data.get(), false, &info); | 262 BlockInitialize(layout2, data.get(), &info); |
268 // This should succeed as expected. | 263 // This should succeed as expected. |
269 EXPECT_EQ(info.header, BlockGetHeaderFromBody(info.body)); | 264 EXPECT_EQ(info.header, BlockGetHeaderFromBody(info.body)); |
270 // This fails because of invalid alignment. | 265 // This fails because of invalid alignment. |
271 EXPECT_TRUE(BlockGetHeaderFromBody( | 266 EXPECT_TRUE(BlockGetHeaderFromBody( |
272 reinterpret_cast<BlockBody*>(info.RawBody() + 1)) == nullptr); | 267 reinterpret_cast<BlockBody*>(info.RawBody() + 1)) == nullptr); |
273 // This fails because the pointer is not at the beginning of the | 268 // This fails because the pointer is not at the beginning of the |
274 // body. | 269 // body. |
275 EXPECT_TRUE(BlockGetHeaderFromBody( | 270 EXPECT_TRUE(BlockGetHeaderFromBody( |
276 reinterpret_cast<BlockBody*>(info.RawBody() + kShadowRatio)) == nullptr); | 271 reinterpret_cast<BlockBody*>(info.RawBody() + kShadowRatio)) == nullptr); |
277 // This fails because of invalid header magic. | 272 // This fails because of invalid header magic. |
(...skipping 15 matching lines...) Expand all Loading... |
293 EXPECT_TRUE(BlockGetHeaderFromBody(info.body) == nullptr); | 288 EXPECT_TRUE(BlockGetHeaderFromBody(info.body) == nullptr); |
294 } | 289 } |
295 | 290 |
296 TEST_F(BlockTest, GetHeaderFromBodyProtectedMemory) { | 291 TEST_F(BlockTest, GetHeaderFromBodyProtectedMemory) { |
297 BlockLayout layout = {}; | 292 BlockLayout layout = {}; |
298 EXPECT_TRUE(BlockPlanLayout(4096, 4096, 4096, 4096, 4096, &layout)); | 293 EXPECT_TRUE(BlockPlanLayout(4096, 4096, 4096, 4096, 4096, &layout)); |
299 void* alloc = ::VirtualAlloc(NULL, layout.block_size, MEM_COMMIT, | 294 void* alloc = ::VirtualAlloc(NULL, layout.block_size, MEM_COMMIT, |
300 PAGE_READWRITE); | 295 PAGE_READWRITE); |
301 ASSERT_TRUE(alloc != NULL); | 296 ASSERT_TRUE(alloc != NULL); |
302 BlockInfo block_info = {}; | 297 BlockInfo block_info = {}; |
303 BlockInitialize(layout, alloc, false, &block_info); | 298 BlockInitialize(layout, alloc, &block_info); |
304 | 299 |
305 BlockProtectRedzones(block_info, &shadow_); | 300 BlockProtectRedzones(block_info, &shadow_); |
306 EXPECT_CALL(*this, OnExceptionCallback(_)); | 301 EXPECT_CALL(*this, OnExceptionCallback(_)); |
307 EXPECT_TRUE(BlockGetHeaderFromBody(block_info.body) == NULL); | 302 EXPECT_TRUE(BlockGetHeaderFromBody(block_info.body) == NULL); |
308 testing::Mock::VerifyAndClearExpectations(this); | 303 testing::Mock::VerifyAndClearExpectations(this); |
309 BlockProtectNone(block_info, &shadow_); | 304 BlockProtectNone(block_info, &shadow_); |
310 | 305 |
311 ASSERT_EQ(TRUE, ::VirtualFree(alloc, 0, MEM_RELEASE)); | 306 ASSERT_EQ(TRUE, ::VirtualFree(alloc, 0, MEM_RELEASE)); |
312 } | 307 } |
313 | 308 |
314 TEST_F(BlockTest, ConvertBlockInfo) { | 309 TEST_F(BlockTest, ConvertBlockInfo) { |
315 BlockLayout layout = {}; | 310 BlockLayout layout = {}; |
316 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 10, 0, 0, &layout)); | 311 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 10, 0, 0, &layout)); |
317 | 312 |
318 std::unique_ptr<uint8_t[]> data(new uint8_t[layout.block_size]); | 313 std::unique_ptr<uint8_t[]> data(new uint8_t[layout.block_size]); |
319 ::memset(data.get(), 0, layout.block_size); | 314 ::memset(data.get(), 0, layout.block_size); |
320 | 315 |
321 BlockInfo expanded = {}; | 316 BlockInfo expanded = {}; |
322 BlockInitialize(layout, data.get(), false, &expanded); | 317 BlockInitialize(layout, data.get(), &expanded); |
323 | 318 |
324 CompactBlockInfo compact = {}; | 319 CompactBlockInfo compact = {}; |
325 ConvertBlockInfo(expanded, &compact); | 320 ConvertBlockInfo(expanded, &compact); |
326 EXPECT_EQ(layout.block_size, compact.block_size); | 321 EXPECT_EQ(layout.block_size, compact.block_size); |
327 EXPECT_EQ(layout.header_size + layout.header_padding_size, | 322 EXPECT_EQ(layout.header_size + layout.header_padding_size, |
328 compact.header_size); | 323 compact.header_size); |
329 EXPECT_EQ(layout.trailer_size + layout.trailer_padding_size, | 324 EXPECT_EQ(layout.trailer_size + layout.trailer_padding_size, |
330 compact.trailer_size); | 325 compact.trailer_size); |
331 EXPECT_FALSE(compact.is_nested); | 326 EXPECT_FALSE(compact.is_nested); |
332 | 327 |
333 BlockInfo expanded2 = {}; | 328 BlockInfo expanded2 = {}; |
334 ConvertBlockInfo(compact, &expanded2); | 329 ConvertBlockInfo(compact, &expanded2); |
335 EXPECT_EQ(0, ::memcmp(&expanded, &expanded2, sizeof(expanded))); | 330 EXPECT_EQ(0, ::memcmp(&expanded, &expanded2, sizeof(expanded))); |
336 } | 331 } |
337 | 332 |
338 TEST_F(BlockTest, BlockInfoFromMemory) { | 333 TEST_F(BlockTest, BlockInfoFromMemory) { |
339 // Plan two layouts, one with header padding and another without. | 334 // Plan two layouts, one with header padding and another without. |
340 BlockLayout layout1 = {}; | 335 BlockLayout layout1 = {}; |
341 BlockLayout layout2 = {}; | 336 BlockLayout layout2 = {}; |
342 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 10, 0, 0, &layout1)); | 337 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 10, 0, 0, &layout1)); |
343 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 10, 32, 0, &layout2)); | 338 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 10, 32, 0, &layout2)); |
344 | 339 |
345 std::unique_ptr<uint8_t[]> data(new uint8_t[layout2.block_size]); | 340 std::unique_ptr<uint8_t[]> data(new uint8_t[layout2.block_size]); |
346 ::memset(data.get(), 0, layout2.block_size); | 341 ::memset(data.get(), 0, layout2.block_size); |
347 | 342 |
348 // First recover a block without header padding. | 343 // First recover a block without header padding. |
349 BlockInfo info = {}; | 344 BlockInfo info = {}; |
350 BlockInitialize(layout1, data.get(), false, &info); | 345 BlockInitialize(layout1, data.get(), &info); |
351 BlockInfo info_recovered = {}; | 346 BlockInfo info_recovered = {}; |
352 EXPECT_TRUE(BlockInfoFromMemory(info.header, &info_recovered)); | 347 EXPECT_TRUE(BlockInfoFromMemory(info.header, &info_recovered)); |
353 EXPECT_EQ(info, info_recovered); | 348 EXPECT_EQ(info, info_recovered); |
354 // Failed because its not aligned. | 349 // Failed because its not aligned. |
355 EXPECT_FALSE(BlockInfoFromMemory( | 350 EXPECT_FALSE(BlockInfoFromMemory( |
356 reinterpret_cast<BlockHeader*>(info.RawHeader() + 1), | 351 reinterpret_cast<BlockHeader*>(info.RawHeader() + 1), |
357 &info_recovered)); | 352 &info_recovered)); |
358 // Failed because the magic is invalid. | 353 // Failed because the magic is invalid. |
359 ++info.header->magic; | 354 ++info.header->magic; |
360 EXPECT_FALSE(BlockInfoFromMemory(info.header, &info_recovered)); | 355 EXPECT_FALSE(BlockInfoFromMemory(info.header, &info_recovered)); |
361 --info.header->magic; | 356 --info.header->magic; |
362 // This fails because the header indicates there's padding yet there is | 357 // This fails because the header indicates there's padding yet there is |
363 // none. | 358 // none. |
364 info.header->has_header_padding = 1; | 359 info.header->has_header_padding = 1; |
365 EXPECT_FALSE(BlockInfoFromMemory(info.header, &info_recovered)); | 360 EXPECT_FALSE(BlockInfoFromMemory(info.header, &info_recovered)); |
366 | 361 |
367 // Now recover a block with header padding. | 362 // Now recover a block with header padding. |
368 BlockInitialize(layout2, data.get(), false, &info); | 363 BlockInitialize(layout2, data.get(), &info); |
369 EXPECT_TRUE(BlockInfoFromMemory(info.header, &info_recovered)); | 364 EXPECT_TRUE(BlockInfoFromMemory(info.header, &info_recovered)); |
370 EXPECT_EQ(info, info_recovered); | 365 EXPECT_EQ(info, info_recovered); |
371 // Failed because the magic is invalid. | 366 // Failed because the magic is invalid. |
372 ++info.header->magic; | 367 ++info.header->magic; |
373 EXPECT_FALSE(BlockInfoFromMemory(info.header, &info_recovered)); | 368 EXPECT_FALSE(BlockInfoFromMemory(info.header, &info_recovered)); |
374 --info.header->magic; | 369 --info.header->magic; |
375 // Failed because the header padding lengths don't match. | 370 // Failed because the header padding lengths don't match. |
376 uint32_t* head = reinterpret_cast<uint32_t*>(info.header_padding); | 371 uint32_t* head = reinterpret_cast<uint32_t*>(info.header_padding); |
377 uint32_t* tail = head + (info.header_padding_size / sizeof(uint32_t)) - 1; | 372 uint32_t* tail = head + (info.header_padding_size / sizeof(uint32_t)) - 1; |
378 ++(*tail); | 373 ++(*tail); |
379 EXPECT_FALSE(BlockInfoFromMemory(info.header, &info_recovered)); | 374 EXPECT_FALSE(BlockInfoFromMemory(info.header, &info_recovered)); |
380 --(*tail); | 375 --(*tail); |
381 | 376 |
382 // Finally ensure that we can recover information about blocks of various | 377 // Finally ensure that we can recover information about blocks of various |
383 // sizes. | 378 // sizes. |
384 const size_t kAllocSize = 3 * GetPageSize(); | 379 const size_t kAllocSize = 3 * GetPageSize(); |
385 void* alloc = ::VirtualAlloc(NULL, kAllocSize, MEM_COMMIT, PAGE_READWRITE); | 380 void* alloc = ::VirtualAlloc(NULL, kAllocSize, MEM_COMMIT, PAGE_READWRITE); |
386 for (uint32_t block_size = 0; block_size < kShadowRatio * 2; ++block_size) { | 381 for (uint32_t block_size = 0; block_size < kShadowRatio * 2; ++block_size) { |
387 BlockLayout layout = {}; | 382 BlockLayout layout = {}; |
388 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, block_size, 0, 0, | 383 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, block_size, 0, 0, |
389 &layout)); | 384 &layout)); |
390 ASSERT_LE(layout.block_size, kAllocSize); | 385 ASSERT_LE(layout.block_size, kAllocSize); |
391 BlockInitialize(layout, alloc, false, &info); | 386 BlockInitialize(layout, alloc, &info); |
392 EXPECT_TRUE(BlockInfoFromMemory(info.header, &info_recovered)); | 387 EXPECT_TRUE(BlockInfoFromMemory(info.header, &info_recovered)); |
393 EXPECT_EQ(info.body_size, info_recovered.body_size); | 388 EXPECT_EQ(info.body_size, info_recovered.body_size); |
394 EXPECT_EQ(info, info_recovered); | 389 EXPECT_EQ(info, info_recovered) << block_size; |
395 | 390 |
396 EXPECT_TRUE(BlockPlanLayout(4096, 4096, block_size, 4096, 4096, | 391 EXPECT_TRUE(BlockPlanLayout(4096, 4096, block_size, 4096, 4096, |
397 &layout)); | 392 &layout)); |
398 ASSERT_LE(layout.block_size, kAllocSize); | 393 ASSERT_LE(layout.block_size, kAllocSize); |
399 BlockInitialize(layout, alloc, false, &info); | 394 BlockInitialize(layout, alloc, &info); |
400 EXPECT_TRUE(BlockInfoFromMemory(info.header, &info_recovered)); | 395 EXPECT_TRUE(BlockInfoFromMemory(info.header, &info_recovered)); |
401 EXPECT_EQ(info.body_size, info_recovered.body_size); | 396 EXPECT_EQ(info.body_size, info_recovered.body_size); |
402 EXPECT_EQ(info, info_recovered); | 397 EXPECT_EQ(info, info_recovered); |
403 } | 398 } |
404 ::VirtualFree(alloc, 0, MEM_RELEASE); | 399 ::VirtualFree(alloc, 0, MEM_RELEASE); |
405 } | 400 } |
406 | 401 |
407 TEST_F(BlockTest, BlockInfoFromMemoryInvalidPadding) { | 402 TEST_F(BlockTest, BlockInfoFromMemoryInvalidPadding) { |
408 BlockLayout layout = {}; | 403 BlockLayout layout = {}; |
409 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 10, | 404 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 10, |
410 4 * sizeof(BlockHeader), 0, &layout)); | 405 4 * sizeof(BlockHeader), 0, &layout)); |
411 | 406 |
412 std::unique_ptr<uint8_t[]> data(new uint8_t[layout.block_size]); | 407 std::unique_ptr<uint8_t[]> data(new uint8_t[layout.block_size]); |
413 ::memset(data.get(), 0, layout.block_size); | 408 ::memset(data.get(), 0, layout.block_size); |
414 | 409 |
415 BlockInfo info = {}; | 410 BlockInfo info = {}; |
416 BlockInitialize(layout, data.get(), false, &info); | 411 BlockInitialize(layout, data.get(), &info); |
417 EXPECT_EQ(1, info.header->has_header_padding); | 412 EXPECT_EQ(1, info.header->has_header_padding); |
418 BlockInfo info_recovered = {}; | 413 BlockInfo info_recovered = {}; |
419 EXPECT_TRUE(BlockInfoFromMemory(info.header, &info_recovered)); | 414 EXPECT_TRUE(BlockInfoFromMemory(info.header, &info_recovered)); |
420 EXPECT_EQ(info, info_recovered); | 415 EXPECT_EQ(info, info_recovered); |
421 | 416 |
422 // Invalidates the padding size and make sure that we can't retrieve the block | 417 // Invalidates the padding size and make sure that we can't retrieve the block |
423 // information. | 418 // information. |
424 size_t* padding_size = reinterpret_cast<size_t*>(info.header + 1); | 419 size_t* padding_size = reinterpret_cast<size_t*>(info.header + 1); |
425 EXPECT_GE(*padding_size, 2 * sizeof(uint32_t)); | 420 EXPECT_GE(*padding_size, 2 * sizeof(uint32_t)); |
426 for (*padding_size = 0; *padding_size < 2 * sizeof(uint32_t); | 421 for (*padding_size = 0; *padding_size < 2 * sizeof(uint32_t); |
427 ++(*padding_size)) { | 422 ++(*padding_size)) { |
428 EXPECT_FALSE(BlockInfoFromMemory(info.header, &info_recovered)); | 423 EXPECT_FALSE(BlockInfoFromMemory(info.header, &info_recovered)); |
429 } | 424 } |
430 } | 425 } |
431 | 426 |
432 TEST_F(BlockTest, BlockInfoFromMemoryProtectedMemory) { | 427 TEST_F(BlockTest, BlockInfoFromMemoryProtectedMemory) { |
433 BlockLayout layout = {}; | 428 BlockLayout layout = {}; |
434 EXPECT_TRUE(BlockPlanLayout(4096, 4096, 4096, 4096, 4096, &layout)); | 429 EXPECT_TRUE(BlockPlanLayout(4096, 4096, 4096, 4096, 4096, &layout)); |
435 void* alloc = ::VirtualAlloc(NULL, layout.block_size, MEM_COMMIT, | 430 void* alloc = ::VirtualAlloc(NULL, layout.block_size, MEM_COMMIT, |
436 PAGE_READWRITE); | 431 PAGE_READWRITE); |
437 ASSERT_TRUE(alloc != NULL); | 432 ASSERT_TRUE(alloc != NULL); |
438 BlockInfo block_info = {}; | 433 BlockInfo block_info = {}; |
439 BlockInitialize(layout, alloc, false, &block_info); | 434 BlockInitialize(layout, alloc, &block_info); |
440 | 435 |
441 BlockProtectRedzones(block_info, &shadow_); | 436 BlockProtectRedzones(block_info, &shadow_); |
442 BlockInfo recovered_info = {}; | 437 BlockInfo recovered_info = {}; |
443 EXPECT_CALL(*this, OnExceptionCallback(_)); | 438 EXPECT_CALL(*this, OnExceptionCallback(_)); |
444 EXPECT_FALSE(BlockInfoFromMemory(block_info.header, &recovered_info)); | 439 EXPECT_FALSE(BlockInfoFromMemory(block_info.header, &recovered_info)); |
445 testing::Mock::VerifyAndClearExpectations(this); | 440 testing::Mock::VerifyAndClearExpectations(this); |
446 BlockProtectNone(block_info, &shadow_); | 441 BlockProtectNone(block_info, &shadow_); |
447 | 442 |
448 ASSERT_EQ(TRUE, ::VirtualFree(alloc, 0, MEM_RELEASE)); | 443 ASSERT_EQ(TRUE, ::VirtualFree(alloc, 0, MEM_RELEASE)); |
449 } | 444 } |
450 | 445 |
451 TEST_F(BlockTest, BlockInfoFromMemoryForNestedBlock) { | |
452 BlockLayout layout = {}; | |
453 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 10, 0, 0, &layout)); | |
454 | |
455 std::unique_ptr<uint8_t[]> data(new uint8_t[layout.block_size]); | |
456 BlockInfo block_info = {}; | |
457 BlockInitialize(layout, data.get(), true, &block_info); | |
458 | |
459 BlockInfo recovered_info = {}; | |
460 EXPECT_TRUE(BlockInfoFromMemory(block_info.header, &recovered_info)); | |
461 | |
462 EXPECT_TRUE(recovered_info.is_nested); | |
463 EXPECT_TRUE(recovered_info.header->is_nested); | |
464 } | |
465 | |
466 TEST_F(BlockTest, ChecksumWorksForAllStates) { | 446 TEST_F(BlockTest, ChecksumWorksForAllStates) { |
467 BlockLayout layout = {}; | 447 BlockLayout layout = {}; |
468 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 10, 0, 0, &layout)); | 448 EXPECT_TRUE(BlockPlanLayout(kShadowRatio, kShadowRatio, 10, 0, 0, &layout)); |
469 std::unique_ptr<uint8_t[]> data(new uint8_t[layout.block_size]); | 449 std::unique_ptr<uint8_t[]> data(new uint8_t[layout.block_size]); |
470 ::memset(data.get(), 0, layout.block_size); | 450 ::memset(data.get(), 0, layout.block_size); |
471 BlockInfo info = {}; | 451 BlockInfo info = {}; |
472 BlockInitialize(layout, data.get(), false, &info); | 452 BlockInitialize(layout, data.get(), &info); |
473 while (true) { | 453 while (true) { |
474 BlockCalculateChecksum(info); | 454 BlockCalculateChecksum(info); |
475 ++info.header->state; | 455 ++info.header->state; |
476 if (info.header->state == 0) | 456 if (info.header->state == 0) |
477 break; | 457 break; |
478 } | 458 } |
479 } | 459 } |
480 | 460 |
481 namespace { | 461 namespace { |
482 | 462 |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
691 chunk_size *= 2) { | 671 chunk_size *= 2) { |
692 for (uint32_t align = kShadowRatio; align <= chunk_size; align *= 2) { | 672 for (uint32_t align = kShadowRatio; align <= chunk_size; align *= 2) { |
693 for (uint32_t redzone = 0; redzone <= chunk_size; redzone += chunk_size) { | 673 for (uint32_t redzone = 0; redzone <= chunk_size; redzone += chunk_size) { |
694 for (size_t i = 0; i < arraysize(kSizes); ++i) { | 674 for (size_t i = 0; i < arraysize(kSizes); ++i) { |
695 BlockLayout layout = {}; | 675 BlockLayout layout = {}; |
696 EXPECT_TRUE(BlockPlanLayout(chunk_size, align, kSizes[i], redzone, | 676 EXPECT_TRUE(BlockPlanLayout(chunk_size, align, kSizes[i], redzone, |
697 redzone, &layout)); | 677 redzone, &layout)); |
698 ASSERT_GT(kAllocSize, layout.block_size); | 678 ASSERT_GT(kAllocSize, layout.block_size); |
699 | 679 |
700 BlockInfo block_info = {}; | 680 BlockInfo block_info = {}; |
701 BlockInitialize(layout, alloc, false, &block_info); | 681 BlockInitialize(layout, alloc, &block_info); |
702 block_info.header->alloc_stack = valid_stack; | 682 block_info.header->alloc_stack = valid_stack; |
703 block_info.trailer->heap_id = valid_heap_id; | 683 block_info.trailer->heap_id = valid_heap_id; |
704 | 684 |
705 // Test that the checksum detects tampering as expected in each block | 685 // Test that the checksum detects tampering as expected in each block |
706 // state. | 686 // state. |
707 block_info.header->state = ALLOCATED_BLOCK; | 687 block_info.header->state = ALLOCATED_BLOCK; |
708 ASSERT_NO_FATAL_FAILURE(TestChecksumDetectsTampering(block_info)); | 688 ASSERT_NO_FATAL_FAILURE(TestChecksumDetectsTampering(block_info)); |
709 | 689 |
710 block_info.header->state = QUARANTINED_BLOCK; | 690 block_info.header->state = QUARANTINED_BLOCK; |
711 block_info.header->free_stack = valid_stack; | 691 block_info.header->free_stack = valid_stack; |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
823 BlockBitFlipsFixChecksum(QUARANTINED_BLOCK, block1.block_info, 0)); | 803 BlockBitFlipsFixChecksum(QUARANTINED_BLOCK, block1.block_info, 0)); |
824 EXPECT_TRUE( | 804 EXPECT_TRUE( |
825 BlockBitFlipsFixChecksum(QUARANTINED_BLOCK, block1.block_info, 3)); | 805 BlockBitFlipsFixChecksum(QUARANTINED_BLOCK, block1.block_info, 3)); |
826 flips = BlockBitFlipsRequired(QUARANTINED_BLOCK, block1.block_info, 3); | 806 flips = BlockBitFlipsRequired(QUARANTINED_BLOCK, block1.block_info, 3); |
827 EXPECT_LT(0u, flips); | 807 EXPECT_LT(0u, flips); |
828 EXPECT_GE(3u, flips); | 808 EXPECT_GE(3u, flips); |
829 } | 809 } |
830 | 810 |
831 } // namespace asan | 811 } // namespace asan |
832 } // namespace agent | 812 } // namespace agent |
OLD | NEW |