Commit message: Added fix for CVE-2016-2089.
CVE: CVE-2016-2089
CWE: CWE-20
Vulnerability description: The jas_matrix_clip function in jas_seq.c in JasPer 1.900.1 allows remote attackers to cause a denial of service (invalid read and application crash) via a crafted JPEG 2000 image.

Project: jasper
File: jas_image.c

static jas_image_cmpt_t *jas_image_cmpt_copy(jas_image_cmpt_t *cmpt)
{
	jas_image_cmpt_t *newcmpt;

	if (!(newcmpt = jas_image_cmpt_create0())) {
		return 0;
	}
	newcmpt->tlx_ = cmpt->tlx_;
	newcmpt->tly_ = cmpt->tly_;
	newcmpt->hstep_ = cmpt->hstep_;
	newcmpt->vstep_ = cmpt->vstep_;
	newcmpt->width_ = cmpt->width_;
	newcmpt->height_ = cmpt->height_;
	newcmpt->prec_ = cmpt->prec_;
	newcmpt->sgnd_ = cmpt->sgnd_;
	newcmpt->cps_ = cmpt->cps_;
	newcmpt->type_ = cmpt->type_;
	if (!(newcmpt->stream_ = jas_stream_memopen(0, 0))) {
		return 0;
	}
	if (jas_stream_seek(cmpt->stream_, 0, SEEK_SET)) {
		return 0;
	}
	if (jas_stream_copy(newcmpt->stream_, cmpt->stream_, -1)) {
		return 0;
	}
	if (jas_stream_seek(newcmpt->stream_, 0, SEEK_SET)) {
		return 0;
	}
	return newcmpt;
}

Project: jasper
File: jas_seq.c

int jas_matrix_resize(jas_matrix_t *matrix, int numrows, int numcols)
{
	int size;
	int i;

	size = numrows * numcols;
	if (size > matrix->datasize_ || numrows > matrix->maxrows_) {
		return -1;
	}

	matrix->numrows_ = numrows;
	matrix->numcols_ = numcols;

	for (i = 0; i < numrows; ++i) {
		matrix->rows_[i] = &matrix->data_[numcols * i];
	}

	return 0;
}

Project: jasper
File: jas_seq.c

void jas_matrix_asl(jas_matrix_t *matrix, int n)
{
	int i;
	int j;
	jas_seqent_t *rowstart;
	int rowstep;
	jas_seqent_t *data;

	if (jas_matrix_numrows(matrix) > 0 && jas_matrix_numcols(matrix) > 0) {
		assert(matrix->rows_);
		rowstep = jas_matrix_rowstep(matrix);
		for (i = matrix->numrows_, rowstart = matrix->rows_[0]; i > 0; --i,
		  rowstart += rowstep) {
			for (j = matrix->numcols_, data = rowstart; j > 0; --j,
			  ++data) {
				*data <<= n;
			}
		}
	}
}

Project: jasper
File: jas_seq.c

void jas_matrix_destroy(jas_matrix_t *matrix)
{
	if (matrix->data_) {
		assert(!(matrix->flags_ & JAS_MATRIX_REF));
		jas_free(matrix->data_);
		matrix->data_ = 0;
	}
	if (matrix->rows_) {
		jas_free(matrix->rows_);
		matrix->rows_ = 0;
	}
	jas_free(matrix);
}

Project: jasper
File: jas_seq.c

int jas_matrix_cmp(jas_matrix_t *mat0, jas_matrix_t *mat1)
{
	int i;
	int j;

	if (mat0->numrows_ != mat1->numrows_ || mat0->numcols_ !=
	  mat1->numcols_) {
		return 1;
	}
	for (i = 0; i < mat0->numrows_; i++) {
		for (j = 0; j < mat0->numcols_; j++) {
			if (jas_matrix_get(mat0, i, j) != jas_matrix_get(mat1, i, j)) {
				return 1;
			}
		}
	}
	return 0;
}

Project: jasper
File: jas_seq.c

