Commit d5c951e8 authored by Sergei Glazunov's avatar Sergei Glazunov Committed by Chromium LUCI CQ

Make zero-sized allocations work with MiraclePtr

If the MiraclePtr PA extras are enabled, Alloc() returns a pointer
past the end of a slot for zero-sized allocations, which leads to
problems when a function needs to determine the slot from a given
pointer.

Adjust the requested allocation size to avoid that.

Bug: 1162769
Change-Id: I7c398a99a257f443ef704b87ac188acef0bcc5a1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2613974
Auto-Submit: Sergei Glazunov <glazunov@google.com>
Reviewed-by: default avatarBartek Nowierski <bartekn@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Commit-Queue: Kentaro Hara <haraken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#841381}
parent cbce40b5
......@@ -1102,7 +1102,18 @@ ALWAYS_INLINE void* PartitionRoot<thread_safe>::AllocFlagsNoHooks(
// a. Call to the thread cache, if it succeeds, go to step 3.
// b. Otherwise, call the "raw" allocator <-- Locking
// 3. Handle cookies/ref-count, zero allocation if required
size_t raw_size = AdjustSizeForExtrasAdd(requested_size);
size_t raw_size = requested_size;
#if ENABLE_REF_COUNT_FOR_BACKUP_REF_PTR
// Without the size adjustment below, |Alloc()| returns a pointer past the end
// of a slot (most of the time a pointer to the beginning of the next slot)
// for zero-sized allocations when |PartitionRefCount| is used. The returned
// value may lead to incorrect results when passed to a function that performs
// bitwise operations on pointers, e.g., |PartitionAllocGetSlotOffset()|.
if (UNLIKELY(raw_size == 0))
raw_size = 1;
#endif // ENABLE_REF_COUNT_FOR_BACKUP_REF_PTR
raw_size = AdjustSizeForExtrasAdd(raw_size);
PA_CHECK(raw_size >= requested_size); // check for overflows
uint16_t bucket_index = SizeToBucketIndex(raw_size);
......
......@@ -754,6 +754,26 @@ TEST(BackupRefPtrImpl, Basic) {
#endif // DCHECK_IS_ON()
}
TEST(BackupRefPtrImpl, ZeroSized) {
// This test works only if GigaCage is enabled. Bail out otherwise.
if (!features::IsPartitionAllocGigaCageEnabled())
return;
// TODO(bartekn): Avoid using PartitionAlloc API directly. Switch to
// new/delete once PartitionAlloc Everywhere is fully enabled.
PartitionAllocGlobalInit(HandleOOM);
PartitionAllocator<ThreadSafe> allocator;
allocator.init({});
std::vector<CheckedPtr<void>> ptrs;
// Use a reasonable number of elements to fill up the slot span.
for (int i = 0; i < 128 * 1024; ++i) {
// Constructing a CheckedPtr instance from a zero-sized allocation should
// not result in a crash.
ptrs.emplace_back(allocator.root()->Alloc(0, ""));
}
}
#endif // BUILDFLAG(USE_PARTITION_ALLOC) && ENABLE_BACKUP_REF_PTR_IMPL &&
// !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
} // namespace internal
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment