CVE-2017-14039: Out-of-bounds Write (CWE-787)
value: A heap-based buffer overflow was discovered in the opj_t2_encode_packet function in lib/openjp2/t2.c in OpenJPEG 2.2.0. The vulnerability causes an out-of-bounds write, which may lead to remote denial of service or possibly unspecified other impact.
CWE description: The product writes data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 8.8
Published: 2017-08-30T22:29Z
Repository: https://github.com/uclouvain/openjpeg
Language: C
Files changed: src/lib/openjp2/j2k.c, src/lib/openjp2/t2.c
Commit date: 2017-08-16 17:20:29 +0200
Commit message: opj_t2_encode_packet(): fix potential write heap buffer overflow (#992)

Diff: diff --git a/src/lib/openjp2/j2k.c b/src/lib/openjp2/j2k.c
index 16915452e..6c1f55f47 100644
--- a/src/lib/openjp2/j2k.c
+++ b/src/lib/openjp2/j2k.c
@@ -4213,11 +4213,10 @@ static OPJ_BOOL opj_j2k_write_sot(opj_j2k_t *p_j2k,
     assert(p_j2k != 00);
     assert(p_manager != 00);
     assert(p_stream != 00);
 
     OPJ_UNUSED(p_stream);
-    OPJ_UNUSED(p_manager);
 
     if (p_total_data_size < 12) {
         opj_event_msg(p_manager, EVT_ERROR,
                       "Not enough bytes in output buffer to write SOT marker\n");
         return OPJ_FALSE;
@@ -4615,10 +4614,16 @@ static OPJ_BOOL opj_j2k_write_sod(opj_j2k_t *p_j2k,
     assert(p_manager != 00);
     assert(p_stream != 00);
 
     OPJ_UNUSED(p_stream);
 
+    if (p_total_data_size < 4) {
+        opj_event_msg(p_manager, EVT_ERROR,
+                      "Not enough bytes in output buffer to write SOD marker\n");
+        return OPJ_FALSE;
+    }
+
     opj_write_bytes(p_data, J2K_MS_SOD,
                     2);                                 /* SOD */
     p_data += 2;
 
     /* make room for the EOF marker */
diff --git a/src/lib/openjp2/t2.c b/src/lib/openjp2/t2.c
index 9d31acda8..0fd5300c6 100644
--- a/src/lib/openjp2/t2.c
+++ b/src/lib/openjp2/t2.c
@@ -627,10 +627,19 @@ static OPJ_BOOL opj_t2_encode_packet(OPJ_UINT32 tileno,
     opj_bio_t *bio = 00;    /* BIO component */
     OPJ_BOOL packet_empty = OPJ_TRUE;
 
     /* <SOP 0xff91> */
     if (tcp->csty & J2K_CP_CSTY_SOP) {
+        if (length < 6) {
+            if (p_t2_mode == FINAL_PASS) {
+                opj_event_msg(p_manager, EVT_ERROR,
+                              "opj_t2_encode_packet(): only %u bytes remaining in "
+                              "output buffer. %u needed.\n",
+                              length, 6);
+            }
+            return OPJ_FALSE;
+        }
         c[0] = 255;
         c[1] = 145;
         c[2] = 0;
         c[3] = 4;
 #if 0
@@ -815,10 +824,19 @@ static OPJ_BOOL opj_t2_encode_packet(OPJ_UINT32 tileno,
 
     opj_bio_destroy(bio);
 
     /* <EPH 0xff92> */
     if (tcp->csty & J2K_CP_CSTY_EPH) {
+        if (length < 2) {
+            if (p_t2_mode == FINAL_PASS) {
+                opj_event_msg(p_manager, EVT_ERROR,
+                              "opj_t2_encode_packet(): only %u bytes remaining in "
+                              "output buffer. %u needed.\n",
+                              length, 2);
+            }
+            return OPJ_FALSE;
+        }
         c[0] = 255;
         c[1] = 146;
         c += 2;
         length -= 2;
     }

Vulnerable code:     OPJ_UNUSED(p_manager);
Fixed code:     if (p_total_data_size < 4) {
        opj_event_msg(p_manager, EVT_ERROR,
                      "Not enough bytes in output buffer to write SOD marker\n");
        return OPJ_FALSE;
    }

        if (length < 6) {
            if (p_t2_mode == FINAL_PASS) {
                opj_event_msg(p_manager, EVT_ERROR,
                              "opj_t2_encode_packet(): only %u bytes remaining in "
                              "output buffer. %u needed.\n",
                              length, 6);
            }
            return OPJ_FALSE;
        }
        if (length < 2) {
            if (p_t2_mode == FINAL_PASS) {
                opj_event_msg(p_manager, EVT_ERROR,
                              "opj_t2_encode_packet(): only %u bytes remaining in "
                              "output buffer. %u needed.\n",
                              length, 2);
            }
            return OPJ_FALSE;
        }