Add third_party/base/memory/aligned_memory.h.
Make AlignedAlloc() available for use in an upcoming CL to fix some
memory alignment issues.
Borrow Chromium's base/aligned_memory.h at crrev.com/773784, but without
crrev.com/756778, which drags in some unneeded bits that introduce more
Chromium dependencies. The other modifications are:
- Wrap in pdfium namespace.
- Update headers and header guards.
- Change logging/checks to work with PDFium's version of base/logging.h.
Bug: chromium:1086796
Change-Id: I1cfe69b2f3ea4621fd7d02ede3aa24d7a8431954
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/70472
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/third_party/BUILD.gn b/third_party/BUILD.gn
index ae8881d..18ff15c 100644
--- a/third_party/BUILD.gn
+++ b/third_party/BUILD.gn
@@ -588,6 +588,8 @@
"base/debug/alias.h",
"base/immediate_crash.h",
"base/logging.h",
+ "base/memory/aligned_memory.cc",
+ "base/memory/aligned_memory.h",
"base/no_destructor.h",
"base/numerics/checked_math.h",
"base/numerics/checked_math_impl.h",
diff --git a/third_party/base/memory/aligned_memory.cc b/third_party/base/memory/aligned_memory.cc
new file mode 100644
index 0000000..b4cd54f
--- /dev/null
+++ b/third_party/base/memory/aligned_memory.cc
@@ -0,0 +1,48 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/base/memory/aligned_memory.h"
+
+#include "build/build_config.h"
+#include "third_party/base/logging.h"
+
+#if defined(OS_ANDROID)
+#include <malloc.h>
+#endif
+
+namespace pdfium {
+namespace base {
+
+void* AlignedAlloc(size_t size, size_t alignment) {
+ DCHECK(size > 0U);
+ DCHECK_EQ(alignment & (alignment - 1), 0U);
+ DCHECK_EQ(alignment % sizeof(void*), 0U);
+ void* ptr = nullptr;
+#if defined(COMPILER_MSVC)
+ ptr = _aligned_malloc(size, alignment);
+// Android technically supports posix_memalign(), but does not expose it in
+// the current version of the library headers used by Chrome. Luckily,
+// memalign() on Android returns pointers which can safely be used with
+// free(), so we can use it instead. Issue filed to document this:
+// http://code.google.com/p/android/issues/detail?id=35391
+#elif defined(OS_ANDROID)
+ ptr = memalign(alignment, size);
+#else
+ if (int ret = posix_memalign(&ptr, alignment, size)) {
+ ptr = nullptr;
+ }
+#endif
+ // Since aligned allocations may fail for non-memory related reasons, force a
+ // crash if we encounter a failed allocation; maintaining consistent behavior
+ // with a normal allocation failure in Chrome.
+ if (!ptr) {
+ CHECK(false);
+ }
+ // Sanity check alignment just to be safe.
+ DCHECK_EQ(reinterpret_cast<uintptr_t>(ptr) & (alignment - 1), 0U);
+ return ptr;
+}
+
+} // namespace base
+} // namespace pdfium
diff --git a/third_party/base/memory/aligned_memory.h b/third_party/base/memory/aligned_memory.h
new file mode 100644
index 0000000..59510e7
--- /dev/null
+++ b/third_party/base/memory/aligned_memory.h
@@ -0,0 +1,62 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BASE_MEMORY_ALIGNED_MEMORY_H_
+#define THIRD_PARTY_BASE_MEMORY_ALIGNED_MEMORY_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <type_traits>
+
+#include "build/build_config.h"
+#include "third_party/base/base_export.h"
+#include "third_party/base/compiler_specific.h"
+
+#if defined(COMPILER_MSVC)
+#include <malloc.h>
+#else
+#include <stdlib.h>
+#endif
+
+// A runtime sized aligned allocation can be created:
+//
+// float* my_array = static_cast<float*>(AlignedAlloc(size, alignment));
+//
+// // ... later, to release the memory:
+// AlignedFree(my_array);
+//
+// Or using unique_ptr:
+//
+// std::unique_ptr<float, AlignedFreeDeleter> my_array(
+// static_cast<float*>(AlignedAlloc(size, alignment)));
+
+namespace pdfium {
+namespace base {
+
+// This can be replaced with std::aligned_alloc when we have C++17.
+// Caveat: std::aligned_alloc requires the size parameter be an integral
+// multiple of alignment.
+BASE_EXPORT void* AlignedAlloc(size_t size, size_t alignment);
+
+inline void AlignedFree(void* ptr) {
+#if defined(COMPILER_MSVC)
+ _aligned_free(ptr);
+#else
+ free(ptr);
+#endif
+}
+
+// Deleter for use with unique_ptr. E.g., use as
+// std::unique_ptr<Foo, base::AlignedFreeDeleter> foo;
+struct AlignedFreeDeleter {
+ inline void operator()(void* ptr) const {
+ AlignedFree(ptr);
+ }
+};
+
+} // namespace base
+} // namespace pdfium
+
+#endif // THIRD_PARTY_BASE_MEMORY_ALIGNED_MEMORY_H_