Upgrade OpenJPEG to 2.3.1.

Bug: pdfium:1309
Change-Id: I4ed683b9883681d9657d02509c9d592b8417ffff
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/57251
Reviewed-by: Nicolás Peña Moreno <npm@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/third_party/libopenjpeg20/0003-dwt-decode.patch b/third_party/libopenjpeg20/0003-dwt-decode.patch
index 631219a..94d4b41 100644
--- a/third_party/libopenjpeg20/0003-dwt-decode.patch
+++ b/third_party/libopenjpeg20/0003-dwt-decode.patch
@@ -1,17 +1,18 @@
 diff --git a/third_party/libopenjpeg20/dwt.c b/third_party/libopenjpeg20/dwt.c
-index 83c148002..1455ee84a 100644
+index 5930d1c71..6512b1e4c 100644
 --- a/third_party/libopenjpeg20/dwt.c
 +++ b/third_party/libopenjpeg20/dwt.c
-@@ -62,8 +62,6 @@
- 
+@@ -63,9 +63,6 @@
  /** @defgroup DWT DWT - Implementation of a discrete wavelet transform */
  /*@{*/
+ 
 -#define OPJ_WS(i) v->mem[(i)*2]
 -#define OPJ_WD(i) v->mem[(1+(i)*2)]
- 
+-
  #ifdef __AVX2__
  /** Number of int32 values in a AVX2 register */
