Reimplement third_party/libopenjpeg20/opj_malloc.h.

Reimplement opj_malloc() and related memory (de)allocation functions
used by OpenJPEG. Instead of being based on a bunch of if-defs based on
platforms and compilers, standarize on using PartitionAlloc for normal
allocations, and use third_party/base/memory/aligned_memory.h for all
aligned allocations.

This fixes a mismatch where the previous implementation assumed many
64-bit POSIX platforms allocate 16-byte aligned memory, when OpenJPEG
actually requires 32-byte alignment in some cases.

Bug: chromium:1086796
Change-Id: I45a3e56b32185285f0792325704c372e65ee200f
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/70473
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxcodec/BUILD.gn b/core/fxcodec/BUILD.gn
index 63d4059..f53f6e0 100644
--- a/core/fxcodec/BUILD.gn
+++ b/core/fxcodec/BUILD.gn
@@ -144,6 +144,7 @@
   ]
   deps = [
     ":fxcodec",
+    "../../third_party:libopenjpeg2",
     "../fpdfapi/parser",
   ]
   pdfium_root_dir = "../../"
diff --git a/third_party/BUILD.gn b/third_party/BUILD.gn
index 18ff15c..9d88d9c 100644
--- a/third_party/BUILD.gn
+++ b/third_party/BUILD.gn
@@ -402,6 +402,8 @@
     "libopenjpeg20/mqc.c",
     "libopenjpeg20/openjpeg.c",
     "libopenjpeg20/opj_clock.c",
+    "libopenjpeg20/opj_malloc.cc",
+    "libopenjpeg20/opj_malloc.h",
     "libopenjpeg20/pi.c",
     "libopenjpeg20/sparse_array.c",
     "libopenjpeg20/sparse_array.h",
diff --git a/third_party/libopenjpeg20/0034-opj_malloc.patch b/third_party/libopenjpeg20/0034-opj_malloc.patch
index b2bc99c..c0ab88e 100644
--- a/third_party/libopenjpeg20/0034-opj_malloc.patch
+++ b/third_party/libopenjpeg20/0034-opj_malloc.patch
@@ -1,170 +1,88 @@
+diff --git a/third_party/libopenjpeg20/opj_malloc.cc b/third_party/libopenjpeg20/opj_malloc.cc
+new file mode 100644
+--- /dev/null
++++ b/third_party/libopenjpeg20/opj_malloc.cc
+@@ -0,0 +1,42 @@
++// Copyright 2020 PDFium Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style license that can be
++// found in the LICENSE file.
++
++// Deliberately not including opj_malloc.h, which has poisoned malloc and
++// friends.
++
++#include "core/fxcrt/fx_memory.h"
++#include "third_party/base/memory/aligned_memory.h"
++
++extern "C" {
++
++void* opj_malloc(size_t size) {
++  return FXMEM_DefaultAlloc(size);
++}
++
++void* opj_calloc(size_t numOfElements, size_t sizeOfElements) {
++  return FXMEM_DefaultCalloc(numOfElements, sizeOfElements);
++}
++
++void* opj_aligned_malloc(size_t size) {
++  return size ? pdfium::base::AlignedAlloc(size, 16) : nullptr;
++}
++
++void opj_aligned_free(void* ptr) {
++  pdfium::base::AlignedFree(ptr);
++}
++
++void* opj_aligned_32_malloc(size_t size) {
++  return size ? pdfium::base::AlignedAlloc(size, 32) : nullptr;
++}
++
++void* opj_realloc(void* m, size_t s) {
++  return FXMEM_DefaultRealloc(m, s);
++}
++
++void opj_free(void* m) {
++  if (m)
++    FXMEM_DefaultFree(m);
++}
++
++}  // extern "C"
 diff --git a/third_party/libopenjpeg20/opj_malloc.h b/third_party/libopenjpeg20/opj_malloc.h
-index cbc4106c7..79b3a6410 100644
 --- a/third_party/libopenjpeg20/opj_malloc.h
 +++ b/third_party/libopenjpeg20/opj_malloc.h
