Vulnerability: Out-of-bounds accesses in the functions pi_next_lrcp, pi_next_rlcp, pi_next_rpcl, pi_next_pcrl, pi_next_rpcl, and pi_next_cprl in openmj2/pi.c in OpenJPEG through 2.3.0 allow remote attackers to cause a denial of service (application crash).
Vulnerability ID: CVE-2018-20846
CWE: CWE-20
Severity score: 2.9
Project: https://github.com/uclouvain/openjpeg
Published: 2019-06-26
File: src/lib/openmj2/pi.c
Commit message: [MJ2] Avoid index out of bounds access to pi->include[]

Signed-off-by: Young_X <YangX92@hotmail.com>
Commit author: Young_X

Vulnerable version (before fix):
 static opj_bool pi_next_cprl(opj_pi_iterator_t * pi); ========================================================== */  static opj_bool pi_next_lrcp(opj_pi_iterator_t * pi) {     opj_pi_comp_t *comp = NULL; static opj_bool pi_next_lrcp(opj_pi_iterator_t * pi)                 for (pi->precno = pi->poc.precno0; pi->precno < pi->poc.precno1; pi->precno++) {                     index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno *                             pi->step_c + pi->precno * pi->step_p;                     if (!pi->include[index]) {                         pi->include[index] = 1;                         return OPJ_TRUE; static opj_bool pi_next_rlcp(opj_pi_iterator_t * pi)                 for (pi->precno = pi->poc.precno0; pi->precno < pi->poc.precno1; pi->precno++) {                     index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno *                             pi->step_c + pi->precno * pi->step_p;                     if (!pi->include[index]) {                         pi->include[index] = 1;                         return OPJ_TRUE; static opj_bool pi_next_rpcl(opj_pi_iterator_t * pi)                     for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) {                         index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno *                                 pi->step_c + pi->precno * pi->step_p;                         if (!pi->include[index]) {                             pi->include[index] = 1;                             return OPJ_TRUE; static opj_bool pi_next_pcrl(opj_pi_iterator_t * pi)                     for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) {                         index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno *                                 pi->step_c + pi->precno * pi->step_p;                         if (!pi->include[index]) {                             pi->include[index] = 1;                             return OPJ_TRUE; static opj_bool pi_next_cprl(opj_pi_iterator_t * pi)                     for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) {                         index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno *                                 pi->step_c + pi->precno * pi->step_p;                         if (!pi->include[index]) {                             pi->include[index] = 1;                             return OPJ_TRUE;

Fixed version (after fix):
 static opj_bool pi_next_cprl(opj_pi_iterator_t * pi); ========================================================== */  static void opj_pi_emit_error(opj_pi_iterator_t * pi, const char* msg) {     (void)pi;     (void)msg; }  static opj_bool pi_next_lrcp(opj_pi_iterator_t * pi) {     opj_pi_comp_t *comp = NULL; static opj_bool pi_next_lrcp(opj_pi_iterator_t * pi)                 for (pi->precno = pi->poc.precno0; pi->precno < pi->poc.precno1; pi->precno++) {                     index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno *                             pi->step_c + pi->precno * pi->step_p;                     /* Avoids index out of bounds access with include*/                     if (index >= pi->include_size) {                         opj_pi_emit_error(pi, "Invalid access to pi->include");                         return OPJ_FALSE;                     }                     if (!pi->include[index]) {                         pi->include[index] = 1;                         return OPJ_TRUE; static opj_bool pi_next_rlcp(opj_pi_iterator_t * pi)                 for (pi->precno = pi->poc.precno0; pi->precno < pi->poc.precno1; pi->precno++) {                     index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno *                             pi->step_c + pi->precno * pi->step_p;                     /* Avoids index out of bounds access with include*/                     if (index >= pi->include_size) {                         opj_pi_emit_error(pi, "Invalid access to pi->include");                         return OPJ_FALSE;                     }                     if (!pi->include[index]) {                         pi->include[index] = 1;                         return OPJ_TRUE; static opj_bool pi_next_rpcl(opj_pi_iterator_t * pi)                     for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) {                         index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno *                                 pi->step_c + pi->precno * pi->step_p;                         /* Avoids index out of bounds access with include*/                         if (index >= pi->include_size) {                             opj_pi_emit_error(pi, "Invalid access to pi->include");                             return OPJ_FALSE;                         }                         if (!pi->include[index]) {                             pi->include[index] = 1;                             return OPJ_TRUE; static opj_bool pi_next_pcrl(opj_pi_iterator_t * pi)                     for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) {                         index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno *                                 pi->step_c + pi->precno * pi->step_p;                         /* Avoids index out of bounds access with include*/                         if (index >= pi->include_size) {                             opj_pi_emit_error(pi, "Invalid access to pi->include");                             return OPJ_FALSE;                         }                         if (!pi->include[index]) {                             pi->include[index] = 1;                             return OPJ_TRUE; static opj_bool pi_next_cprl(opj_pi_iterator_t * pi)                     for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) {                         index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno *                                 pi->step_c + pi->precno * pi->step_p;                         /* Avoids index out of bounds access with include*/                         if (index >= pi->include_size) {                             opj_pi_emit_error(pi, "Invalid access to pi->include");                             return OPJ_FALSE;                         }                         if (!pi->include[index]) {                             pi->include[index] = 1;                             return OPJ_TRUE;

Patch:
patch: @@ -85,6 +85,12 @@ static opj_bool pi_next_cprl(opj_pi_iterator_t * pi);
 ==========================================================
 */
 
+static void opj_pi_emit_error(opj_pi_iterator_t * pi, const char* msg)
+{
+    (void)pi;
+    (void)msg;
+}
+
 static opj_bool pi_next_lrcp(opj_pi_iterator_t * pi)
 {
     opj_pi_comp_t *comp = NULL;
@@ -114,6 +120,11 @@ static opj_bool pi_next_lrcp(opj_pi_iterator_t * pi)
                 for (pi->precno = pi->poc.precno0; pi->precno < pi->poc.precno1; pi->precno++) {
                     index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno *
                             pi->step_c + pi->precno * pi->step_p;
+                    /* Avoids index out of bounds access with include*/
+                    if (index >= pi->include_size) {
+                        opj_pi_emit_error(pi, "Invalid access to pi->include");
+                        return OPJ_FALSE;
+                    }
                     if (!pi->include[index]) {
                         pi->include[index] = 1;
                         return OPJ_TRUE;
@@ -156,6 +167,11 @@ static opj_bool pi_next_rlcp(opj_pi_iterator_t * pi)
                 for (pi->precno = pi->poc.precno0; pi->precno < pi->poc.precno1; pi->precno++) {
                     index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno *
                             pi->step_c + pi->precno * pi->step_p;
+                    /* Avoids index out of bounds access with include*/
+                    if (index >= pi->include_size) {
+                        opj_pi_emit_error(pi, "Invalid access to pi->include");
+                        return OPJ_FALSE;
+                    }
                     if (!pi->include[index]) {
                         pi->include[index] = 1;
                         return OPJ_TRUE;
@@ -256,6 +272,11 @@ static opj_bool pi_next_rpcl(opj_pi_iterator_t * pi)
                     for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) {
                         index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno *
                                 pi->step_c + pi->precno * pi->step_p;
+                        /* Avoids index out of bounds access with include*/
+                        if (index >= pi->include_size) {
+                            opj_pi_emit_error(pi, "Invalid access to pi->include");
+                            return OPJ_FALSE;
+                        }
                         if (!pi->include[index]) {
                             pi->include[index] = 1;
                             return OPJ_TRUE;
@@ -356,6 +377,11 @@ static opj_bool pi_next_pcrl(opj_pi_iterator_t * pi)
                     for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) {
                         index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno *
                                 pi->step_c + pi->precno * pi->step_p;
+                        /* Avoids index out of bounds access with include*/
+                        if (index >= pi->include_size) {
+                            opj_pi_emit_error(pi, "Invalid access to pi->include");
+                            return OPJ_FALSE;
+                        }
                         if (!pi->include[index]) {
                             pi->include[index] = 1;
                             return OPJ_TRUE;
@@ -454,6 +480,11 @@ static opj_bool pi_next_cprl(opj_pi_iterator_t * pi)
                     for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) {
                         index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno *
                                 pi->step_c + pi->precno * pi->step_p;
+                        /* Avoids index out of bounds access with include*/
+                        if (index >= pi->include_size) {
+                            opj_pi_emit_error(pi, "Invalid access to pi->include");
+                            return OPJ_FALSE;
+                        }
                         if (!pi->include[index]) {
                             pi->include[index] = 1;
                             return OPJ_TRUE;
path: src/lib/openmj2/pi.c