void jas_matrix_clip(jas_matrix_t *matrix, jas_seqent_t minval, jas_seqent_t maxval)
{
	int i;
	int j;
	jas_seqent_t v;
	jas_seqent_t *rowstart;
	jas_seqent_t *data;
	int rowstep;

	if (jas_matrix_numrows(matrix) > 0 && jas_matrix_numcols(matrix) > 0) {
		assert(matrix->rows_);
		rowstep = jas_matrix_rowstep(matrix);
		for (i = matrix->numrows_, rowstart = matrix->rows_[0]; i > 0; --i,
		  rowstart += rowstep) {
			data = rowstart;
			for (j = matrix->numcols_, data = rowstart; j > 0; --j,
			  ++data) {
				v = *data;
				if (v < minval) {
					*data = minval;
				} else if (v > maxval) {
					*data = maxval;
				}
			}
		}
	}
}

Project: jasper
File: jas_seq.c

jas_seq2d_t *jas_seq2d_copy(jas_seq2d_t *x)
{
	jas_matrix_t *y;
	int i;
	int j;
	y = jas_seq2d_create(jas_seq2d_xstart(x), jas_seq2d_ystart(x), jas_seq2d_xend(x),
	  jas_seq2d_yend(x));
	assert(y);
	for (i = 0; i < x->numrows_; ++i) {
		for (j = 0; j < x->numcols_; ++j) {
			*jas_matrix_getref(y, i, j) = jas_matrix_get(x, i, j);
		}
	}
	return y;
}

Project: jasper
File: jas_image.c