-@@ -31,8 +31,6 @@
-  */
- #ifndef OPJ_MALLOC_H
+@@ -33,6 +33,11 @@
  #define OPJ_MALLOC_H
--
--#include <stddef.h>
+ 
+ #include <stddef.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
  /**
  @file opj_malloc.h
  @brief Internal functions
-@@ -52,7 +50,16 @@ Allocate an uninitialized memory block
- @param size Bytes to allocate
+@@ -68,7 +73,6 @@ Allocate memory aligned to a 16 byte bou
  @return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available
  */
--void * opj_malloc(size_t size);
-+#ifdef ALLOC_PERF_OPT
-+void * OPJ_CALLCONV opj_malloc(size_t size);
-+#else
-+/* prevent assertion on overflow for MSVC */
-+#ifdef _MSC_VER
-+#define opj_malloc(size) ((size_t)(size) >= (size_t)-0x100 ? NULL : malloc(size))
-+#else
-+#define opj_malloc(size) malloc(size)
-+#endif
-+#endif
- 
- /**
- Allocate a memory block with elements initialized to 0
-@@ -60,24 +67,98 @@ Allocate a memory block with elements initialized to 0
- @param sizeOfElements Bytes per block to allocate
- @return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available
- */
--void * opj_calloc(size_t numOfElements, size_t sizeOfElements);
-+#ifdef ALLOC_PERF_OPT
-+void * OPJ_CALLCONV opj_calloc(size_t _NumOfElements, size_t _SizeOfElements);
-+#else
-+/* prevent assertion on overflow for MSVC */
-+#ifdef _MSC_VER
-+#define opj_calloc(num, size) ((size_t)(num) != 0 && (size_t)(num) >= (size_t)-0x100 / (size_t)(size) ? NULL : calloc(num, size))
-+#else
-+#define opj_calloc(num, size) calloc(num, size)
-+#endif
-+#endif
- 
- /**
- Allocate memory aligned to a 16 byte boundary
- @param size Bytes to allocate
- @return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available
- */
--void * opj_aligned_malloc(size_t size);
+ void * opj_aligned_malloc(size_t size);
 -void * opj_aligned_realloc(void *ptr, size_t size);
--void opj_aligned_free(void* ptr);
-+/* FIXME: These should be set with cmake tests, but we're currently not requiring use of cmake */
-+#ifdef _WIN32
-+  /* Someone should tell the mingw people that their malloc.h ought to provide _mm_malloc() */
-+  #ifdef __GNUC__
-+    #include <mm_malloc.h>
-+    #define HAVE_MM_MALLOC
-+  #else /* MSVC, Intel C++ */
-+    #include <malloc.h>
-+    #ifdef _mm_malloc
-+      #define HAVE_MM_MALLOC
-+    #endif
-+  #endif
-+#else /* Not _WIN32 */
-+  #if defined(__sun)
-+    #define HAVE_MEMALIGN
-+  #elif defined(__FreeBSD__)
-+    #define HAVE_POSIX_MEMALIGN
-+  /* Linux x86_64 and OSX always align allocations to 16 bytes */
-+  #elif !defined(__amd64__) && !defined(__APPLE__) && !defined(_AIX)
-+    #define HAVE_MEMALIGN
-+    #include <malloc.h>
-+  #endif
-+#endif
+ void opj_aligned_free(void* ptr);
  
--/**
--Allocate memory aligned to a 32 byte boundary
--@param size Bytes to allocate
--@return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available
--*/
--void * opj_aligned_32_malloc(size_t size);
+ /**
+@@ -77,7 +81,6 @@ Allocate memory aligned to a 32 byte bou
+ @return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available
+ */
+ void * opj_aligned_32_malloc(size_t size);
 -void * opj_aligned_32_realloc(void *ptr, size_t size);
