Commit message: Fixed an integer overflow problem in the JPC codec that later resulted
in the use of uninitialized data.
CVE: CVE-2016-10251
CWE: CWE-190
Vulnerability description: Integer overflow in the jpc_pi_nextcprl function in jpc_t2cod.c in JasPer before 1.900.20 allows remote attackers to have unspecified impact via a crafted file, which triggers use of an uninitialized value.

Project: jasper
File: jpc_t2cod.c

jpc_pchg_t *jpc_pchg_copy(jpc_pchg_t *pchg)
{
	jpc_pchg_t *newpchg;
	if (!(newpchg = jas_malloc(sizeof(jpc_pchg_t)))) {
		return 0;
	}
	*newpchg = *pchg;
	return newpchg;
}

Project: jasper
File: jpc_t2cod.c

void jpc_pchg_destroy(jpc_pchg_t *pchg)
{
	jas_free(pchg);
}

Project: jasper
File: jpc_t2cod.c

jpc_pchglist_t *jpc_pchglist_copy(jpc_pchglist_t *pchglist)
{
	jpc_pchglist_t *newpchglist;
	jpc_pchg_t *newpchg;
	int pchgno;
	if (!(newpchglist = jpc_pchglist_create())) {
		return 0;
	}
	for (pchgno = 0; pchgno < pchglist->numpchgs; ++pchgno) {
		if (!(newpchg = jpc_pchg_copy(pchglist->pchgs[pchgno])) ||
		  jpc_pchglist_insert(newpchglist, -1, newpchg)) {
			jpc_pchglist_destroy(newpchglist);
			return 0;
		}
	}
	return newpchglist;
}

Project: jasper
File: jpc_t2cod.c

void jpc_pchglist_destroy(jpc_pchglist_t *pchglist)
{
	int pchgno;
	if (pchglist->pchgs) {
		for (pchgno = 0; pchgno < pchglist->numpchgs; ++pchgno) {
			jpc_pchg_destroy(pchglist->pchgs[pchgno]);
		}
		jas_free(pchglist->pchgs);
	}
	jas_free(pchglist);
}

Project: jasper
File: jpc_t2cod.c

jpc_pchg_t *jpc_pchglist_get(jpc_pchglist_t *pchglist, int pchgno)
{
	return pchglist->pchgs[pchgno];
}

Project: jasper
File: jpc_t2cod.c

int jpc_pchglist_numpchgs(jpc_pchglist_t *pchglist)
{
	return pchglist->numpchgs;
}

Project: jasper
File: jpc_t2cod.c

jpc_pchg_t *jpc_pchglist_remove(jpc_pchglist_t *pchglist, int pchgno)
{
	int i;
	jpc_pchg_t *pchg;
	assert(pchgno < pchglist->numpchgs);
	pchg = pchglist->pchgs[pchgno];
	for (i = pchgno + 1; i < pchglist->numpchgs; ++i) {
		pchglist->pchgs[i - 1] = pchglist->pchgs[i];
	}
	--pchglist->numpchgs;
	return pchg;
}

Project: jasper
File: jpc_t2cod.c

int jpc_pi_addpchg(jpc_pi_t *pi, jpc_pocpchg_t *pchg)
{
	return jpc_pchglist_insert(pi->pchglist, -1, pchg);
}

Project: jasper
File: jpc_t2cod.c

jpc_pi_t *jpc_pi_create0()
{
	jpc_pi_t *pi;
	if (!(pi = jas_malloc(sizeof(jpc_pi_t)))) {
		return 0;
	}
	pi->picomps = 0;
	pi->pchgno = 0;
	if (!(pi->pchglist = jpc_pchglist_create())) {
		jas_free(pi);
		return 0;
	}
	return pi;
}

Project: jasper
File: jpc_t2cod.c

int jpc_pi_init(jpc_pi_t *pi)
{
	int compno;
	int rlvlno;
	int prcno;
	jpc_picomp_t *picomp;
	jpc_pirlvl_t *pirlvl;
	int *prclyrno;

	pi->prgvolfirst = 0;
	pi->valid = 0;
	pi->pktno = -1;
	pi->pchgno = -1;
	pi->pchg = 0;

	for (compno = 0, picomp = pi->picomps; compno < pi->numcomps;
	  ++compno, ++picomp) {
		for (rlvlno = 0, pirlvl = picomp->pirlvls; rlvlno <
		  picomp->numrlvls; ++rlvlno, ++pirlvl) {
			for (prcno = 0, prclyrno = pirlvl->prclyrnos;
			  prcno < pirlvl->numprcs; ++prcno, ++prclyrno) {
				*prclyrno = 0;
			}
		}
	}
	return 0;
}