jas_image_t *jas_image_chclrspc(jas_image_t *image, jas_cmprof_t *outprof,
  int intent)
{
	jas_image_t *inimage;
	int minhstep;
	int minvstep;
	int i;
	int j;
	int k;
	int n;
	int hstep;
	int vstep;
	int numinauxchans;
	int numoutauxchans;
	int numinclrchans;
	int numoutclrchans;
	int prec;
	jas_image_t *outimage;
	int cmpttype;
	int numoutchans;
	jas_cmprof_t *inprof;
	jas_cmprof_t *tmpprof;
	jas_image_cmptparm_t cmptparm;
	int width;
	int height;
	jas_cmxform_t *xform;
	jas_cmpixmap_t inpixmap;
	jas_cmpixmap_t outpixmap;
	jas_cmcmptfmt_t *incmptfmts;
	jas_cmcmptfmt_t *outcmptfmts;

#if 0
jas_eprintf("IMAGE\n");
jas_image_dump(image, stderr);
#endif

	if (!(inimage = jas_image_copy(image)))
		goto error;
	image = 0;

	if (!jas_image_ishomosamp(inimage)) {
		minhstep = jas_image_cmpthstep(inimage, 0);
		minvstep = jas_image_cmptvstep(inimage, 0);
		for (i = 1; i < jas_image_numcmpts(inimage); ++i) {
			hstep = jas_image_cmpthstep(inimage, i);
			vstep = jas_image_cmptvstep(inimage, i);
			if (hstep < minhstep)
				minhstep = hstep;
			if (vstep < minvstep)
				minvstep = vstep;
		}
		n = jas_image_numcmpts(inimage);
		for (i = 0; i < n; ++i) {
			cmpttype = jas_image_cmpttype(inimage, i);
			if (jas_image_sampcmpt(inimage, i, i + 1, 0, 0, minhstep, minvstep, jas_image_cmptsgnd(inimage, i), jas_image_cmptprec(inimage, i)))
				goto error;
			jas_image_setcmpttype(inimage, i + 1, cmpttype);
			jas_image_delcmpt(inimage, i);
		}
	}

	width = jas_image_cmptwidth(inimage, 0);
	height = jas_image_cmptheight(inimage, 0);
	hstep = jas_image_cmpthstep(inimage, 0);
	vstep = jas_image_cmptvstep(inimage, 0);

	inprof = jas_image_cmprof(inimage);
	assert(inprof);
	numinclrchans = jas_clrspc_numchans(jas_cmprof_clrspc(inprof));
	numinauxchans = jas_image_numcmpts(inimage) - numinclrchans;
	numoutclrchans = jas_clrspc_numchans(jas_cmprof_clrspc(outprof));
	numoutauxchans = 0;
	numoutchans = numoutclrchans + numoutauxchans;
	prec = 8;

	if (!(outimage = jas_image_create0()))
		goto error;

	/* Create a component for each of the colorants. */
	for (i = 0; i < numoutclrchans; ++i) {
		cmptparm.tlx = 0;
		cmptparm.tly = 0;
		cmptparm.hstep = hstep;
		cmptparm.vstep = vstep;
		cmptparm.width = width;
		cmptparm.height = height;
		cmptparm.prec = prec;
		cmptparm.sgnd = 0;
		if (jas_image_addcmpt(outimage, -1, &cmptparm))
			goto error;
		jas_image_setcmpttype(outimage, i, JAS_IMAGE_CT_COLOR(i));
	}
#if 0
	/* Copy the auxiliary components without modification. */
	for (i = 0; i < jas_image_numcmpts(inimage); ++i) {
		if (!ISCOLOR(jas_image_cmpttype(inimage, i))) {
			jas_image_copycmpt(outimage, -1, inimage, i);
/* XXX - need to specify laydown of component on ref. grid */
		}
	}
#endif

	if (!(tmpprof = jas_cmprof_copy(outprof)))
		goto error;
	assert(!jas_image_cmprof(outimage));
	jas_image_setcmprof(outimage, tmpprof);
	tmpprof = 0;
	jas_image_setclrspc(outimage, jas_cmprof_clrspc(outprof));

	if (!(xform = jas_cmxform_create(inprof, outprof, 0, JAS_CMXFORM_OP_FWD, intent, 0)))
		goto error;

	inpixmap.numcmpts = numinclrchans;
	incmptfmts = malloc(numinclrchans * sizeof(jas_cmcmptfmt_t));
	assert(incmptfmts);
	inpixmap.cmptfmts = incmptfmts;
	for (i = 0; i < numinclrchans; ++i) {
		j = jas_image_getcmptbytype(inimage, JAS_IMAGE_CT_COLOR(i));
		assert(j >= 0);
		if (!(incmptfmts[i].buf = malloc(width * sizeof(long))))
			goto error;
		incmptfmts[i].prec = jas_image_cmptprec(inimage, j);
		incmptfmts[i].sgnd = jas_image_cmptsgnd(inimage, j);
		incmptfmts[i].width = width;
		incmptfmts[i].height = 1;
	}

	outpixmap.numcmpts = numoutclrchans;
	outcmptfmts = malloc(numoutclrchans * sizeof(jas_cmcmptfmt_t));
	assert(outcmptfmts);
	outpixmap.cmptfmts = outcmptfmts;

	for (i = 0; i < numoutclrchans; ++i) {
		j = jas_image_getcmptbytype(outimage, JAS_IMAGE_CT_COLOR(i));
		assert(j >= 0);
		if (!(outcmptfmts[i].buf = malloc(width * sizeof(long))))
			goto error;
		outcmptfmts[i].prec = jas_image_cmptprec(outimage, j);
		outcmptfmts[i].sgnd = jas_image_cmptsgnd(outimage, j);
		outcmptfmts[i].width = width;
		outcmptfmts[i].height = 1;
	}

	for (i = 0; i < height; ++i) {
		for (j = 0; j < numinclrchans; ++j) {
			k = jas_image_getcmptbytype(inimage, JAS_IMAGE_CT_COLOR(j));
			if (jas_image_readcmpt2(inimage, k, 0, i, width, 1, incmptfmts[j].buf))
				goto error;
		}
		jas_cmxform_apply(xform, &inpixmap, &outpixmap);
		for (j = 0; j < numoutclrchans; ++j) {
			k = jas_image_getcmptbytype(outimage, JAS_IMAGE_CT_COLOR(j));
			if (jas_image_writecmpt2(outimage, k, 0, i, width, 1, outcmptfmts[j].buf))
				goto error;
		}
	}

	for (i = 0; i < numoutclrchans; ++i)
		jas_free(outcmptfmts[i].buf);
	jas_free(outcmptfmts);
	for (i = 0; i < numinclrchans; ++i)
		jas_free(incmptfmts[i].buf);
	jas_free(incmptfmts);
	jas_cmxform_destroy(xform);
	jas_image_destroy(inimage);

#if 0
jas_eprintf("INIMAGE\n");
jas_image_dump(inimage, stderr);
jas_eprintf("OUTIMAGE\n");
jas_image_dump(outimage, stderr);
#endif
	return outimage;
error:
	return 0;
}

