[base] Add base::UncheckedFree() to free() memory from UncheckedMalloc()

Chromium configures malloc() to crash rather than returning nullptr, as
some callers are not prepared to handle nullptr properly, and crashing is
preferable to introducing a security issue. In some cases though,
base::UncheckedMalloc() is used to explicitly ask for a nullptr return
value.

However, it is implicitly assumed that a pointer allocated this way can
be passed to free(). This is not the case on all platforms, in all
configurations. For instance, on macOS, there are (rare) cases where
base::UncheckedMalloc() is PartitionAlloc, while free() isn't
necessarily aware of PartitionAlloc. This leads to crashes, which can be
hard to diagnose since they are relatively rare.

To mitigate that, introduce base::UncheckedFree(). This is not enforced,
yet, as call site conversion is split into another CL.

Bug: 1274236, 1279371
Change-Id: Ib10d1cc17b8856dd5af03e0724c35b2423a43e28
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3329862
Reviewed-by: Wez <[email protected]>
Commit-Queue: Benoit Lize <[email protected]>
Cr-Commit-Position: refs/heads/main@{#951002}
diff --git a/base/process/memory.h b/base/process/memory.h
index 46ff72f8..5f82d4f 100644
--- a/base/process/memory.h
+++ b/base/process/memory.h
@@ -77,12 +77,20 @@
 // specifically ASan and other sanitizers.
 // Return value tells whether the allocation succeeded. If it fails |result| is
 // set to NULL, otherwise it holds the memory address.
-BASE_EXPORT WARN_UNUSED_RESULT bool UncheckedMalloc(size_t size,
-                                                    void** result);
+//
+// Note: You *must* use UncheckedFree() to free() the memory allocated, not
+// regular free(). This also means that this a pointer allocated below cannot be
+// passed to realloc().
+BASE_EXPORT WARN_UNUSED_RESULT bool UncheckedMalloc(size_t size, void** result);
 BASE_EXPORT WARN_UNUSED_RESULT bool UncheckedCalloc(size_t num_items,
                                                     size_t size,
                                                     void** result);
 
+// *Must* be used to free memory allocated with base::UncheckedMalloc() and
+// base::UncheckedCalloc().
+// TODO(crbug.com/1279371): Enforce it, when all callers are converted.
+BASE_EXPORT void UncheckedFree(void* ptr);
+
 }  // namespace base
 
 #endif  // BASE_PROCESS_MEMORY_H_