-@@ -81,6 +79,7 @@
+ #define VREG_INT_COUNT       8
+@@ -82,6 +79,7 @@
  
  typedef struct dwt_local {
      OPJ_INT32* mem;
@@ -19,7 +20,7 @@
      OPJ_INT32 dn;   /* number of elements in high pass band */
      OPJ_INT32 sn;   /* number of elements in low pass band */
      OPJ_INT32 cas;  /* 0 = start on even coord, 1 = start on odd coord */
-@@ -132,13 +131,14 @@ static void opj_dwt_deinterleave_v(OPJ_INT32 *a, OPJ_INT32 *b, OPJ_INT32 dn,
+@@ -133,13 +131,13 @@ static void opj_dwt_deinterleave_v(OPJ_INT32 *a, OPJ_INT32 *b, OPJ_INT32 dn,
  /**
  Forward 5-3 wavelet transform in 1-D
  */
@@ -34,11 +35,10 @@
 -                                  OPJ_INT32 cas);
 +static void opj_dwt_encode_1_real(OPJ_INT32 *a, OPJ_SIZE_T a_count,
 +    OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas);
-+
- 
  /**
  Explicit calculation of the Quantization Stepsizes
-@@ -149,14 +149,14 @@ static void opj_dwt_encode_stepsize(OPJ_INT32 stepsize, OPJ_INT32 numbps,
+ */
+@@ -149,14 +147,14 @@ static void opj_dwt_encode_stepsize(OPJ_INT32 stepsize, OPJ_INT32 numbps,
  Inverse wavelet transform in 2-D.
  */
  static OPJ_BOOL opj_dwt_decode_tile(opj_thread_pool_t* tp,
@@ -56,7 +56,7 @@
  
  static OPJ_UINT32 opj_dwt_max_resolution(opj_tcd_resolution_t* OPJ_RESTRICT r,
          OPJ_UINT32 i);
-@@ -205,13 +205,20 @@ static void opj_v4dwt_decode_step2(opj_v4_t* l, opj_v4_t* w,
+@@ -205,13 +203,20 @@ static void opj_v4dwt_decode_step2(opj_v4_t* l, opj_v4_t* w,
  
  /*@}*/
  
@@ -83,7 +83,7 @@
  
  /* <summary>                                                              */
  /* This table contains the norms of the 5-3 wavelets for different bands. */
-@@ -344,8 +351,8 @@ static void opj_dwt_interleave_v(const opj_dwt_t* v, OPJ_INT32 *a, OPJ_INT32 x)
+@@ -344,8 +349,8 @@ static void opj_dwt_interleave_v(const opj_dwt_t* v, OPJ_INT32 *a, OPJ_INT32 x)
  /* <summary>                            */
  /* Forward 5-3 wavelet transform in 1-D. */
  /* </summary>                           */
@@ -94,7 +94,7 @@
  {
      OPJ_INT32 i;
  
-@@ -376,8 +383,8 @@ static void opj_dwt_encode_1(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn,
+@@ -376,8 +381,8 @@ static void opj_dwt_encode_1(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn,
  /* <summary>                            */
  /* Inverse 5-3 wavelet transform in 1-D. */
  /* </summary>                           */
@@ -105,7 +105,7 @@
  {
      OPJ_INT32 i;
  
-@@ -406,7 +413,7 @@ static void opj_dwt_decode_1_(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn,
+@@ -406,7 +411,7 @@ static void opj_dwt_decode_1_(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn,
  
  static void opj_dwt_decode_1(const opj_dwt_t *v)
  {
@@ -114,7 +114,7 @@
  }
  
  #endif /* STANDARD_SLOW_VERSION */
-@@ -1037,8 +1044,8 @@ static void opj_idwt53_v(const opj_dwt_t *dwt,
+@@ -1037,8 +1042,8 @@ static void opj_idwt53_v(const opj_dwt_t *dwt,
  /* <summary>                             */
  /* Forward 9-7 wavelet transform in 1-D. */
  /* </summary>                            */
@@ -125,7 +125,7 @@
  {
      OPJ_INT32 i;
      if (!cas) {
-@@ -1106,8 +1113,8 @@ static void opj_dwt_encode_stepsize(OPJ_INT32 stepsize, OPJ_INT32 numbps,
+@@ -1106,8 +1111,8 @@ static void opj_dwt_encode_stepsize(OPJ_INT32 stepsize, OPJ_INT32 numbps,
  /* <summary>                            */
  /* Forward 5-3 wavelet transform in 2-D. */
  /* </summary>                           */
@@ -136,7 +136,7 @@
  {
      OPJ_INT32 i, j, k;
      OPJ_INT32 *a = 00;
-@@ -1117,6 +1124,7 @@ static INLINE OPJ_BOOL opj_dwt_encode_procedure(opj_tcd_tilecomp_t * tilec,
+@@ -1117,6 +1122,7 @@ static INLINE OPJ_BOOL opj_dwt_encode_procedure(opj_tcd_tilecomp_t * tilec,
  
      OPJ_INT32 rw;           /* width of the resolution level computed   */
      OPJ_INT32 rh;           /* height of the resolution level computed  */
@@ -144,7 +144,7 @@
      OPJ_SIZE_T l_data_size;
  
      opj_tcd_resolution_t * l_cur_res = 0;
-@@ -1129,13 +1137,13 @@ static INLINE OPJ_BOOL opj_dwt_encode_procedure(opj_tcd_tilecomp_t * tilec,
+@@ -1129,13 +1135,13 @@ static INLINE OPJ_BOOL opj_dwt_encode_procedure(opj_tcd_tilecomp_t * tilec,
      l_cur_res = tilec->resolutions + l;
      l_last_res = l_cur_res - 1;
  
@@ -161,7 +161,7 @@
      bj = (OPJ_INT32*)opj_malloc(l_data_size);
      /* l_data_size is equal to 0 when numresolutions == 1 but bj is not used */
      /* in that case, so do not error out */
-@@ -1167,7 +1175,7 @@ static INLINE OPJ_BOOL opj_dwt_encode_procedure(opj_tcd_tilecomp_t * tilec,
+@@ -1167,7 +1173,7 @@ static INLINE OPJ_BOOL opj_dwt_encode_procedure(opj_tcd_tilecomp_t * tilec,
                  bj[k] = aj[k * w];
              }
  
@@ -170,7 +170,7 @@
  
              opj_dwt_deinterleave_v(bj, aj, dn, sn, w, cas_col);
          }
-@@ -1180,7 +1188,7 @@ static INLINE OPJ_BOOL opj_dwt_encode_procedure(opj_tcd_tilecomp_t * tilec,
+@@ -1180,7 +1186,7 @@ static INLINE OPJ_BOOL opj_dwt_encode_procedure(opj_tcd_tilecomp_t * tilec,
              for (k = 0; k < rw; k++) {
                  bj[k] = aj[k];
              }
@@ -179,7 +179,7 @@
              opj_dwt_deinterleave_h(bj, aj, dn, sn, cas_row);
          }
  
-@@ -1379,7 +1387,7 @@ static void opj_dwt_decode_v_func(void* user_data, opj_tls_t* tls)
+@@ -1379,7 +1385,7 @@ static void opj_dwt_decode_v_func(void* user_data, opj_tls_t* tls)
  /* Inverse wavelet transform in 2-D.    */
  /* </summary>                           */
  static OPJ_BOOL opj_dwt_decode_tile(opj_thread_pool_t* tp,
@@ -188,7 +188,7 @@
  {
      opj_dwt_t h;
      opj_dwt_t v;
-@@ -1401,22 +1409,23 @@ static OPJ_BOOL opj_dwt_decode_tile(opj_thread_pool_t* tp,
+@@ -1401,22 +1407,23 @@ static OPJ_BOOL opj_dwt_decode_tile(opj_thread_pool_t* tp,
          return OPJ_TRUE;
      }
      num_threads = opj_thread_pool_get_thread_count(tp);
@@ -215,7 +215,7 @@
      v.mem = h.mem;
  
      while (--numres) {
-@@ -1594,7 +1603,8 @@ static void opj_dwt_interleave_partial_v(OPJ_INT32 *dest,
+@@ -1594,7 +1601,8 @@ static void opj_dwt_interleave_partial_v(OPJ_INT32 *dest,
      OPJ_UNUSED(ret);
  }
  
@@ -225,7 +225,7 @@
                                       OPJ_INT32 cas,
                                       OPJ_INT32 win_l_x0,
                                       OPJ_INT32 win_l_x1,
-@@ -1974,16 +1984,16 @@ static OPJ_BOOL opj_dwt_decode_partial_tile(
+@@ -1974,16 +1982,16 @@ static OPJ_BOOL opj_dwt_decode_partial_tile(
          opj_sparse_array_int32_free(sa);
          return OPJ_TRUE;
      }
@@ -245,7 +245,7 @@
      h.mem = (OPJ_INT32*)opj_aligned_32_malloc(h_mem_size);
      if (! h.mem) {
          /* FIXME event manager error callback */
-@@ -1991,6 +2001,7 @@ static OPJ_BOOL opj_dwt_decode_partial_tile(
+@@ -1991,6 +1999,7 @@ static OPJ_BOOL opj_dwt_decode_partial_tile(
          return OPJ_FALSE;
      }
  
@@ -253,7 +253,7 @@
      v.mem = h.mem;
  
      for (resno = 1; resno < numres; resno ++) {
-@@ -2101,7 +2112,7 @@ static OPJ_BOOL opj_dwt_decode_partial_tile(
+@@ -2101,7 +2110,7 @@ static OPJ_BOOL opj_dwt_decode_partial_tile(
                                               win_ll_x1,
                                               win_hl_x0,
                                               win_hl_x1);
diff --git a/third_party/libopenjpeg20/0005-jp2_apply_pclr.patch b/third_party/libopenjpeg20/0005-jp2_apply_pclr.patch
index c8caea8..2d45017 100644
--- a/third_party/libopenjpeg20/0005-jp2_apply_pclr.patch
+++ b/third_party/libopenjpeg20/0005-jp2_apply_pclr.patch
@@ -1,5 +1,5 @@
 diff --git a/third_party/libopenjpeg20/jp2.c b/third_party/libopenjpeg20/jp2.c
-index da4e05f82..c9562f705 100644
+index 8dc1ecbe6..61b3f5821 100644
 --- a/third_party/libopenjpeg20/jp2.c
 +++ b/third_party/libopenjpeg20/jp2.c
 @@ -1073,8 +1073,8 @@ static OPJ_BOOL opj_jp2_apply_pclr(opj_image_t *image,
@@ -13,7 +13,7 @@
          }
  
          /* Palette mapping: */
-@@ -1102,19 +1102,19 @@ static OPJ_BOOL opj_jp2_apply_pclr(opj_image_t *image,
+@@ -1102,7 +1102,7 @@ static OPJ_BOOL opj_jp2_apply_pclr(opj_image_t *image,
          pcol = cmap[i].pcol;
          src = old_comps[cmp].data;
          assert(src); /* verified above */
@@ -22,11 +22,7 @@
  
          /* Direct use: */
          if (cmap[i].mtyp == 0) {
--            assert(cmp == 0);
-+            assert( cmp == 0 ); // probably wrong.
-             dst = new_comps[i].data;
-             assert(dst);
-             for (j = 0; j < max; ++j) {
+@@ -1112,8 +1112,8 @@ static OPJ_BOOL opj_jp2_apply_pclr(opj_image_t *image,
                  dst[j] = src[j];
              }
          } else {
diff --git a/third_party/libopenjpeg20/0019-tcd_init_tile.patch b/third_party/libopenjpeg20/0019-tcd_init_tile.patch
index fc5a3aa..8746eac 100644
--- a/third_party/libopenjpeg20/0019-tcd_init_tile.patch
+++ b/third_party/libopenjpeg20/0019-tcd_init_tile.patch
@@ -1,21 +1,14 @@
 diff --git a/third_party/libopenjpeg20/tcd.c b/third_party/libopenjpeg20/tcd.c
-index f0710cd14..35d15e3d1 100644
+index be3b84363..5757fd401 100644
 --- a/third_party/libopenjpeg20/tcd.c
 +++ b/third_party/libopenjpeg20/tcd.c
-@@ -1040,9 +1040,15 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
-                                                           cblkwidthexpn);
+@@ -1065,6 +1065,9 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
                      l_current_precinct->ch = (OPJ_UINT32)((brcblkyend - tlcblkystart) >>
                                                            cblkheightexpn);
--
+ 
 +                    if (l_current_precinct->cw && ((OPJ_UINT32)-1) / l_current_precinct->cw < l_current_precinct->ch) {
 +                        return OPJ_FALSE;
 +                    }
                      l_nb_code_blocks = l_current_precinct->cw * l_current_precinct->ch;
                      /*fprintf(stderr, "\t\t\t\t precinct_cw = %d x recinct_ch = %d\n",l_current_precinct->cw, l_current_precinct->ch);      */
-+
-+                    if (((OPJ_UINT32)-1) / (OPJ_UINT32)sizeof_block < l_nb_code_blocks) {
-+                        return OPJ_FALSE;
-+                    }
-                     l_nb_code_blocks_size = l_nb_code_blocks * (OPJ_UINT32)sizeof_block;
- 
-                     if (!l_current_precinct->cblks.blocks && (l_nb_code_blocks > 0U)) {
+                     if ((((OPJ_UINT32) - 1) / (OPJ_UINT32)sizeof_block) <
diff --git a/third_party/libopenjpeg20/0022-jp2_apply_pclr_overflow.patch b/third_party/libopenjpeg20/0022-jp2_apply_pclr_overflow.patch
index f4f2ef5..c1773d4 100644
--- a/third_party/libopenjpeg20/0022-jp2_apply_pclr_overflow.patch
+++ b/third_party/libopenjpeg20/0022-jp2_apply_pclr_overflow.patch
@@ -1,8 +1,8 @@
 diff --git a/third_party/libopenjpeg20/jp2.c b/third_party/libopenjpeg20/jp2.c
-index 1fa607d66..78a2d22ff 100644
+index 8dc2b977f..3e23bc363 100644
 --- a/third_party/libopenjpeg20/jp2.c
 +++ b/third_party/libopenjpeg20/jp2.c
-@@ -1049,6 +1049,14 @@ static OPJ_BOOL opj_jp2_apply_pclr(opj_image_t *image,
+@@ -1058,6 +1058,14 @@ static OPJ_BOOL opj_jp2_apply_pclr(opj_image_t *image,
      }
  
      old_comps = image->comps;
@@ -17,7 +17,7 @@
      new_comps = (opj_image_comp_t*)
                  opj_malloc(nr_channels * sizeof(opj_image_comp_t));
      if (!new_comps) {
-@@ -1093,21 +1101,27 @@ static OPJ_BOOL opj_jp2_apply_pclr(opj_image_t *image,
+@@ -1102,20 +1110,26 @@ static OPJ_BOOL opj_jp2_apply_pclr(opj_image_t *image,
          cmp = cmap[i].cmp;
          pcol = cmap[i].pcol;
          src = old_comps[cmp].data;
@@ -37,7 +37,6 @@
 +
          /* Direct use: */
          if (cmap[i].mtyp == 0) {
-             assert( cmp == 0 ); // probably wrong.
 -            dst = new_comps[i].data;
 -            assert(dst);
              for (j = 0; j < max; ++j) {
diff --git a/third_party/libopenjpeg20/0037-opj_j2k_merge_ppt_leak.patch b/third_party/libopenjpeg20/0037-opj_j2k_merge_ppt_leak.patch
deleted file mode 100644
index 3ea17f9..0000000
--- a/third_party/libopenjpeg20/0037-opj_j2k_merge_ppt_leak.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-diff --git a/third_party/libopenjpeg20/j2k.c b/third_party/libopenjpeg20/j2k.c
-index cea614709..afcd597ee 100644
---- a/third_party/libopenjpeg20/j2k.c
-+++ b/third_party/libopenjpeg20/j2k.c
-@@ -4085,7 +4085,12 @@ static OPJ_BOOL opj_j2k_merge_ppt(opj_tcp_t *p_tcp, opj_event_mgr_t * p_manager)
-     /* preconditions */
-     assert(p_tcp != 00);
-     assert(p_manager != 00);
--    assert(p_tcp->ppt_buffer == NULL);
-+
-+    if (p_tcp->ppt_buffer != NULL) {
-+        opj_event_msg(p_manager, EVT_ERROR,
-+                      "opj_j2k_merge_ppt() has already been called\n");
-+        return OPJ_FALSE;
-+    }
- 
-     if (p_tcp->ppt == 0U) {
-         return OPJ_TRUE;
-@@ -8836,7 +8841,10 @@ OPJ_BOOL opj_j2k_read_tile_header(opj_j2k_t * p_j2k,
- 
-     /* Current marker is the EOC marker ?*/
-     if (l_current_marker == J2K_MS_EOC) {
--        p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_EOC;
-+        if (p_j2k->m_specific_param.m_decoder.m_state != J2K_STATE_EOC) {
-+            p_j2k->m_current_tile_number = 0;
-+            p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_EOC;
-+        }
-     }
- 
-     /* FIXME DOC ???*/
diff --git a/third_party/libopenjpeg20/README.pdfium b/third_party/libopenjpeg20/README.pdfium
index 2c944d5..45d8bec 100644
--- a/third_party/libopenjpeg20/README.pdfium
+++ b/third_party/libopenjpeg20/README.pdfium
@@ -1,6 +1,6 @@
 Name: OpenJPEG
 URL: http://www.openjpeg.org/
-Version: 2.3.0 (also update in opj_config*)
+Version: 2.3.1 (also update in opj_config*)
 Security Critical: yes
 License: 2-clause BSD
 
@@ -29,4 +29,3 @@
 0034-opj_malloc.patch: PDFium changes in opj_malloc.
 0035-opj_image_data_free.patch: Use the right free function in opj_jp2_apply_pclr.
 0036-opj_j2k_update_image_dimensions.patch: fix integer overflow.
-0037-opj_j2k_merge_ppt_leak.patch: fix memory leak.
diff --git a/third_party/libopenjpeg20/dwt.c b/third_party/libopenjpeg20/dwt.c
index 1455ee8..6512b1e 100644
--- a/third_party/libopenjpeg20/dwt.c
+++ b/third_party/libopenjpeg20/dwt.c
@@ -138,8 +138,6 @@
 */
 static void opj_dwt_encode_1_real(OPJ_INT32 *a, OPJ_SIZE_T a_count,
     OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas);
-
-
 /**
 Explicit calculation of the Quantization Stepsizes
 */
@@ -981,7 +979,7 @@
 #if (defined(__SSE2__) || defined(__AVX2__))
         if (len > 1 && nb_cols == PARALLEL_COLS_53) {
             /* Same as below general case, except that thanks to SSE2/AVX2 */
-            /* we can efficently process 8/16 columns in parallel */
+            /* we can efficiently process 8/16 columns in parallel */
             opj_idwt53_v_cas0_mcols_SSE2_OR_AVX2(dwt->mem, sn, len, tiledp_col, stride);
             return;
         }
@@ -1024,7 +1022,7 @@
 #if (defined(__SSE2__) || defined(__AVX2__))
         if (len > 2 && nb_cols == PARALLEL_COLS_53) {
             /* Same as below general case, except that thanks to SSE2/AVX2 */
-            /* we can efficently process 8/16 columns in parallel */
+            /* we can efficiently process 8/16 columns in parallel */
             opj_idwt53_v_cas1_mcols_SSE2_OR_AVX2(dwt->mem, sn, len, tiledp_col, stride);
             return;
         }
@@ -2052,7 +2050,7 @@
         tr_hl_x0 = (OPJ_UINT32)tr->bands[0].x0;
         tr_lh_y0 = (OPJ_UINT32)tr->bands[1].y0;
 
-        /* Substract the origin of the bands for this tile, to the subwindow */
+        /* Subtract the origin of the bands for this tile, to the subwindow */
         /* of interest band coordinates, so as to get them relative to the */
         /* tile */
         win_ll_x0 = opj_uint_subs(win_ll_x0, tr_ll_x0);
@@ -2707,17 +2705,20 @@
     /* overflow check */
     if (l_data_size > (SIZE_MAX - 5U)) {
         /* FIXME event manager error callback */
+        opj_sparse_array_int32_free(sa);
         return OPJ_FALSE;
     }
     l_data_size += 5U;
     /* overflow check */
     if (l_data_size > (SIZE_MAX / sizeof(opj_v4_t))) {
         /* FIXME event manager error callback */
+        opj_sparse_array_int32_free(sa);
         return OPJ_FALSE;
     }
     h.wavelet = (opj_v4_t*) opj_aligned_malloc(l_data_size * sizeof(opj_v4_t));
     if (!h.wavelet) {
         /* FIXME event manager error callback */
+        opj_sparse_array_int32_free(sa);
         return OPJ_FALSE;
     }
     v.wavelet = h.wavelet;
@@ -2770,7 +2771,7 @@
         tr_hl_x0 = (OPJ_UINT32)tr->bands[0].x0;
         tr_lh_y0 = (OPJ_UINT32)tr->bands[1].y0;
 
-        /* Substract the origin of the bands for this tile, to the subwindow */
+        /* Subtract the origin of the bands for this tile, to the subwindow */
         /* of interest band coordinates, so as to get them relative to the */
         /* tile */
         win_ll_x0 = opj_uint_subs(win_ll_x0, tr_ll_x0);
diff --git a/third_party/libopenjpeg20/image.c b/third_party/libopenjpeg20/image.c
index 13bcb8e..fe37390 100644
--- a/third_party/libopenjpeg20/image.c
+++ b/third_party/libopenjpeg20/image.c
@@ -48,8 +48,8 @@
         image->color_space = clrspc;
         image->numcomps = numcmpts;
         /* allocate memory for the per-component information */
-        image->comps = (opj_image_comp_t*)opj_calloc(1,
-                       image->numcomps * sizeof(opj_image_comp_t));
+        image->comps = (opj_image_comp_t*)opj_calloc(image->numcomps,
+                       sizeof(opj_image_comp_t));
         if (!image->comps) {
             /* TODO replace with event manager, breaks API */
             /* fprintf(stderr,"Unable to allocate memory for image.\n"); */
diff --git a/third_party/libopenjpeg20/j2k.c b/third_party/libopenjpeg20/j2k.c
index afcd597..690b533 100644
--- a/third_party/libopenjpeg20/j2k.c
+++ b/third_party/libopenjpeg20/j2k.c
@@ -508,7 +508,7 @@
                                   opj_event_mgr_t * p_manager);
 
 /**
- * Reads a COD marker (Coding Styke defaults)
+ * Reads a COD marker (Coding style defaults)
  * @param       p_header_data   the data contained in the COD box.
  * @param       p_j2k                   the jpeg2000 codec.
  * @param       p_header_size   the size of the data contained in the COD marker.
@@ -1925,7 +1925,8 @@
     /* FIXME move it in a index structure included in p_j2k*/
     p_j2k->cstr_index->main_head_start = opj_stream_tell(p_stream) - 2;
 
-    opj_event_msg(p_manager, EVT_INFO, "Start to read j2k main header (%d).\n",
+    opj_event_msg(p_manager, EVT_INFO,
+                  "Start to read j2k main header (%" PRId64 ").\n",
                   p_j2k->cstr_index->main_head_start);
 
     /* Add the marker to the codestream index*/
@@ -2621,7 +2622,7 @@
 }
 
 /**
- * Reads a COD marker (Coding Styke defaults)
+ * Reads a COD marker (Coding style defaults)
  * @param       p_header_data   the data contained in the COD box.
  * @param       p_j2k                   the jpeg2000 codec.
  * @param       p_header_size   the size of the data contained in the COD marker.
@@ -2653,12 +2654,17 @@
             &l_cp->tcps[p_j2k->m_current_tile_number] :
             p_j2k->m_specific_param.m_decoder.m_default_tcp;
 
+#if 0
+    /* This check was added per https://github.com/uclouvain/openjpeg/commit/daed8cc9195555e101ab708a501af2dfe6d5e001 */
+    /* but this is no longer necessary to handle issue476.jp2 */
+    /* and this actually cause issues on legit files. See https://github.com/uclouvain/openjpeg/issues/1043 */
     /* Only one COD per tile */
     if (l_tcp->cod) {
         opj_event_msg(p_manager, EVT_ERROR,
                       "COD marker already read. No more than one COD marker per tile.\n");
         return OPJ_FALSE;
     }
+#endif
     l_tcp->cod = 1;
 
     /* Make sure room is sufficient */
@@ -6424,7 +6430,9 @@
 
 OPJ_BOOL opj_j2k_set_threads(opj_j2k_t *j2k, OPJ_UINT32 num_threads)
 {
-    if (opj_has_thread_support()) {
+    /* Currently we pass the thread-pool to the tcd, so we cannot re-set it */
+    /* afterwards */
+    if (opj_has_thread_support() && j2k->m_tcd == NULL) {
         opj_thread_pool_destroy(j2k->m_tp);
         j2k->m_tp = NULL;
         if (num_threads <= (OPJ_UINT32)INT_MAX) {
diff --git a/third_party/libopenjpeg20/jp2.c b/third_party/libopenjpeg20/jp2.c
index 2374d45..ea67b98 100644
--- a/third_party/libopenjpeg20/jp2.c
+++ b/third_party/libopenjpeg20/jp2.c
@@ -1006,7 +1006,7 @@
                 if (!pcol_usage[i]) {
                     is_sane = 0U;
                     opj_event_msg(p_manager, EVT_WARNING,
-                                  "Component mapping seems wrong. Trying to correct.\n", i);
+                                  "Component mapping seems wrong. Trying to correct.\n");
                     break;
                 }
             }
@@ -1088,7 +1088,7 @@
 
         /* Palette mapping: */
         new_comps[i].data = (OPJ_INT32*)
-                            opj_image_data_alloc(old_comps[cmp].w * old_comps[cmp].h * sizeof(OPJ_INT32));
+                            opj_image_data_alloc(sizeof(OPJ_INT32) * old_comps[cmp].w * old_comps[cmp].h);
         if (!new_comps[i].data) {
             while (i > 0) {
                 -- i;
@@ -1125,7 +1125,6 @@
 
         /* Direct use: */
         if (cmap[i].mtyp == 0) {
-            assert( cmp == 0 ); // probably wrong.
             for (j = 0; j < max; ++j) {
                 dst[j] = src[j];
             }
@@ -1209,8 +1208,8 @@
         return OPJ_FALSE;
     }
 
-    entries = (OPJ_UINT32*) opj_malloc((size_t)nr_channels * nr_entries * sizeof(
-                                           OPJ_UINT32));
+    entries = (OPJ_UINT32*) opj_malloc(sizeof(OPJ_UINT32) * nr_channels *
+                                       nr_entries);
     if (!entries) {
         return OPJ_FALSE;
     }
diff --git a/third_party/libopenjpeg20/openjpeg.h b/third_party/libopenjpeg20/openjpeg.h
index c119e8f..f051b58 100644
--- a/third_party/libopenjpeg20/openjpeg.h
+++ b/third_party/libopenjpeg20/openjpeg.h
@@ -548,7 +548,7 @@
     /** Verbose mode */
     OPJ_BOOL m_verbose;
 
-    /** tile number ot the decoded tile*/
+    /** tile number of the decoded tile */
     OPJ_UINT32 tile_index;
     /** Nb of tile to decode */
     OPJ_UINT32 nb_tile_to_decode;
@@ -1182,7 +1182,8 @@
         opj_stream_skip_fn p_function);
 
 /**
- * Sets the given function to be used as a seek function, the stream is then seekable.
+ * Sets the given function to be used as a seek function, the stream is then seekable,
+ * using SEEK_SET behavior.
  * @param       p_stream    the stream to modify
  * @param       p_function  the function to use a skip function.
 */
@@ -1317,6 +1318,9 @@
  * number, or "ALL_CPUS". If OPJ_NUM_THREADS is set and this function is called,
  * this function will override the behaviour of the environment variable.
  *
+ * Currently this function must be called after opj_setup_decoder() and
+ * before opj_read_header().
+ *
  * Note: currently only has effect on the decompressor.
  *
  * @param p_codec       decompressor handler
@@ -1385,7 +1389,7 @@
  * performance improvements when reading an image by chunks.
  *
  * @param   p_codec         the jpeg2000 codec.
- * @param   p_image         the decoded image previously setted by opj_read_header
+ * @param   p_image         the decoded image previously set by opj_read_header
  * @param   p_start_x       the left position of the rectangle to decode (in image coordinates).
  * @param   p_end_x         the right position of the rectangle to decode (in image coordinates).
  * @param   p_start_y       the up position of the rectangle to decode (in image coordinates).
diff --git a/third_party/libopenjpeg20/opj_config.h b/third_party/libopenjpeg20/opj_config.h
index 7384541..fda1f64 100644
--- a/third_party/libopenjpeg20/opj_config.h
+++ b/third_party/libopenjpeg20/opj_config.h
@@ -13,4 +13,4 @@
 /* Version number. */
 #define OPJ_VERSION_MAJOR 2
 #define OPJ_VERSION_MINOR 3
-#define OPJ_VERSION_BUILD 0
+#define OPJ_VERSION_BUILD 1
diff --git a/third_party/libopenjpeg20/opj_config_private.h b/third_party/libopenjpeg20/opj_config_private.h
index 81b449d..b6986f9 100644
--- a/third_party/libopenjpeg20/opj_config_private.h
+++ b/third_party/libopenjpeg20/opj_config_private.h
@@ -7,7 +7,7 @@
 /* create opj_config_private.h for CMake */
 #define OPJ_HAVE_INTTYPES_H 	1
 
-#define OPJ_PACKAGE_VERSION "2.3.0"
+#define OPJ_PACKAGE_VERSION "2.3.1"
 
 /* Not used by openjp2*/
 /*#define HAVE_MEMORY_H 1*/
diff --git a/third_party/libopenjpeg20/opj_intmath.h b/third_party/libopenjpeg20/opj_intmath.h
index ad13597..754b551 100644
--- a/third_party/libopenjpeg20/opj_intmath.h
+++ b/third_party/libopenjpeg20/opj_intmath.h
@@ -170,7 +170,7 @@
 static INLINE OPJ_UINT32  opj_uint_ceildiv(OPJ_UINT32  a, OPJ_UINT32  b)
 {
     assert(b);
-    return (a + b - 1) / b;
+    return (OPJ_UINT32)(((OPJ_UINT64)a + b - 1) / b);
 }
 
 /**
diff --git a/third_party/libopenjpeg20/pi.c b/third_party/libopenjpeg20/pi.c
index 256fe37..5f3d9ec 100644
--- a/third_party/libopenjpeg20/pi.c
+++ b/third_party/libopenjpeg20/pi.c
@@ -757,6 +757,9 @@
     /* position in x and y of tile */
     OPJ_UINT32 p, q;
 
+    /* non-corrected (in regard to image offset) tile offset */
+    OPJ_UINT32 l_tx0, l_ty0;
+
     /* preconditions */
     assert(p_cp != 00);
     assert(p_image != 00);
@@ -772,14 +775,14 @@
     q = p_tileno / p_cp->tw;
 
     /* find extent of tile */
-    *p_tx0 = opj_int_max((OPJ_INT32)(p_cp->tx0 + p * p_cp->tdx),
-                         (OPJ_INT32)p_image->x0);
-    *p_tx1 = opj_int_min((OPJ_INT32)(p_cp->tx0 + (p + 1) * p_cp->tdx),
-                         (OPJ_INT32)p_image->x1);
-    *p_ty0 = opj_int_max((OPJ_INT32)(p_cp->ty0 + q * p_cp->tdy),
-                         (OPJ_INT32)p_image->y0);
-    *p_ty1 = opj_int_min((OPJ_INT32)(p_cp->ty0 + (q + 1) * p_cp->tdy),
-                         (OPJ_INT32)p_image->y1);
+    l_tx0 = p_cp->tx0 + p *
+            p_cp->tdx; /* can't be greater than p_image->x1 so won't overflow */
+    *p_tx0 = (OPJ_INT32)opj_uint_max(l_tx0, p_image->x0);
+    *p_tx1 = (OPJ_INT32)opj_uint_min(opj_uint_adds(l_tx0, p_cp->tdx), p_image->x1);
+    l_ty0 = p_cp->ty0 + q *
+            p_cp->tdy; /* can't be greater than p_image->y1 so won't overflow */
+    *p_ty0 = (OPJ_INT32)opj_uint_max(l_ty0, p_image->y0);
+    *p_ty1 = (OPJ_INT32)opj_uint_min(opj_uint_adds(l_ty0, p_cp->tdy), p_image->y1);
 
     /* max precision is 0 (can only grow) */
     *p_max_prec = 0;
diff --git a/third_party/libopenjpeg20/t1.c b/third_party/libopenjpeg20/t1.c
index 7674438..f6f7671 100644
--- a/third_party/libopenjpeg20/t1.c
+++ b/third_party/libopenjpeg20/t1.c
@@ -1618,8 +1618,8 @@
         cblk_w = (OPJ_UINT32)(cblk->x1 - cblk->x0);
         cblk_h = (OPJ_UINT32)(cblk->y1 - cblk->y0);
 
-        cblk->decoded_data = (OPJ_INT32*)opj_aligned_malloc(cblk_w * cblk_h * sizeof(
-                                 OPJ_INT32));
+        cblk->decoded_data = (OPJ_INT32*)opj_aligned_malloc(sizeof(OPJ_INT32) *
+                             cblk_w * cblk_h);
         if (cblk->decoded_data == NULL) {
             if (job->p_manager_mutex) {
                 opj_mutex_lock(job->p_manager_mutex);
@@ -1634,7 +1634,7 @@
             return;
         }
         /* Zero-init required */
-        memset(cblk->decoded_data, 0, cblk_w * cblk_h * sizeof(OPJ_INT32));
+        memset(cblk->decoded_data, 0, sizeof(OPJ_INT32) * cblk_w * cblk_h);
     } else if (cblk->decoded_data) {
         /* Not sure if that code path can happen, but better be */
         /* safe than sorry */
@@ -2168,9 +2168,18 @@
                         t1->data = tiledp;
                         t1->data_stride = tile_w;
                         if (tccp->qmfbid == 1) {
+                            /* Do multiplication on unsigned type, even if the
+                             * underlying type is signed, to avoid potential
+                             * int overflow on large value (the output will be
+                             * incorrect in such situation, but whatever...)
+                             * This assumes complement-to-2 signed integer
+                             * representation
+                             * Fixes https://github.com/uclouvain/openjpeg/issues/1053
+                             */
+                            OPJ_UINT32* OPJ_RESTRICT tiledp_u = (OPJ_UINT32*) tiledp;
                             for (j = 0; j < cblk_h; ++j) {
                                 for (i = 0; i < cblk_w; ++i) {
-                                    tiledp[tileIndex] *= (1 << T1_NMSEDEC_FRACBITS);
+                                    tiledp_u[tileIndex] <<= T1_NMSEDEC_FRACBITS;
                                     tileIndex++;
                                 }
                                 tileIndex += tileLineAdvance;
diff --git a/third_party/libopenjpeg20/t2.c b/third_party/libopenjpeg20/t2.c
index 6f956d1..9825118 100644
--- a/third_party/libopenjpeg20/t2.c
+++ b/third_party/libopenjpeg20/t2.c
@@ -667,7 +667,11 @@
     opj_tcd_resolution_t *res = &tilec->resolutions[resno];
 
     opj_bio_t *bio = 00;    /* BIO component */
+#ifdef ENABLE_EMPTY_PACKET_OPTIMIZATION
     OPJ_BOOL packet_empty = OPJ_TRUE;
+#else
+    OPJ_BOOL packet_empty = OPJ_FALSE;
+#endif
 
     /* <SOP 0xff91> */
     if (tcp->csty & J2K_CP_CSTY_SOP) {
@@ -728,6 +732,11 @@
     }
     opj_bio_init_enc(bio, c, length);
 
+#ifdef ENABLE_EMPTY_PACKET_OPTIMIZATION
+    /* WARNING: this code branch is disabled, since it has been reported that */
+    /* such packets cause decoding issues with cinema J2K hardware */
+    /* decoders: https://groups.google.com/forum/#!topic/openjpeg/M7M_fLX_Bco */
+
     /* Check if the packet is empty */
     /* Note: we could also skip that step and always write a packet header */
     band = res->bands;
@@ -755,10 +764,9 @@
             break;
         }
     }
-
+#endif
     opj_bio_write(bio, packet_empty ? 0 : 1, 1);           /* Empty header bit */
 
-
     /* Writing Packet header */
     band = res->bands;
     for (bandno = 0; !packet_empty &&
diff --git a/third_party/libopenjpeg20/tcd.c b/third_party/libopenjpeg20/tcd.c
index 7298fa3..2ae211e 100644
--- a/third_party/libopenjpeg20/tcd.c
+++ b/third_party/libopenjpeg20/tcd.c
@@ -1069,13 +1069,16 @@
                                                           cblkwidthexpn);
                     l_current_precinct->ch = (OPJ_UINT32)((brcblkyend - tlcblkystart) >>
                                                           cblkheightexpn);
+
                     if (l_current_precinct->cw && ((OPJ_UINT32)-1) / l_current_precinct->cw < l_current_precinct->ch) {
                         return OPJ_FALSE;
                     }
                     l_nb_code_blocks = l_current_precinct->cw * l_current_precinct->ch;
                     /*fprintf(stderr, "\t\t\t\t precinct_cw = %d x recinct_ch = %d\n",l_current_precinct->cw, l_current_precinct->ch);      */
-
-                    if (((OPJ_UINT32)-1) / (OPJ_UINT32)sizeof_block < l_nb_code_blocks) {
+                    if ((((OPJ_UINT32) - 1) / (OPJ_UINT32)sizeof_block) <
+                            l_nb_code_blocks) {
+                        opj_event_msg(manager, EVT_ERROR,
+                                      "Size of code block data exceeds system limits\n");
                         return OPJ_FALSE;
                     }
                     l_nb_code_blocks_size = l_nb_code_blocks * (OPJ_UINT32)sizeof_block;
diff --git a/third_party/libopenjpeg20/thread.c b/third_party/libopenjpeg20/thread.c
index af33c2c..f2fca2e 100644
--- a/third_party/libopenjpeg20/thread.c
+++ b/third_party/libopenjpeg20/thread.c
@@ -723,6 +723,8 @@
         tp->worker_threads[i].thread = opj_thread_create(opj_worker_thread_function,
                                        &(tp->worker_threads[i]));
         if (tp->worker_threads[i].thread == NULL) {
+            opj_mutex_destroy(tp->worker_threads[i].mutex);
+            opj_cond_destroy(tp->worker_threads[i].cond);
             tp->worker_threads_count = i;
             bRet = OPJ_FALSE;
             break;
@@ -732,7 +734,7 @@
     /* Wait all threads to be started */
     /* printf("waiting for all threads to be started\n"); */
     opj_mutex_lock(tp->mutex);
-    while (tp->waiting_worker_thread_count < num_threads) {
+    while (tp->waiting_worker_thread_count < tp->worker_threads_count) {
         opj_cond_wait(tp->cond, tp->mutex);
     }
     opj_mutex_unlock(tp->mutex);