-+#define opj_aligned_malloc(size) malloc(size)
-+#define opj_aligned_32_malloc(size) malloc(size)
-+#define opj_aligned_free(m) free(m)
-+
-+#ifdef HAVE_MM_MALLOC
-+  #undef opj_aligned_malloc
-+  #define opj_aligned_malloc(size) _mm_malloc((size), 16)
-+  #undef opj_aligned_32_malloc
-+  #define opj_aligned_32_malloc(size) _mm_malloc((size), 32)
-+  #undef opj_aligned_free
-+  #define opj_aligned_free(m) _mm_free(m)
-+#endif
-+
-+#ifdef HAVE_MEMALIGN
-+  extern void* memalign(size_t, size_t);
-+  #undef opj_aligned_malloc
-+  #define opj_aligned_malloc(size) memalign(16, (size))
-+  #undef opj_aligned_32_malloc
-+  #define opj_aligned_32_malloc(size) memalign(32, (size))
-+  #undef opj_aligned_free
-+  #define opj_aligned_free(m) free(m)
-+#endif
-+
-+#ifdef HAVE_POSIX_MEMALIGN
-+  #undef opj_aligned_malloc
-+  extern int posix_memalign(void**, size_t, size_t);
-+
-+  static INLINE void* __attribute__ ((malloc)) opj_aligned_malloc(size_t size){
-+    void* mem = NULL;
-+    posix_memalign(&mem, 16, size);
-+    return mem;
-+  }
-+
-+  #undef opj_aligned_32_malloc
-+  static INLINE void* __attribute__ ((malloc)) opj_aligned_32_malloc(size_t size){
-+    void* mem = NULL;
-+    posix_memalign(&mem, 32, size);
-+    return mem;
-+  }
-+
-+  #undef opj_aligned_free
-+  #define opj_aligned_free(m) free(m)
-+#endif
-+
-+#ifdef ALLOC_PERF_OPT
-+  #undef opj_aligned_malloc
-+  #define opj_aligned_malloc(size) opj_malloc(size)
-+  #undef opj_aligned_32_malloc
-+  #define opj_aligned_32_malloc(size) opj_malloc(size)
-+  #undef opj_aligned_free
-+  #define opj_aligned_free(m) opj_free(m)
-+#endif
  
  /**
  Reallocate memory blocks.
-@@ -85,13 +166,26 @@ Reallocate memory blocks.
- @param s New size in bytes
- @return Returns a void pointer to the reallocated (and possibly moved) memory block
- */
--void * opj_realloc(void * m, size_t s);
-+#ifdef ALLOC_PERF_OPT
-+void * OPJ_CALLCONV opj_realloc(void * m, size_t s);
-+#else
-+/* prevent assertion on overflow for MSVC */
-+#ifdef _MSC_VER
-+#define opj_realloc(m, s) ((size_t)(s) >= (size_t)-0x100 ? NULL : realloc(m, s))
-+#else
-+#define opj_realloc(m, s) realloc(m, s)
-+#endif
+@@ -102,5 +105,8 @@ void opj_free(void * m);
+ 
+ /*@}*/
+ 
+-#endif /* OPJ_MALLOC_H */
++#ifdef __cplusplus
++}  // extern "C"
 +#endif
  