Project: jasper
File: jas_seq.c

void jas_matrix_asr(jas_matrix_t *matrix, int n)
{
	int i;
	int j;
	jas_seqent_t *rowstart;
	int rowstep;
	jas_seqent_t *data;

	assert(n >= 0);
	if (jas_matrix_numrows(matrix) > 0 && jas_matrix_numcols(matrix) > 0) {
		assert(matrix->rows_);
		rowstep = jas_matrix_rowstep(matrix);
		for (i = matrix->numrows_, rowstart = matrix->rows_[0]; i > 0; --i,
		  rowstart += rowstep) {
			for (j = matrix->numcols_, data = rowstart; j > 0; --j,
			  ++data) {
				*data >>= n;
			}
		}
	}
}

Project: jasper
File: jas_seq.c

void jas_matrix_divpow2(jas_matrix_t *matrix, int n)
{
	int i;
	int j;
	jas_seqent_t *rowstart;
	int rowstep;
	jas_seqent_t *data;

	if (jas_matrix_numrows(matrix) > 0 && jas_matrix_numcols(matrix) > 0) {
		assert(matrix->rows_);
		rowstep = jas_matrix_rowstep(matrix);
		for (i = matrix->numrows_, rowstart = matrix->rows_[0]; i > 0; --i,
		  rowstart += rowstep) {
			for (j = matrix->numcols_, data = rowstart; j > 0; --j,
			  ++data) {
				*data = (*data >= 0) ? ((*data) >> n) :
				  (-((-(*data)) >> n));
			}
		}
	}
}

Project: jasper
File: jas_seq.c

void jas_matrix_setall(jas_matrix_t *matrix, jas_seqent_t val)
{
	int i;
	int j;
	jas_seqent_t *rowstart;
	int rowstep;
	jas_seqent_t *data;

	if (jas_matrix_numrows(matrix) > 0 && jas_matrix_numcols(matrix) > 0) {
		assert(matrix->rows_);
		rowstep = jas_matrix_rowstep(matrix);
		for (i = matrix->numrows_, rowstart = matrix->rows_[0]; i > 0; --i,
		  rowstart += rowstep) {
			for (j = matrix->numcols_, data = rowstart; j > 0; --j,
			  ++data) {
				*data = val;
			}
		}
	}
}

Project: jasper
File: jas_seq.c

jas_matrix_t *jas_matrix_copy(jas_matrix_t *x)
{
	jas_matrix_t *y;
	int i;
	int j;
	y = jas_matrix_create(x->numrows_, x->numcols_);
	for (i = 0; i < x->numrows_; ++i) {
		for (j = 0; j < x->numcols_; ++j) {
			*jas_matrix_getref(y, i, j) = jas_matrix_get(x, i, j);
		}
	}
	return y;
}

Project: jasper
File: jas_image.c

jas_image_t *jas_image_copy(jas_image_t *image)
{
	jas_image_t *newimage;
	int cmptno;

	newimage = jas_image_create0();
	if (jas_image_growcmpts(newimage, image->numcmpts_)) {
		goto error;
	}
	for (cmptno = 0; cmptno < image->numcmpts_; ++cmptno) {
		if (!(newimage->cmpts_[cmptno] = jas_image_cmpt_copy(image->cmpts_[cmptno]))) {
			goto error;
		}
		++newimage->numcmpts_;
	}

	jas_image_setbbox(newimage);

	if (image->cmprof_) {
		if (!(newimage->cmprof_ = jas_cmprof_copy(image->cmprof_)))
			goto error;
	}

	return newimage;
error:
	if (newimage) {
		jas_image_destroy(newimage);
	}
	return 0;
}

Project: jasper
File: jas_image.c

