| 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 |