- /**
- Deallocates or frees a memory block.
- @param m Previously allocated memory block to be freed
- */
--void opj_free(void * m);
-+#ifdef ALLOC_PERF_OPT
-+void OPJ_CALLCONV opj_free(void * m);
-+#else
-+#define opj_free(m) free(m)
-+#endif
- 
- #if defined(__GNUC__) && !defined(OPJ_SKIP_POISON)
- #pragma GCC poison malloc calloc realloc free
++#endif /* OPJ_MALLOC_H */
diff --git a/third_party/libopenjpeg20/opj_malloc.cc b/third_party/libopenjpeg20/opj_malloc.cc
new file mode 100644
index 0000000..f530060
--- /dev/null
+++ b/third_party/libopenjpeg20/opj_malloc.cc
@@ -0,0 +1,42 @@
+// Copyright 2020 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Deliberately not including opj_malloc.h, which has poisoned malloc and
+// friends.
+
+#include "core/fxcrt/fx_memory.h"
+#include "third_party/base/memory/aligned_memory.h"
+
+extern "C" {
+
+void* opj_malloc(size_t size) {
+  return FXMEM_DefaultAlloc(size);
+}
+
+void* opj_calloc(size_t numOfElements, size_t sizeOfElements) {
+  return FXMEM_DefaultCalloc(numOfElements, sizeOfElements);
+}
+
+void* opj_aligned_malloc(size_t size) {
+  return size ? pdfium::base::AlignedAlloc(size, 16) : nullptr;
+}
+
+void opj_aligned_free(void* ptr) {
+  pdfium::base::AlignedFree(ptr);
+}
+
+void* opj_aligned_32_malloc(size_t size) {
+  return size ? pdfium::base::AlignedAlloc(size, 32) : nullptr;
+}
+
+void* opj_realloc(void* m, size_t s) {
+  return FXMEM_DefaultRealloc(m, s);
+}
+
+void opj_free(void* m) {
+  if (m)
+    FXMEM_DefaultFree(m);
+}
+
+}  // extern "C"
diff --git a/third_party/libopenjpeg20/opj_malloc.h b/third_party/libopenjpeg20/opj_malloc.h
index 79b3a64..c215c24 100644
--- a/third_party/libopenjpeg20/opj_malloc.h
+++ b/third_party/libopenjpeg20/opj_malloc.h
@@ -31,6 +31,13 @@
  */
 #ifndef OPJ_MALLOC_H
 #define OPJ_MALLOC_H
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /**
 @file opj_malloc.h
 @brief Internal functions
@@ -50,16 +57,7 @@
 @param size Bytes to allocate
 @return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available
 */
-#ifdef ALLOC_PERF_OPT
-void * OPJ_CALLCONV opj_malloc(size_t size);
-#else
-/* prevent assertion on overflow for MSVC */
-#ifdef _MSC_VER
-#define opj_malloc(size) ((size_t)(size) >= (size_t)-0x100 ? NULL : malloc(size))
-#else
-#define opj_malloc(size) malloc(size)
-#endif
-#endif
+void * opj_malloc(size_t size);
 
 /**
 Allocate a memory block with elements initialized to 0
@@ -67,98 +65,22 @@
 @param sizeOfElements Bytes per block to allocate
 @return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available
 */
-#ifdef ALLOC_PERF_OPT
-void * OPJ_CALLCONV opj_calloc(size_t _NumOfElements, size_t _SizeOfElements);
-#else
-/* prevent assertion on overflow for MSVC */
-#ifdef _MSC_VER
-#define opj_calloc(num, size) ((size_t)(num) != 0 && (size_t)(num) >= (size_t)-0x100 / (size_t)(size) ? NULL : calloc(num, size))
-#else
-#define opj_calloc(num, size) calloc(num, size)
-#endif
-#endif
+void * opj_calloc(size_t numOfElements, size_t sizeOfElements);
 
 /**
 Allocate memory aligned to a 16 byte boundary
 @param size Bytes to allocate
 @return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available
 */
-/* FIXME: These should be set with cmake tests, but we're currently not requiring use of cmake */
-#ifdef _WIN32
-  /* Someone should tell the mingw people that their malloc.h ought to provide _mm_malloc() */
-  #ifdef __GNUC__
-    #include <mm_malloc.h>
-    #define HAVE_MM_MALLOC
-  #else /* MSVC, Intel C++ */
-    #include <malloc.h>
-    #ifdef _mm_malloc
-      #define HAVE_MM_MALLOC
-    #endif
-  #endif
-#else /* Not _WIN32 */
-  #if defined(__sun)
-    #define HAVE_MEMALIGN
-  #elif defined(__FreeBSD__)
-    #define HAVE_POSIX_MEMALIGN
-  /* Linux x86_64 and OSX always align allocations to 16 bytes */
-  #elif !defined(__amd64__) && !defined(__APPLE__) && !defined(_AIX)
-    #define HAVE_MEMALIGN
-    #include <malloc.h>
-  #endif
-#endif
+void * opj_aligned_malloc(size_t size);
+void opj_aligned_free(void* ptr);
 
