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 */