| Index: base/metrics/persistent_memory_allocator.cc
|
| diff --git a/base/metrics/persistent_memory_allocator.cc b/base/metrics/persistent_memory_allocator.cc
|
| index bc873fefa0aeebc1b631861d594e55bf4919cc69..ee668233cf96b176d8962460ecd50054b6d5fec0 100644
|
| --- a/base/metrics/persistent_memory_allocator.cc
|
| +++ b/base/metrics/persistent_memory_allocator.cc
|
| @@ -14,10 +14,8 @@
|
|
|
| namespace {
|
|
|
| -// Required range of memory segment sizes. It has to fit in an unsigned 32-bit
|
| -// number and should be a power of 2 in order to accomodate almost any page
|
| -// size.
|
| -const uint32_t kSegmentMinSize = 1 << 10; // 1 KiB
|
| +// Limit of memory segment size. It has to fit in an unsigned 32-bit number
|
| +// and should be a power of 2 in order to accomodate almost any page size.
|
| const uint32_t kSegmentMaxSize = 1 << 30; // 1 GiB
|
|
|
| // A constant (random) value placed in the shared metadata to identify
|
| @@ -239,7 +237,6 @@ bool PersistentMemoryAllocator::IsMemoryAcceptable(const void* base,
|
| bool readonly) {
|
| return ((base && reinterpret_cast<uintptr_t>(base) % kAllocAlignment == 0) &&
|
| (size >= sizeof(SharedMetadata) && size <= kSegmentMaxSize) &&
|
| - (size >= kSegmentMinSize || readonly) &&
|
| (size % kAllocAlignment == 0 || readonly) &&
|
| (page_size == 0 || size % page_size == 0 || readonly));
|
| }
|
| @@ -301,7 +298,6 @@ PersistentMemoryAllocator::PersistentMemoryAllocator(
|
| first_block->type_id != 0 ||
|
| first_block->next != 0) {
|
| // ...or something malicious has been playing with the metadata.
|
| - NOTREACHED();
|
| SetCorrupt();
|
| }
|
|
|
| @@ -339,12 +335,22 @@ PersistentMemoryAllocator::PersistentMemoryAllocator(
|
| }
|
| if (!readonly) {
|
| // The allocator is attaching to a previously initialized segment of
|
| - // memory. Make sure the embedded data matches what has been passed.
|
| - if (shared_meta()->size != mem_size_ ||
|
| - shared_meta()->page_size != mem_page_) {
|
| - NOTREACHED();
|
| + // memory. If the initialization parameters differ, make the best of it
|
| + // by reducing the local construction parameters to match those of
|
| + // the actual memory area. This ensures that the local object never
|
| + // tries to write outside of the original bounds.
|
| + // Because the fields are const to ensure that no code other than the
|
| + // constructor makes changes to them as well as to give optimization
|
| + // hints to the compiler, it's necessary to const-cast them for changes
|
| + // here.
|
| + if (shared_meta()->size < mem_size_)
|
| + *const_cast<uint32_t*>(&mem_size_) = shared_meta()->size;
|
| + if (shared_meta()->page_size < mem_page_)
|
| + *const_cast<uint32_t*>(&mem_page_) = shared_meta()->page_size;
|
| +
|
| + // Ensure that settings are still valid after the above adjustments.
|
| + if (!IsMemoryAcceptable(base, mem_size_, mem_page_, readonly))
|
| SetCorrupt();
|
| - }
|
| }
|
| }
|
| }
|
| @@ -744,7 +750,7 @@ SharedPersistentMemoryAllocator::~SharedPersistentMemoryAllocator() {}
|
| // static
|
| bool SharedPersistentMemoryAllocator::IsSharedMemoryAcceptable(
|
| const SharedMemory& memory) {
|
| - return IsMemoryAcceptable(memory.memory(), memory.mapped_size(), 0, true);
|
| + return IsMemoryAcceptable(memory.memory(), memory.mapped_size(), 0, false);
|
| }
|
|
|
|
|
| @@ -752,22 +758,25 @@ bool SharedPersistentMemoryAllocator::IsSharedMemoryAcceptable(
|
|
|
| FilePersistentMemoryAllocator::FilePersistentMemoryAllocator(
|
| std::unique_ptr<MemoryMappedFile> file,
|
| + size_t max_size,
|
| uint64_t id,
|
| - base::StringPiece name)
|
| + base::StringPiece name,
|
| + bool read_only)
|
| : PersistentMemoryAllocator(const_cast<uint8_t*>(file->data()),
|
| - file->length(),
|
| + max_size != 0 ? max_size : file->length(),
|
| 0,
|
| id,
|
| name,
|
| - true),
|
| + read_only),
|
| mapped_file_(std::move(file)) {}
|
|
|
| FilePersistentMemoryAllocator::~FilePersistentMemoryAllocator() {}
|
|
|
| // static
|
| bool FilePersistentMemoryAllocator::IsFileAcceptable(
|
| - const MemoryMappedFile& file) {
|
| - return IsMemoryAcceptable(file.data(), file.length(), 0, true);
|
| + const MemoryMappedFile& file,
|
| + bool read_only) {
|
| + return IsMemoryAcceptable(file.data(), file.length(), 0, read_only);
|
| }
|
|
|
| } // namespace base
|
|
|