int jas_image_addcmpt(jas_image_t *image, int cmptno,
  jas_image_cmptparm_t *cmptparm)
{
	jas_image_cmpt_t *newcmpt;
	if (cmptno < 0)
		cmptno = image->numcmpts_;
	assert(cmptno >= 0 && cmptno <= image->numcmpts_);
	if (image->numcmpts_ >= image->maxcmpts_) {
		if (jas_image_growcmpts(image, image->maxcmpts_ + 128)) {
			return -1;
		}
	}
	if (!(newcmpt = jas_image_cmpt_create(cmptparm->tlx,
	  cmptparm->tly, cmptparm->hstep, cmptparm->vstep,
	  cmptparm->width, cmptparm->height, cmptparm->prec,
	  cmptparm->sgnd, 1))) {
		return -1;
	}
	if (cmptno < image->numcmpts_) {
		memmove(&image->cmpts_[cmptno + 1], &image->cmpts_[cmptno],
		  (image->numcmpts_ - cmptno) * sizeof(jas_image_cmpt_t *));
	}
	image->cmpts_[cmptno] = newcmpt;
	++image->numcmpts_;

	jas_image_setbbox(image);

	return 0;
}

Project: jasper
File: jas_seq.c

jas_matrix_t *jas_seq2d_input(FILE *in)
{
	jas_matrix_t *matrix;
	int i;
	int j;
	long x;
	int numrows;
	int numcols;
	int xoff;
	int yoff;

	if (fscanf(in, "%d %d", &xoff, &yoff) != 2)
		return 0;
	if (fscanf(in, "%d %d", &numcols, &numrows) != 2)
		return 0;
	if (!(matrix = jas_seq2d_create(xoff, yoff, xoff + numcols, yoff + numrows)))
		return 0;

	if (jas_matrix_numrows(matrix) != numrows || jas_matrix_numcols(matrix) != numcols) {
		abort();
	}

	/* Get matrix data. */
	for (i = 0; i < jas_matrix_numrows(matrix); i++) {
		for (j = 0; j < jas_matrix_numcols(matrix); j++) {
			if (fscanf(in, "%ld", &x) != 1) {
				jas_matrix_destroy(matrix);
				return 0;
			}
			jas_matrix_set(matrix, i, j, JAS_CAST(jas_seqent_t, x));
		}
	}

	return matrix;
}

Project: jasper
File: jas_seq.c

int jas_seq2d_output(jas_matrix_t *matrix, FILE *out)
{
#define MAXLINELEN	80
	int i;
	int j;
	jas_seqent_t x;
	char buf[MAXLINELEN + 1];
	char sbuf[MAXLINELEN + 1];
	int n;

	fprintf(out, "%d %d\n", jas_seq2d_xstart(matrix),
	  jas_seq2d_ystart(matrix));
	fprintf(out, "%d %d\n", jas_matrix_numcols(matrix),
	  jas_matrix_numrows(matrix));

	buf[0] = '\0';
	for (i = 0; i < jas_matrix_numrows(matrix); ++i) {
		for (j = 0; j < jas_matrix_numcols(matrix); ++j) {
			x = jas_matrix_get(matrix, i, j);
			sprintf(sbuf, "%s%4ld", (strlen(buf) > 0) ? " " : "",
			  JAS_CAST(long, x));
			n = strlen(buf);
			if (n + strlen(sbuf) > MAXLINELEN) {
				fputs(buf, out);
				fputs("\n", out);
				buf[0] = '\0';
			}
			strcat(buf, sbuf);
			if (j == jas_matrix_numcols(matrix) - 1) {
				fputs(buf, out);
				fputs("\n", out);
				buf[0] = '\0';
			}
		}
	}
	fputs(buf, out);

	return 0;
}

Project: jasper
File: jas_seq.c

void jas_seq2d_bindsub(jas_matrix_t *s, jas_matrix_t *s1, int xstart, int ystart,
  int xend, int yend)
{
	jas_matrix_bindsub(s, s1, ystart - s1->ystart_, xstart - s1->xstart_,
	  yend - s1->ystart_ - 1, xend - s1->xstart_ - 1);
}