1 /*
2  * Copyright (c) 1999-2000 Image Power, Inc. and the University of
3  *   British Columbia.
4  * Copyright (c) 2001-2002 Michael David Adams.
5  * All rights reserved.
6  */
7 
8 /* __START_OF_JASPER_LICENSE__
9  *
10  * JasPer License Version 2.0
11  *
12  * Copyright (c) 2001-2006 Michael David Adams
13  * Copyright (c) 1999-2000 Image Power, Inc.
14  * Copyright (c) 1999-2000 The University of British Columbia
15  *
16  * All rights reserved.
17  *
18  * Permission is hereby granted, free of charge, to any person (the
19  * "User") obtaining a copy of this software and associated documentation
20  * files (the "Software"), to deal in the Software without restriction,
21  * including without limitation the rights to use, copy, modify, merge,
22  * publish, distribute, and/or sell copies of the Software, and to permit
23  * persons to whom the Software is furnished to do so, subject to the
24  * following conditions:
25  *
26  * 1.  The above copyright notices and this permission notice (which
27  * includes the disclaimer below) shall be included in all copies or
28  * substantial portions of the Software.
29  *
30  * 2.  The name of a copyright holder shall not be used to endorse or
31  * promote products derived from the Software without specific prior
32  * written permission.
33  *
34  * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS
35  * LICENSE.  NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER
36  * THIS DISCLAIMER.  THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
37  * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
38  * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
39  * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.  IN NO
40  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
41  * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
42  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
43  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
44  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  NO ASSURANCES ARE
45  * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE
46  * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY.
47  * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS
48  * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL
49  * PROPERTY RIGHTS OR OTHERWISE.  AS A CONDITION TO EXERCISING THE RIGHTS
50  * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE
51  * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY.  THE SOFTWARE
52  * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL
53  * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES,
54  * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL
55  * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH
56  * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH,
57  * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH
58  * RISK ACTIVITIES").  THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY
59  * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES.
60  *
61  * __END_OF_JASPER_LICENSE__
62  */
63 
64 /*
65  * JP2 Library
66  *
67  * $Id$
68  */
69 
70 /******************************************************************************\
71 * Includes.
72 \******************************************************************************/
73 
74 #include "jp2_cod.h"
75 
76 #include "jasper/jas_malloc.h"
77 #include "jasper/jas_debug.h"
78 
79 #include <assert.h>
80 #include <string.h>
81 
82 /******************************************************************************\
83 * Function prototypes.
84 \******************************************************************************/
85 
ones(int n)86 static inline uint_fast32_t ones(int n)
87 {
88 	assert(n >= 0);
89 	return (JAS_CAST(uint_fast32_t, 1) << n) - 1;
90 }
91 
92 static const jp2_boxinfo_t *jp2_boxinfolookup(int type);
93 
94 static int jp2_getuint8(jas_stream_t *in, uint_fast8_t *val);
95 static int jp2_getuint16(jas_stream_t *in, uint_fast16_t *val);
96 static int jp2_getuint32(jas_stream_t *in, uint_fast32_t *val);
97 static int jp2_getuint64(jas_stream_t *in, uint_fast64_t *val);
98 static int jp2_putuint8(jas_stream_t *out, uint_fast8_t val);
99 static int jp2_putuint16(jas_stream_t *out, uint_fast16_t val);
100 static int jp2_putuint32(jas_stream_t *out, uint_fast32_t val);
101 static int jp2_putuint64(jas_stream_t *out, uint_fast64_t val);
102 
103 static int jp2_getint(jas_stream_t *in, int s, int n, int_fast32_t *val);
104 
105 static void jp2_box_dump(const jp2_box_t *box, FILE *out);
106 
107 static int jp2_jp_getdata(jp2_box_t *box, jas_stream_t *in);
108 static int jp2_jp_putdata(const jp2_box_t *box, jas_stream_t *out);
109 static int jp2_ftyp_getdata(jp2_box_t *box, jas_stream_t *in);
110 static int jp2_ftyp_putdata(const jp2_box_t *box, jas_stream_t *out);
111 static int jp2_ihdr_getdata(jp2_box_t *box, jas_stream_t *in);
112 static int jp2_ihdr_putdata(const jp2_box_t *box, jas_stream_t *out);
113 static void jp2_bpcc_destroy(jp2_box_t *box);
114 static int jp2_bpcc_getdata(jp2_box_t *box, jas_stream_t *in);
115 static int jp2_bpcc_putdata(const jp2_box_t *box, jas_stream_t *out);
116 static int jp2_colr_getdata(jp2_box_t *box, jas_stream_t *in);
117 static int jp2_colr_putdata(const jp2_box_t *box, jas_stream_t *out);
118 static void jp2_colr_dumpdata(const jp2_box_t *box, FILE *out);
119 static void jp2_colr_destroy(jp2_box_t *box);
120 static void jp2_cdef_destroy(jp2_box_t *box);
121 static int jp2_cdef_getdata(jp2_box_t *box, jas_stream_t *in);
122 static int jp2_cdef_putdata(const jp2_box_t *box, jas_stream_t *out);
123 static void jp2_cdef_dumpdata(const jp2_box_t *box, FILE *out);
124 static void jp2_cmap_destroy(jp2_box_t *box);
125 static int jp2_cmap_getdata(jp2_box_t *box, jas_stream_t *in);
126 static int jp2_cmap_putdata(const jp2_box_t *box, jas_stream_t *out);
127 static void jp2_cmap_dumpdata(const jp2_box_t *box, FILE *out);
128 static void jp2_pclr_destroy(jp2_box_t *box);
129 static int jp2_pclr_getdata(jp2_box_t *box, jas_stream_t *in);
130 static int jp2_pclr_putdata(const jp2_box_t *box, jas_stream_t *out);
131 static void jp2_pclr_dumpdata(const jp2_box_t *box, FILE *out);
132 
133 /******************************************************************************\
134 * Local data.
135 \******************************************************************************/
136 
137 static const jp2_boxinfo_t jp2_boxinfos[] = {
138 	{JP2_BOX_JP, 0, "JP",
139 	  {0, 0, jp2_jp_getdata, jp2_jp_putdata, 0}},
140 	{JP2_BOX_FTYP, 0, "FTYP",
141 	  {0, 0, jp2_ftyp_getdata, jp2_ftyp_putdata, 0}},
142 	{JP2_BOX_JP2H, JP2_BOX_SUPER, "JP2H",
143 	  {0, 0, 0, 0, 0}},
144 	{JP2_BOX_IHDR, 0, "IHDR",
145 	  {0, 0, jp2_ihdr_getdata, jp2_ihdr_putdata, 0}},
146 	{JP2_BOX_BPCC, 0, "BPCC",
147 	  {0, jp2_bpcc_destroy, jp2_bpcc_getdata, jp2_bpcc_putdata, 0}},
148 	{JP2_BOX_COLR, 0, "COLR",
149 	  {0, jp2_colr_destroy, jp2_colr_getdata, jp2_colr_putdata, jp2_colr_dumpdata}},
150 	{JP2_BOX_PCLR, 0, "PCLR",
151 	  {0, jp2_pclr_destroy, jp2_pclr_getdata, jp2_pclr_putdata, jp2_pclr_dumpdata}},
152 	{JP2_BOX_CMAP, 0, "CMAP",
153 	  {0, jp2_cmap_destroy, jp2_cmap_getdata, jp2_cmap_putdata, jp2_cmap_dumpdata}},
154 	{JP2_BOX_CDEF, 0, "CDEF",
155 	  {0, jp2_cdef_destroy, jp2_cdef_getdata, jp2_cdef_putdata, jp2_cdef_dumpdata}},
156 	{JP2_BOX_RES, JP2_BOX_SUPER, "RES",
157 	  {0, 0, 0, 0, 0}},
158 	{JP2_BOX_RESC, 0, "RESC",
159 	  {0, 0, 0, 0, 0}},
160 	{JP2_BOX_RESD, 0, "RESD",
161 	  {0, 0, 0, 0, 0}},
162 	{JP2_BOX_JP2C, JP2_BOX_NODATA, "JP2C",
163 	  {0, 0, 0, 0, 0}},
164 	{JP2_BOX_JP2I, 0, "JP2I",
165 	  {0, 0, 0, 0, 0}},
166 	{JP2_BOX_XML, 0, "XML",
167 	  {0, 0, 0, 0, 0}},
168 	{JP2_BOX_UUID, 0, "UUID",
169 	  {0, 0, 0, 0, 0}},
170 	{JP2_BOX_UINF, JP2_BOX_SUPER, "UINF",
171 	  {0, 0, 0, 0, 0}},
172 	{JP2_BOX_ULST, 0, "ULST",
173 	  {0, 0, 0, 0, 0}},
174 	{JP2_BOX_URL, 0, "URL",
175 	  {0, 0, 0, 0, 0}},
176 	{0, 0, 0, {0, 0, 0, 0, 0}},
177 };
178 
179 static const jp2_boxinfo_t jp2_boxinfo_unk = {
180 	0, 0, "Unknown", {0, 0, 0, 0, 0}
181 };
182 
183 /******************************************************************************\
184 * Box constructor.
185 \******************************************************************************/
186 
jp2_box_create0(void)187 static jp2_box_t *jp2_box_create0(void)
188 {
189 	jp2_box_t *box;
190 	if (!(box = jas_malloc(sizeof(jp2_box_t)))) {
191 		return 0;
192 	}
193 	memset(box, 0, sizeof(jp2_box_t));
194 	// Mark the box data as never having been constructed
195 	// so that we will not errantly attempt to destroy it later.
196 	box->ops = &jp2_boxinfo_unk.ops;
197 	return box;
198 }
199 
jp2_box_create(int type)200 jp2_box_t *jp2_box_create(int type)
201 {
202 	const jp2_boxinfo_t *boxinfo = jp2_boxinfolookup(type);
203 	assert(boxinfo != NULL);
204 	if (boxinfo == &jp2_boxinfo_unk) {
205 		// on error, jp2_boxinfolookup() returns &jp2_boxinfo_unk
206 		return NULL;
207 	}
208 
209 	jp2_box_t *box;
210 	if (!(box = jp2_box_create0())) {
211 		return 0;
212 	}
213 	box->type = type;
214 	box->len = 0;
215 	box->info = boxinfo;
216 	box->ops = &boxinfo->ops;
217 	return box;
218 }
219 
220 /******************************************************************************\
221 * Box destructor.
222 \******************************************************************************/
223 
jp2_box_destroy(jp2_box_t * box)224 void jp2_box_destroy(jp2_box_t *box)
225 {
226 	if (box->ops->destroy) {
227 		(*box->ops->destroy)(box);
228 	}
229 	jas_free(box);
230 }
231 
jp2_bpcc_destroy(jp2_box_t * box)232 static void jp2_bpcc_destroy(jp2_box_t *box)
233 {
234 	jp2_bpcc_t *bpcc = &box->data.bpcc;
235 	if (bpcc->bpcs) {
236 		jas_free(bpcc->bpcs);
237 		bpcc->bpcs = 0;
238 	}
239 }
240 
jp2_cdef_destroy(jp2_box_t * box)241 static void jp2_cdef_destroy(jp2_box_t *box)
242 {
243 	jp2_cdef_t *cdef = &box->data.cdef;
244 	if (cdef->ents) {
245 		jas_free(cdef->ents);
246 		cdef->ents = 0;
247 	}
248 }
249 
250 /******************************************************************************\
251 * Box input.
252 \******************************************************************************/
253 
jp2_box_get(jas_stream_t * in)254 jp2_box_t *jp2_box_get(jas_stream_t *in)
255 {
256 	jp2_box_t *box;
257 	const jp2_boxinfo_t *boxinfo;
258 	jas_stream_t *tmpstream;
259 	uint_fast32_t len;
260 	uint_fast64_t extlen;
261 	bool dataflag;
262 
263 	box = 0;
264 	tmpstream = 0;
265 
266 	if (!(box = jp2_box_create0())) {
267 		goto error;
268 	}
269 	if (jp2_getuint32(in, &len) || jp2_getuint32(in, &box->type)) {
270 		goto error;
271 	}
272 	boxinfo = jp2_boxinfolookup(box->type);
273 	box->info = boxinfo;
274 	box->len = len;
275 	JAS_DBGLOG(10, (
276 	  "preliminary processing of JP2 box: "
277 	  "type=%c%s%c (0x%08x); length=%"PRIuFAST32"\n",
278 	  '"', boxinfo->name, '"', box->type, box->len
279 	  ));
280 	size_t hdrlen;
281 	if (box->len == 1) {
282 		JAS_DBGLOG(10, ("big length\n"));
283 		if (jp2_getuint64(in, &extlen)) {
284 			goto error;
285 		}
286 		if (extlen > 0xffffffffUL) {
287 			jas_eprintf("warning: cannot handle large 64-bit box length\n");
288 			goto error;
289 		}
290 		box->len = extlen;
291 		hdrlen = JP2_BOX_HDRLEN(true);
292 	} else {
293 		hdrlen = JP2_BOX_HDRLEN(false);
294 	}
295 	if (box->len != 0 && box->len < 8) {
296 		goto error;
297 	}
298 	if (box->len > 0x7fffffffUL) {
299 		/* this limit is the largest value which can
300 		   be passed to jas_stream_copy() without
301 		   overflowing */
302 		goto error;
303 	}
304 
305 	dataflag = !(box->info->flags & (JP2_BOX_SUPER | JP2_BOX_NODATA));
306 
307 	if (dataflag) {
308 		if (box->len < hdrlen)
309 			goto error;
310 		box->datalen = box->len - hdrlen;
311 
312 		if (!(tmpstream = jas_stream_memopen(0, 0))) {
313 			goto error;
314 		}
315 		if (jas_stream_copy(tmpstream, in, box->datalen)) {
316 			jas_eprintf("cannot copy box data\n");
317 			goto error;
318 		}
319 		jas_stream_rewind(tmpstream);
320 
321 		// From here onwards, the box data will need to be destroyed.
322 		// So, initialize the box operations.
323 		box->ops = &boxinfo->ops;
324 
325 		if (box->ops->getdata) {
326 			if ((*box->ops->getdata)(box, tmpstream)) {
327 				jas_eprintf("cannot parse box data\n");
328 				goto error;
329 			}
330 		}
331 		jas_stream_close(tmpstream);
332 	}
333 
334 	if (jas_getdbglevel() >= 1) {
335 		jp2_box_dump(box, stderr);
336 	}
337 
338 	return box;
339 
340 error:
341 	if (box) {
342 		jp2_box_destroy(box);
343 	}
344 	if (tmpstream) {
345 		jas_stream_close(tmpstream);
346 	}
347 	return 0;
348 }
349 
jp2_box_dump(const jp2_box_t * box,FILE * out)350 static void jp2_box_dump(const jp2_box_t *box, FILE *out)
351 {
352 	const jp2_boxinfo_t *boxinfo = box->info;
353 	assert(boxinfo);
354 
355 	fprintf(out, "JP2 box: ");
356 	fprintf(out, "type=%c%s%c (0x%08"PRIxFAST32"); length=%"PRIuFAST32"\n", '"',
357 	  boxinfo->name, '"', box->type, box->len);
358 	if (box->ops->dumpdata) {
359 		(*box->ops->dumpdata)(box, out);
360 	}
361 }
362 
jp2_jp_getdata(jp2_box_t * box,jas_stream_t * in)363 static int jp2_jp_getdata(jp2_box_t *box, jas_stream_t *in)
364 {
365 	jp2_jp_t *jp = &box->data.jp;
366 	if (jp2_getuint32(in, &jp->magic)) {
367 		return -1;
368 	}
369 	return 0;
370 }
371 
jp2_ftyp_getdata(jp2_box_t * box,jas_stream_t * in)372 static int jp2_ftyp_getdata(jp2_box_t *box, jas_stream_t *in)
373 {
374 	if (box->datalen < 8)
375 		return -1;
376 
377 	jp2_ftyp_t *ftyp = &box->data.ftyp;
378 	unsigned int i;
379 	if (jp2_getuint32(in, &ftyp->majver) || jp2_getuint32(in, &ftyp->minver)) {
380 		return -1;
381 	}
382 	ftyp->numcompatcodes = (box->datalen - 8) / 4;
383 	if (ftyp->numcompatcodes > JP2_FTYP_MAXCOMPATCODES) {
384 		return -1;
385 	}
386 	for (i = 0; i < ftyp->numcompatcodes; ++i) {
387 		if (jp2_getuint32(in, &ftyp->compatcodes[i])) {
388 			return -1;
389 		}
390 	}
391 	return 0;
392 }
393 
jp2_ihdr_getdata(jp2_box_t * box,jas_stream_t * in)394 static int jp2_ihdr_getdata(jp2_box_t *box, jas_stream_t *in)
395 {
396 	jp2_ihdr_t *ihdr = &box->data.ihdr;
397 	if (jp2_getuint32(in, &ihdr->height) || jp2_getuint32(in, &ihdr->width) ||
398 	  jp2_getuint16(in, &ihdr->numcmpts) || jp2_getuint8(in, &ihdr->bpc) ||
399 	  jp2_getuint8(in, &ihdr->comptype) || jp2_getuint8(in, &ihdr->csunk) ||
400 	  jp2_getuint8(in, &ihdr->ipr)) {
401 		return -1;
402 	}
403 	return 0;
404 }
405 
jp2_bpcc_getdata(jp2_box_t * box,jas_stream_t * in)406 static int jp2_bpcc_getdata(jp2_box_t *box, jas_stream_t *in)
407 {
408 	if (box->datalen > 0xffff)
409 		/* excessive number of components - this is a
410 		   pessimistic limit, because in jp2_ihdr_getdata(),
411 		   it's a 16 bit integer */
412 		return -1;
413 
414 	jp2_bpcc_t *bpcc = &box->data.bpcc;
415 	unsigned int i;
416 	bpcc->bpcs = 0;
417 	bpcc->numcmpts = box->datalen;
418 	if (!(bpcc->bpcs = jas_alloc2(bpcc->numcmpts, sizeof(uint_fast8_t)))) {
419 		return -1;
420 	}
421 	for (i = 0; i < bpcc->numcmpts; ++i) {
422 		if (jp2_getuint8(in, &bpcc->bpcs[i])) {
423 			return -1;
424 		}
425 	}
426 	return 0;
427 }
428 
jp2_colr_dumpdata(const jp2_box_t * box,FILE * out)429 static void jp2_colr_dumpdata(const jp2_box_t *box, FILE *out)
430 {
431 	const jp2_colr_t *colr = &box->data.colr;
432 	fprintf(out, "method=%d; pri=%d; approx=%d\n", (int)colr->method, (int)colr->pri, (int)colr->approx);
433 	switch (colr->method) {
434 	case JP2_COLR_ENUM:
435 		fprintf(out, "csid=%d\n", (int)colr->csid);
436 		break;
437 	case JP2_COLR_ICC:
438 		jas_memdump(out, colr->iccp, colr->iccplen);
439 		break;
440 	}
441 }
442 
jp2_colr_getdata(jp2_box_t * box,jas_stream_t * in)443 static int jp2_colr_getdata(jp2_box_t *box, jas_stream_t *in)
444 {
445 	if (box->datalen < 3)
446 		return -1;
447 
448 	jp2_colr_t *colr = &box->data.colr;
449 	colr->csid = 0;
450 	colr->iccp = 0;
451 	colr->iccplen = 0;
452 
453 	if (jp2_getuint8(in, &colr->method) || jp2_getuint8(in, &colr->pri) ||
454 	  jp2_getuint8(in, &colr->approx)) {
455 		return -1;
456 	}
457 	switch (colr->method) {
458 	case JP2_COLR_ENUM:
459 		if (jp2_getuint32(in, &colr->csid)) {
460 			return -1;
461 		}
462 		break;
463 	case JP2_COLR_ICC:
464 		colr->iccplen = box->datalen - 3;
465 		if (colr->iccplen > 1024 * 1024)
466 			/* refuse to read ICC profiles larger than 1
467 			   MB (I have no idea how large ICC profiles
468 			   can get, but I believe this limit might be
469 			   very pessimistic and should be lowered
470 			   further) */
471 			return -1;
472 		if (!(colr->iccp = jas_alloc2(colr->iccplen, sizeof(uint_fast8_t)))) {
473 			return -1;
474 		}
475 		if (jas_stream_read(in, colr->iccp, colr->iccplen) != colr->iccplen) {
476 			return -1;
477 		}
478 		break;
479 	}
480 	return 0;
481 }
482 
jp2_cdef_dumpdata(const jp2_box_t * box,FILE * out)483 static void jp2_cdef_dumpdata(const jp2_box_t *box, FILE *out)
484 {
485 	const jp2_cdef_t *cdef = &box->data.cdef;
486 	unsigned int i;
487 	for (i = 0; i < cdef->numchans; ++i) {
488 		fprintf(out,
489 		  "channo=%"PRIuFAST16"; type=%"PRIuFAST16"; assoc=%"PRIuFAST16"\n",
490 		  cdef->ents[i].channo, cdef->ents[i].type, cdef->ents[i].assoc);
491 	}
492 }
493 
jp2_colr_destroy(jp2_box_t * box)494 static void jp2_colr_destroy(jp2_box_t *box)
495 {
496 	jp2_colr_t *colr = &box->data.colr;
497 	if (colr->iccp) {
498 		jas_free(colr->iccp);
499 	}
500 }
501 
jp2_cdef_getdata(jp2_box_t * box,jas_stream_t * in)502 static int jp2_cdef_getdata(jp2_box_t *box, jas_stream_t *in)
503 {
504 	jp2_cdef_t *cdef = &box->data.cdef;
505 	jp2_cdefchan_t *chan;
506 	unsigned int channo;
507 	cdef->ents = 0;
508 	if (jp2_getuint16(in, &cdef->numchans)) {
509 		return -1;
510 	}
511 	if (!(cdef->ents = jas_alloc2(cdef->numchans, sizeof(jp2_cdefchan_t)))) {
512 		return -1;
513 	}
514 	for (channo = 0; channo < cdef->numchans; ++channo) {
515 		chan = &cdef->ents[channo];
516 		if (jp2_getuint16(in, &chan->channo) || jp2_getuint16(in, &chan->type) ||
517 		  jp2_getuint16(in, &chan->assoc)) {
518 			return -1;
519 		}
520 	}
521 	return 0;
522 }
523 
524 /******************************************************************************\
525 * Box output.
526 \******************************************************************************/
527 
jp2_box_put(jp2_box_t * box,jas_stream_t * out)528 int jp2_box_put(jp2_box_t *box, jas_stream_t *out)
529 {
530 	jas_stream_t *tmpstream;
531 	bool extlen;
532 	bool dataflag;
533 
534 	tmpstream = 0;
535 
536 	dataflag = !(box->info->flags & (JP2_BOX_SUPER | JP2_BOX_NODATA));
537 
538 	if (dataflag) {
539 		if (!(tmpstream = jas_stream_memopen(0, 0))) {
540 			goto error;
541 		}
542 		if (box->ops->putdata) {
543 			if ((*box->ops->putdata)(box, tmpstream)) {
544 				goto error;
545 			}
546 		}
547 		box->len = jas_stream_tell(tmpstream) + JP2_BOX_HDRLEN(false);
548 		jas_stream_rewind(tmpstream);
549 	}
550 	extlen = (box->len >= (((uint_fast64_t)1) << 32)) != 0;
551 	if (jp2_putuint32(out, extlen ? 1 : box->len)) {
552 		goto error;
553 	}
554 	if (jp2_putuint32(out, box->type)) {
555 		goto error;
556 	}
557 	if (extlen) {
558 		if (jp2_putuint64(out, box->len)) {
559 			goto error;
560 		}
561 	}
562 
563 	if (dataflag) {
564 		if (jas_stream_copy(out, tmpstream, box->len -
565 		  JP2_BOX_HDRLEN(false))) {
566 			jas_eprintf("cannot copy box data\n");
567 			goto error;
568 		}
569 		jas_stream_close(tmpstream);
570 	}
571 
572 	return 0;
573 
574 error:
575 
576 	if (tmpstream) {
577 		jas_stream_close(tmpstream);
578 	}
579 	return -1;
580 }
581 
jp2_jp_putdata(const jp2_box_t * box,jas_stream_t * out)582 static int jp2_jp_putdata(const jp2_box_t *box, jas_stream_t *out)
583 {
584 	const jp2_jp_t *jp = &box->data.jp;
585 	if (jp2_putuint32(out, jp->magic)) {
586 		return -1;
587 	}
588 	return 0;
589 }
590 
jp2_ftyp_putdata(const jp2_box_t * box,jas_stream_t * out)591 static int jp2_ftyp_putdata(const jp2_box_t *box, jas_stream_t *out)
592 {
593 	const jp2_ftyp_t *ftyp = &box->data.ftyp;
594 	unsigned int i;
595 	if (jp2_putuint32(out, ftyp->majver) || jp2_putuint32(out, ftyp->minver)) {
596 		return -1;
597 	}
598 	for (i = 0; i < ftyp->numcompatcodes; ++i) {
599 		if (jp2_putuint32(out, ftyp->compatcodes[i])) {
600 			return -1;
601 		}
602 	}
603 	return 0;
604 }
605 
jp2_ihdr_putdata(const jp2_box_t * box,jas_stream_t * out)606 static int jp2_ihdr_putdata(const jp2_box_t *box, jas_stream_t *out)
607 {
608 	const jp2_ihdr_t *ihdr = &box->data.ihdr;
609 	if (jp2_putuint32(out, ihdr->height) || jp2_putuint32(out, ihdr->width) ||
610 	  jp2_putuint16(out, ihdr->numcmpts) || jp2_putuint8(out, ihdr->bpc) ||
611 	  jp2_putuint8(out, ihdr->comptype) || jp2_putuint8(out, ihdr->csunk) ||
612 	  jp2_putuint8(out, ihdr->ipr)) {
613 		return -1;
614 	}
615 	return 0;
616 }
617 
jp2_bpcc_putdata(const jp2_box_t * box,jas_stream_t * out)618 static int jp2_bpcc_putdata(const jp2_box_t *box, jas_stream_t *out)
619 {
620 	const jp2_bpcc_t *bpcc = &box->data.bpcc;
621 	unsigned int i;
622 	for (i = 0; i < bpcc->numcmpts; ++i) {
623 		if (jp2_putuint8(out, bpcc->bpcs[i])) {
624 			return -1;
625 		}
626 	}
627 	return 0;
628 }
629 
jp2_colr_putdata(const jp2_box_t * box,jas_stream_t * out)630 static int jp2_colr_putdata(const jp2_box_t *box, jas_stream_t *out)
631 {
632 	const jp2_colr_t *colr = &box->data.colr;
633 	if (jp2_putuint8(out, colr->method) || jp2_putuint8(out, colr->pri) ||
634 	  jp2_putuint8(out, colr->approx)) {
635 		return -1;
636 	}
637 	switch (colr->method) {
638 	case JP2_COLR_ENUM:
639 		if (jp2_putuint32(out, colr->csid)) {
640 			return -1;
641 		}
642 		break;
643 	case JP2_COLR_ICC:
644 		if (jas_stream_write(out, colr->iccp, colr->iccplen) != colr->iccplen)
645 			return -1;
646 		break;
647 	}
648 	return 0;
649 }
650 
jp2_cdef_putdata(const jp2_box_t * box,jas_stream_t * out)651 static int jp2_cdef_putdata(const jp2_box_t *box, jas_stream_t *out)
652 {
653 	const jp2_cdef_t *cdef = &box->data.cdef;
654 	unsigned int i;
655 
656 	if (jp2_putuint16(out, cdef->numchans)) {
657 		return -1;
658 	}
659 
660 	for (i = 0; i < cdef->numchans; ++i) {
661 		const jp2_cdefchan_t *ent = &cdef->ents[i];
662 		if (jp2_putuint16(out, ent->channo) ||
663 		  jp2_putuint16(out, ent->type) ||
664 		  jp2_putuint16(out, ent->assoc)) {
665 			return -1;
666 		}
667 	}
668 	return 0;
669 }
670 
671 /******************************************************************************\
672 * Input operations for primitive types.
673 \******************************************************************************/
674 
jp2_getuint8(jas_stream_t * in,uint_fast8_t * val)675 static int jp2_getuint8(jas_stream_t *in, uint_fast8_t *val)
676 {
677 	int c;
678 	if ((c = jas_stream_getc(in)) == EOF) {
679 		return -1;
680 	}
681 	if (val) {
682 		*val = c;
683 	}
684 	return 0;
685 }
686 
jp2_getuint16(jas_stream_t * in,uint_fast16_t * val)687 static int jp2_getuint16(jas_stream_t *in, uint_fast16_t *val)
688 {
689 	jas_uchar buffer[2];
690 	if (jas_stream_read(in, buffer, sizeof(buffer)) != sizeof(buffer))
691 		return -1;
692 	*val = (uint_fast16_t)buffer[0] << 8 | (uint_fast16_t)buffer[1];
693 	return 0;
694 }
695 
jp2_getuint32(jas_stream_t * in,uint_fast32_t * val)696 static int jp2_getuint32(jas_stream_t *in, uint_fast32_t *val)
697 {
698 	jas_uchar buffer[4];
699 	if (jas_stream_read(in, buffer, sizeof(buffer)) != sizeof(buffer))
700 		return -1;
701 	*val = (uint_fast32_t)buffer[0] << 24 | (uint_fast32_t)buffer[1] << 16
702 		| (uint_fast32_t)buffer[2] << 8 | (uint_fast32_t)buffer[3];
703 	return 0;
704 }
705 
jp2_getuint64(jas_stream_t * in,uint_fast64_t * val)706 static int jp2_getuint64(jas_stream_t *in, uint_fast64_t *val)
707 {
708 	uint_fast64_t tmpval;
709 	int i;
710 	int c;
711 
712 	tmpval = 0;
713 	for (i = 0; i < 8; ++i) {
714 		tmpval <<= 8;
715 		if ((c = jas_stream_getc(in)) == EOF) {
716 			return -1;
717 		}
718 		tmpval |= (c & 0xff);
719 	}
720 	*val = tmpval;
721 
722 	return 0;
723 }
724 
725 /******************************************************************************\
726 * Output operations for primitive types.
727 \******************************************************************************/
728 
jp2_putuint8(jas_stream_t * out,uint_fast8_t val)729 static int jp2_putuint8(jas_stream_t *out, uint_fast8_t val)
730 {
731 	if (jas_stream_putc(out, val & 0xff) == EOF) {
732 		return -1;
733 	}
734 	return 0;
735 }
736 
jp2_putuint16(jas_stream_t * out,uint_fast16_t val)737 static int jp2_putuint16(jas_stream_t *out, uint_fast16_t val)
738 {
739 	if (jas_stream_putc(out, (val >> 8) & 0xff) == EOF ||
740 	  jas_stream_putc(out, val & 0xff) == EOF) {
741 		return -1;
742 	}
743 	return 0;
744 }
745 
jp2_putuint32(jas_stream_t * out,uint_fast32_t val)746 static int jp2_putuint32(jas_stream_t *out, uint_fast32_t val)
747 {
748 	if (jas_stream_putc(out, (val >> 24) & 0xff) == EOF ||
749 	  jas_stream_putc(out, (val >> 16) & 0xff) == EOF ||
750 	  jas_stream_putc(out, (val >> 8) & 0xff) == EOF ||
751 	  jas_stream_putc(out, val & 0xff) == EOF) {
752 		return -1;
753 	}
754 	return 0;
755 }
756 
jp2_putuint64(jas_stream_t * out,uint_fast64_t val)757 static int jp2_putuint64(jas_stream_t *out, uint_fast64_t val)
758 {
759 	if (jp2_putuint32(out, (val >> 32) & 0xffffffffUL) ||
760 	  jp2_putuint32(out, val & 0xffffffffUL)) {
761 		return -1;
762 	}
763 	return 0;
764 }
765 
766 /******************************************************************************\
767 * Miscellaneous code.
768 \******************************************************************************/
769 
jp2_boxinfolookup(int type)770 static const jp2_boxinfo_t *jp2_boxinfolookup(int type)
771 {
772 	const jp2_boxinfo_t *boxinfo;
773 	for (boxinfo = jp2_boxinfos; boxinfo->name; ++boxinfo) {
774 		if (boxinfo->type == type) {
775 			return boxinfo;
776 		}
777 	}
778 	return &jp2_boxinfo_unk;
779 }
780 
781 
782 
783 
784 
jp2_cmap_destroy(jp2_box_t * box)785 static void jp2_cmap_destroy(jp2_box_t *box)
786 {
787 	jp2_cmap_t *cmap = &box->data.cmap;
788 	if (cmap->ents) {
789 		jas_free(cmap->ents);
790 	}
791 }
792 
jp2_cmap_getdata(jp2_box_t * box,jas_stream_t * in)793 static int jp2_cmap_getdata(jp2_box_t *box, jas_stream_t *in)
794 {
795 	jp2_cmap_t *cmap = &box->data.cmap;
796 	jp2_cmapent_t *ent;
797 	unsigned int i;
798 	cmap->ents = 0;
799 
800 	cmap->numchans = (box->datalen) / 4;
801 	if (cmap->numchans > 0xff)
802 		/* excessive number of channels - this is a
803 		   pessimistic limit, because in jp2_pclr_getdata(),
804 		   it's a 8 bit integer */
805 		return -1;
806 
807 	if (!(cmap->ents = jas_alloc2(cmap->numchans, sizeof(jp2_cmapent_t)))) {
808 		return -1;
809 	}
810 	for (i = 0; i < cmap->numchans; ++i) {
811 		ent = &cmap->ents[i];
812 		if (jp2_getuint16(in, &ent->cmptno) ||
813 		  jp2_getuint8(in, &ent->map) ||
814 		  jp2_getuint8(in, &ent->pcol)) {
815 			return -1;
816 		}
817 	}
818 
819 	return 0;
820 }
821 
jp2_cmap_putdata(const jp2_box_t * box,jas_stream_t * out)822 static int jp2_cmap_putdata(const jp2_box_t *box, jas_stream_t *out)
823 {
824 	/* Eliminate compiler warning about unused variables. */
825 	(void)box;
826 	(void)out;
827 
828 	return -1;
829 }
830 
jp2_cmap_dumpdata(const jp2_box_t * box,FILE * out)831 static void jp2_cmap_dumpdata(const jp2_box_t *box, FILE *out)
832 {
833 	const jp2_cmap_t *cmap = &box->data.cmap;
834 	unsigned int i;
835 	fprintf(out, "numchans = %d\n", (int) cmap->numchans);
836 	for (i = 0; i < cmap->numchans; ++i) {
837 		const jp2_cmapent_t *ent = &cmap->ents[i];
838 		fprintf(out, "cmptno=%d; map=%d; pcol=%d\n",
839 		  (int) ent->cmptno, (int) ent->map, (int) ent->pcol);
840 	}
841 }
842 
jp2_pclr_destroy(jp2_box_t * box)843 static void jp2_pclr_destroy(jp2_box_t *box)
844 {
845 	jp2_pclr_t *pclr = &box->data.pclr;
846 	if (pclr->lutdata) {
847 		jas_free(pclr->lutdata);
848 	}
849 	if (pclr->bpc)
850 		jas_free(pclr->bpc);
851 }
852 
jp2_pclr_getdata(jp2_box_t * box,jas_stream_t * in)853 static int jp2_pclr_getdata(jp2_box_t *box, jas_stream_t *in)
854 {
855 	jp2_pclr_t *pclr = &box->data.pclr;
856 	int lutsize;
857 	unsigned int i;
858 	unsigned int j;
859 	int_fast32_t x;
860 
861 	pclr->lutdata = 0;
862 	pclr->bpc = 0;
863 
864 	if (jp2_getuint16(in, &pclr->numlutents) ||
865 	  jp2_getuint8(in, &pclr->numchans)) {
866 		return -1;
867 	}
868 
869 	// verify in range data as per I.5.3.4 - Palette box
870 	if (pclr->numchans < 1 || pclr->numlutents < 1 || pclr->numlutents > 1024) {
871 		return -1;
872 	}
873 
874 	lutsize = pclr->numlutents * pclr->numchans;
875 	if (!(pclr->lutdata = jas_alloc2(lutsize, sizeof(int_fast32_t)))) {
876 		return -1;
877 	}
878 	if (!(pclr->bpc = jas_alloc2(pclr->numchans, sizeof(uint_fast8_t)))) {
879 		return -1;
880 	}
881 	for (i = 0; i < pclr->numchans; ++i) {
882 		if (jp2_getuint8(in, &pclr->bpc[i])) {
883 			return -1;
884 		}
885 	}
886 	for (i = 0; i < pclr->numlutents; ++i) {
887 		for (j = 0; j < pclr->numchans; ++j) {
888 			if (jp2_getint(in, (pclr->bpc[j] & 0x80) != 0,
889 			  (pclr->bpc[j] & 0x7f) + 1, &x)) {
890 				return -1;
891 			}
892 			pclr->lutdata[i * pclr->numchans + j] = x;
893 		}
894 	}
895 	return 0;
896 }
897 
jp2_pclr_putdata(const jp2_box_t * box,jas_stream_t * out)898 static int jp2_pclr_putdata(const jp2_box_t *box, jas_stream_t *out)
899 {
900 #if 0
901 	const jp2_pclr_t *pclr = &box->data.pclr;
902 #endif
903 	/* Eliminate warning about unused variable. */
904 	(void)box;
905 	(void)out;
906 	return -1;
907 }
908 
jp2_pclr_dumpdata(const jp2_box_t * box,FILE * out)909 static void jp2_pclr_dumpdata(const jp2_box_t *box, FILE *out)
910 {
911 	const jp2_pclr_t *pclr = &box->data.pclr;
912 	unsigned int i;
913 	int j;
914 	fprintf(out, "numents=%d; numchans=%d\n", (int) pclr->numlutents,
915 	  (int) pclr->numchans);
916 	for (i = 0; i < pclr->numlutents; ++i) {
917 		for (j = 0; j < pclr->numchans; ++j) {
918 			fprintf(out, "LUT[%d][%d]=%"PRIiFAST32"\n", i, j,
919 			  pclr->lutdata[i * pclr->numchans + j]);
920 		}
921 	}
922 }
923 
jp2_getint(jas_stream_t * in,int s,int n,int_fast32_t * val)924 static int jp2_getint(jas_stream_t *in, int s, int n, int_fast32_t *val)
925 {
926 	int c;
927 	int i;
928 	uint_fast32_t v;
929 	int m;
930 
931 	m = (n + 7) / 8;
932 
933 	// Ensure that the integer to be read has a valid size.
934 	if (n < 0 || n > 32) {
935 		jas_eprintf("jp2_getint: invalid integer size (%d bits)\n", n);
936 		return -1;
937 	}
938 
939 	v = 0;
940 	for (i = 0; i < m; ++i) {
941 		if ((c = jas_stream_getc(in)) == EOF) {
942 			return -1;
943 		}
944 		v = (v << 8) | c;
945 	}
946 	v &= ones(n);
947 	if (s) {
948 		int sb;
949 		sb = v & (JAS_CAST(uint_fast32_t, 1) << (8 * m - 1));
950 		*val = ((~v) + 1) & ones(8 * m);
951 		if (sb) {
952 			*val = -*val;
953 		}
954 	} else {
955 		*val = v;
956 	}
957 
958 	return 0;
959 }
960 
jp2_cdef_lookup(jp2_cdef_t * cdef,int channo)961 const jp2_cdefchan_t *jp2_cdef_lookup(jp2_cdef_t *cdef, int channo)
962 {
963 	unsigned int i;
964 	jp2_cdefchan_t *cdefent;
965 	for (i = 0; i < cdef->numchans; ++i) {
966 		cdefent = &cdef->ents[i];
967 		if (cdefent->channo == JAS_CAST(unsigned int, channo)) {
968 			return cdefent;
969 		}
970 	}
971 	return 0;
972 }
973