Project: jasper
File: jpc_t2cod.c

int jpc_pi_next(jpc_pi_t *pi)
{
	jpc_pchg_t *pchg;
	int ret;


	for (;;) {

		pi->valid = false;

		if (!pi->pchg) {
			++pi->pchgno;
			pi->compno = 0;
			pi->rlvlno = 0;
			pi->prcno = 0;
			pi->lyrno = 0;
			pi->prgvolfirst = true;
			if (pi->pchgno < jpc_pchglist_numpchgs(pi->pchglist)) {
				pi->pchg = jpc_pchglist_get(pi->pchglist, pi->pchgno);
			} else if (pi->pchgno == jpc_pchglist_numpchgs(pi->pchglist)) {
				pi->pchg = &pi->defaultpchg;
			} else {
				return 1;
			}
		}

		pchg = pi->pchg;
		switch (pchg->prgord) {
		case JPC_COD_LRCPPRG:
			ret = jpc_pi_nextlrcp(pi);
			break;
		case JPC_COD_RLCPPRG:
			ret = jpc_pi_nextrlcp(pi);
			break;
		case JPC_COD_RPCLPRG:
			ret = jpc_pi_nextrpcl(pi);
			break;
		case JPC_COD_PCRLPRG:
			ret = jpc_pi_nextpcrl(pi);
			break;
		case JPC_COD_CPRLPRG:
			ret = jpc_pi_nextcprl(pi);
			break;
		default:
			ret = -1;
			break;
		}
		if (!ret) {
			pi->valid = true;
			++pi->pktno;
			return 0;
		}
		pi->pchg = 0;
	}
}

Project: jasper
File: jpc_t2cod.c

static int jpc_pi_nextlrcp(register jpc_pi_t *pi)
{
	jpc_pchg_t *pchg;
	int *prclyrno;

	pchg = pi->pchg;
	if (!pi->prgvolfirst) {
		prclyrno = &pi->pirlvl->prclyrnos[pi->prcno];
		goto skip;
	} else {
		pi->prgvolfirst = false;
	}

	for (pi->lyrno = 0; pi->lyrno < pi->numlyrs && pi->lyrno <
	  JAS_CAST(int, pchg->lyrnoend); ++pi->lyrno) {
		for (pi->rlvlno = pchg->rlvlnostart; pi->rlvlno < pi->maxrlvls &&
		  pi->rlvlno < pchg->rlvlnoend; ++pi->rlvlno) {
			for (pi->compno = pchg->compnostart, pi->picomp =
			  &pi->picomps[pi->compno]; pi->compno < pi->numcomps
			  && pi->compno < JAS_CAST(int, pchg->compnoend); ++pi->compno,
			  ++pi->picomp) {
				if (pi->rlvlno >= pi->picomp->numrlvls) {
					continue;
				}
				pi->pirlvl = &pi->picomp->pirlvls[pi->rlvlno];
				for (pi->prcno = 0, prclyrno =
				  pi->pirlvl->prclyrnos; pi->prcno <
				  pi->pirlvl->numprcs; ++pi->prcno,
				  ++prclyrno) {
					if (pi->lyrno >= *prclyrno) {
						*prclyrno = pi->lyrno;
						++(*prclyrno);
						return 0;
					}
skip:
					;
				}
			}
		}
	}
	return 1;
}

Project: jasper
File: jpc_t2cod.c

static void jpc_picomp_destroy(jpc_picomp_t *picomp)
{
	int rlvlno;
	jpc_pirlvl_t *pirlvl;
	if (picomp->pirlvls) {
		for (rlvlno = 0, pirlvl = picomp->pirlvls; rlvlno <
		  picomp->numrlvls; ++rlvlno, ++pirlvl) {
			pirlvl_destroy(pirlvl);
		}
		jas_free(picomp->pirlvls);
	}
}

Project: jasper
File: jpc_t2cod.c

static void pirlvl_destroy(jpc_pirlvl_t *rlvl)
{
	if (rlvl->prclyrnos) {
		jas_free(rlvl->prclyrnos);
	}
}