-#define opj_aligned_malloc(size) malloc(size)
-#define opj_aligned_32_malloc(size) malloc(size)
-#define opj_aligned_free(m) free(m)
-
-#ifdef HAVE_MM_MALLOC
-  #undef opj_aligned_malloc
-  #define opj_aligned_malloc(size) _mm_malloc((size), 16)
-  #undef opj_aligned_32_malloc
-  #define opj_aligned_32_malloc(size) _mm_malloc((size), 32)
-  #undef opj_aligned_free
-  #define opj_aligned_free(m) _mm_free(m)
-#endif
-
-#ifdef HAVE_MEMALIGN
-  extern void* memalign(size_t, size_t);
-  #undef opj_aligned_malloc
-  #define opj_aligned_malloc(size) memalign(16, (size))
-  #undef opj_aligned_32_malloc
-  #define opj_aligned_32_malloc(size) memalign(32, (size))
-  #undef opj_aligned_free
-  #define opj_aligned_free(m) free(m)
-#endif
-
-#ifdef HAVE_POSIX_MEMALIGN
-  #undef opj_aligned_malloc
-  extern int posix_memalign(void**, size_t, size_t);
-
-  static INLINE void* __attribute__ ((malloc)) opj_aligned_malloc(size_t size){
-    void* mem = NULL;
-    posix_memalign(&mem, 16, size);
-    return mem;
-  }
-
-  #undef opj_aligned_32_malloc
-  static INLINE void* __attribute__ ((malloc)) opj_aligned_32_malloc(size_t size){
-    void* mem = NULL;
-    posix_memalign(&mem, 32, size);
-    return mem;
-  }
-
-  #undef opj_aligned_free
-  #define opj_aligned_free(m) free(m)
-#endif
-
-#ifdef ALLOC_PERF_OPT
-  #undef opj_aligned_malloc
-  #define opj_aligned_malloc(size) opj_malloc(size)
-  #undef opj_aligned_32_malloc
-  #define opj_aligned_32_malloc(size) opj_malloc(size)
-  #undef opj_aligned_free
-  #define opj_aligned_free(m) opj_free(m)
-#endif
+/**
+Allocate memory aligned to a 32 byte boundary
+@param size Bytes to allocate
+@return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available
+*/
+void * opj_aligned_32_malloc(size_t size);
 
 /**
 Reallocate memory blocks.
@@ -166,26 +88,13 @@
 @param s New size in bytes
 @return Returns a void pointer to the reallocated (and possibly moved) memory block
 */
-#ifdef ALLOC_PERF_OPT
-void * OPJ_CALLCONV opj_realloc(void * m, size_t s);
-#else
-/* prevent assertion on overflow for MSVC */
-#ifdef _MSC_VER
-#define opj_realloc(m, s) ((size_t)(s) >= (size_t)-0x100 ? NULL : realloc(m, s))
-#else
-#define opj_realloc(m, s) realloc(m, s)
-#endif
-#endif
+void * opj_realloc(void * m, size_t s);
 
 /**
 Deallocates or frees a memory block.
 @param m Previously allocated memory block to be freed
 */
-#ifdef ALLOC_PERF_OPT
-void OPJ_CALLCONV opj_free(void * m);
-#else
-#define opj_free(m) free(m)
-#endif
+void opj_free(void * m);
 
 #if defined(__GNUC__) && !defined(OPJ_SKIP_POISON)
 #pragma GCC poison malloc calloc realloc free
@@ -196,5 +105,8 @@
 
 /*@}*/
 
-#endif /* OPJ_MALLOC_H */
+#ifdef __cplusplus
+}  // extern "C"
+#endif
 
+#endif /* OPJ_MALLOC_H */