1 /*
2  * Copyright (c) 2010, Andrey Kiselev <dron@ak4719.spb.edu>
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and
5  * its documentation for any purpose is hereby granted without fee, provided
6  * that (i) the above copyright notices and this permission notice appear in
7  * all copies of the software and related documentation, and (ii) the names of
8  * Sam Leffler and Silicon Graphics may not be used in any advertising or
9  * publicity relating to the software without the specific, prior written
10  * permission of Sam Leffler and Silicon Graphics.
11  *
12  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
13  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
14  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
15  *
16  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
17  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
18  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
19  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
20  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
21  * OF THIS SOFTWARE.
22  */
23 
24 #include "tiffiop.h"
25 #ifdef LZMA_SUPPORT
26 /*
27  * TIFF Library.
28  *
29  * LZMA2 Compression Support
30  *
31  * You need an LZMA2 SDK to link with. See http://tukaani.org/xz/ for details.
32  *
33  * The codec is derived from ZLIB codec (tif_zip.c).
34  */
35 
36 #include "tif_predict.h"
37 #include "lzma.h"
38 
39 #include <stdio.h>
40 
41 /*
42  * State block for each open TIFF file using LZMA2 compression/decompression.
43  */
44 typedef struct {
45 	TIFFPredictorState predict;
46         lzma_stream	stream;
47 	lzma_filter	filters[LZMA_FILTERS_MAX + 1];
48 	lzma_options_delta opt_delta;		/* delta filter options */
49 	lzma_options_lzma opt_lzma;		/* LZMA2 filter options */
50 	int             preset;			/* compression level */
51 	lzma_check	check;			/* type of the integrity check */
52 	int             state;			/* state flags */
53 #define LSTATE_INIT_DECODE 0x01
54 #define LSTATE_INIT_ENCODE 0x02
55 
56 	TIFFVGetMethod  vgetparent;            /* super-class method */
57 	TIFFVSetMethod  vsetparent;            /* super-class method */
58 } LZMAState;
59 
60 #define LState(tif)             ((LZMAState*) (tif)->tif_data)
61 #define DecoderState(tif)       LState(tif)
62 #define EncoderState(tif)       LState(tif)
63 
64 static int LZMAEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s);
65 static int LZMADecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s);
66 
67 static const char *
LZMAStrerror(lzma_ret ret)68 LZMAStrerror(lzma_ret ret)
69 {
70 	switch (ret) {
71 		case LZMA_OK:
72 		    return "operation completed successfully";
73 		case LZMA_STREAM_END:
74 		    return "end of stream was reached";
75 		case LZMA_NO_CHECK:
76 		    return "input stream has no integrity check";
77 		case LZMA_UNSUPPORTED_CHECK:
78 		    return "cannot calculate the integrity check";
79 		case LZMA_GET_CHECK:
80 		    return "integrity check type is now available";
81 		case LZMA_MEM_ERROR:
82 		    return "cannot allocate memory";
83 		case LZMA_MEMLIMIT_ERROR:
84 		    return "memory usage limit was reached";
85 		case LZMA_FORMAT_ERROR:
86 		    return "file format not recognized";
87 		case LZMA_OPTIONS_ERROR:
88 		    return "invalid or unsupported options";
89 		case LZMA_DATA_ERROR:
90 		    return "data is corrupt";
91 		case LZMA_BUF_ERROR:
92 		    return "no progress is possible (stream is truncated or corrupt)";
93 		case LZMA_PROG_ERROR:
94 		    return "programming error";
95 		default:
96 		    return "unidentified liblzma error";
97 	}
98 }
99 
100 static int
LZMAFixupTags(TIFF * tif)101 LZMAFixupTags(TIFF* tif)
102 {
103 	(void) tif;
104 	return 1;
105 }
106 
107 static int
LZMASetupDecode(TIFF * tif)108 LZMASetupDecode(TIFF* tif)
109 {
110 	LZMAState* sp = DecoderState(tif);
111 
112 	assert(sp != NULL);
113 
114         /* if we were last encoding, terminate this mode */
115 	if (sp->state & LSTATE_INIT_ENCODE) {
116 	    lzma_end(&sp->stream);
117 	    sp->state = 0;
118 	}
119 
120 	sp->state |= LSTATE_INIT_DECODE;
121 	return 1;
122 }
123 
124 /*
125  * Setup state for decoding a strip.
126  */
127 static int
LZMAPreDecode(TIFF * tif,uint16 s)128 LZMAPreDecode(TIFF* tif, uint16 s)
129 {
130 	static const char module[] = "LZMAPreDecode";
131 	LZMAState* sp = DecoderState(tif);
132 	lzma_ret ret;
133 
134 	(void) s;
135 	assert(sp != NULL);
136 
137 	if( (sp->state & LSTATE_INIT_DECODE) == 0 )
138             tif->tif_setupdecode(tif);
139 
140 	sp->stream.next_in = tif->tif_rawdata;
141 	sp->stream.avail_in = (size_t) tif->tif_rawcc;
142 	if ((tmsize_t)sp->stream.avail_in != tif->tif_rawcc) {
143 		TIFFErrorExt(tif->tif_clientdata, module,
144 			     "Liblzma cannot deal with buffers this size");
145 		return 0;
146 	}
147 
148 	/*
149 	 * Disable memory limit when decoding. UINT64_MAX is a flag to disable
150 	 * the limit, we are passing (uint64_t)-1 which should be the same.
151 	 */
152 	ret = lzma_stream_decoder(&sp->stream, (uint64_t)-1, 0);
153 	if (ret != LZMA_OK) {
154 		TIFFErrorExt(tif->tif_clientdata, module,
155 			     "Error initializing the stream decoder, %s",
156 			     LZMAStrerror(ret));
157 		return 0;
158 	}
159 	return 1;
160 }
161 
162 static int
LZMADecode(TIFF * tif,uint8 * op,tmsize_t occ,uint16 s)163 LZMADecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
164 {
165 	static const char module[] = "LZMADecode";
166 	LZMAState* sp = DecoderState(tif);
167 
168 	(void) s;
169 	assert(sp != NULL);
170 	assert(sp->state == LSTATE_INIT_DECODE);
171 
172         sp->stream.next_in = tif->tif_rawcp;
173         sp->stream.avail_in = (size_t) tif->tif_rawcc;
174 
175 	sp->stream.next_out = op;
176 	sp->stream.avail_out = (size_t) occ;
177 	if ((tmsize_t)sp->stream.avail_out != occ) {
178 		TIFFErrorExt(tif->tif_clientdata, module,
179 			     "Liblzma cannot deal with buffers this size");
180 		return 0;
181 	}
182 
183 	do {
184 		/*
185 		 * Save the current stream state to properly recover from the
186 		 * decoding errors later.
187 		 */
188 		const uint8_t *next_in = sp->stream.next_in;
189 		size_t avail_in = sp->stream.avail_in;
190 
191 		lzma_ret ret = lzma_code(&sp->stream, LZMA_RUN);
192 		if (ret == LZMA_STREAM_END)
193 			break;
194 		if (ret == LZMA_MEMLIMIT_ERROR) {
195 			lzma_ret r = lzma_stream_decoder(&sp->stream,
196 							 lzma_memusage(&sp->stream), 0);
197 			if (r != LZMA_OK) {
198 				TIFFErrorExt(tif->tif_clientdata, module,
199 					     "Error initializing the stream decoder, %s",
200 					     LZMAStrerror(r));
201 				break;
202 			}
203 			sp->stream.next_in = next_in;
204 			sp->stream.avail_in = avail_in;
205 			continue;
206 		}
207 		if (ret != LZMA_OK) {
208 			TIFFErrorExt(tif->tif_clientdata, module,
209 			    "Decoding error at scanline %lu, %s",
210 			    (unsigned long) tif->tif_row, LZMAStrerror(ret));
211 			break;
212 		}
213 	} while (sp->stream.avail_out > 0);
214 	if (sp->stream.avail_out != 0) {
215 		TIFFErrorExt(tif->tif_clientdata, module,
216 		    "Not enough data at scanline %lu (short %lu bytes)",
217 		    (unsigned long) tif->tif_row, (unsigned long) sp->stream.avail_out);
218 		return 0;
219 	}
220 
221         tif->tif_rawcp = (uint8 *)sp->stream.next_in; /* cast away const */
222         tif->tif_rawcc = sp->stream.avail_in;
223 
224 	return 1;
225 }
226 
227 static int
LZMASetupEncode(TIFF * tif)228 LZMASetupEncode(TIFF* tif)
229 {
230 	LZMAState* sp = EncoderState(tif);
231 
232 	assert(sp != NULL);
233 	if (sp->state & LSTATE_INIT_DECODE) {
234 		lzma_end(&sp->stream);
235 		sp->state = 0;
236 	}
237 
238 	sp->state |= LSTATE_INIT_ENCODE;
239 	return 1;
240 }
241 
242 /*
243  * Reset encoding state at the start of a strip.
244  */
245 static int
LZMAPreEncode(TIFF * tif,uint16 s)246 LZMAPreEncode(TIFF* tif, uint16 s)
247 {
248 	static const char module[] = "LZMAPreEncode";
249 	LZMAState *sp = EncoderState(tif);
250 
251 	(void) s;
252 	assert(sp != NULL);
253 	if( sp->state != LSTATE_INIT_ENCODE )
254             tif->tif_setupencode(tif);
255 
256 	sp->stream.next_out = tif->tif_rawdata;
257 	sp->stream.avail_out = (size_t)tif->tif_rawdatasize;
258 	if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize) {
259 		TIFFErrorExt(tif->tif_clientdata, module,
260 			     "Liblzma cannot deal with buffers this size");
261 		return 0;
262 	}
263 	return (lzma_stream_encoder(&sp->stream, sp->filters, sp->check) == LZMA_OK);
264 }
265 
266 /*
267  * Encode a chunk of pixels.
268  */
269 static int
LZMAEncode(TIFF * tif,uint8 * bp,tmsize_t cc,uint16 s)270 LZMAEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
271 {
272 	static const char module[] = "LZMAEncode";
273 	LZMAState *sp = EncoderState(tif);
274 
275 	assert(sp != NULL);
276 	assert(sp->state == LSTATE_INIT_ENCODE);
277 
278 	(void) s;
279 	sp->stream.next_in = bp;
280 	sp->stream.avail_in = (size_t) cc;
281 	if ((tmsize_t)sp->stream.avail_in != cc) {
282 		TIFFErrorExt(tif->tif_clientdata, module,
283 			     "Liblzma cannot deal with buffers this size");
284 		return 0;
285 	}
286 	do {
287 		lzma_ret ret = lzma_code(&sp->stream, LZMA_RUN);
288 		if (ret != LZMA_OK) {
289 			TIFFErrorExt(tif->tif_clientdata, module,
290 				"Encoding error at scanline %lu, %s",
291 				(unsigned long) tif->tif_row, LZMAStrerror(ret));
292 			return 0;
293 		}
294 		if (sp->stream.avail_out == 0) {
295 			tif->tif_rawcc = tif->tif_rawdatasize;
296 			TIFFFlushData1(tif);
297 			sp->stream.next_out = tif->tif_rawdata;
298 			sp->stream.avail_out = (size_t)tif->tif_rawdatasize;  /* this is a safe typecast, as check is made already in LZMAPreEncode */
299 		}
300 	} while (sp->stream.avail_in > 0);
301 	return 1;
302 }
303 
304 /*
305  * Finish off an encoded strip by flushing the last
306  * string and tacking on an End Of Information code.
307  */
308 static int
LZMAPostEncode(TIFF * tif)309 LZMAPostEncode(TIFF* tif)
310 {
311 	static const char module[] = "LZMAPostEncode";
312 	LZMAState *sp = EncoderState(tif);
313 	lzma_ret ret;
314 
315 	sp->stream.avail_in = 0;
316 	do {
317 		ret = lzma_code(&sp->stream, LZMA_FINISH);
318 		switch (ret) {
319 		case LZMA_STREAM_END:
320 		case LZMA_OK:
321 			if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize) {
322 				tif->tif_rawcc =
323 					tif->tif_rawdatasize - sp->stream.avail_out;
324 				TIFFFlushData1(tif);
325 				sp->stream.next_out = tif->tif_rawdata;
326 				sp->stream.avail_out = (size_t)tif->tif_rawdatasize;  /* this is a safe typecast, as check is made already in ZIPPreEncode */
327 			}
328 			break;
329 		default:
330 			TIFFErrorExt(tif->tif_clientdata, module, "Liblzma error: %s",
331 				     LZMAStrerror(ret));
332 			return 0;
333 		}
334 	} while (ret != LZMA_STREAM_END);
335 	return 1;
336 }
337 
338 static void
LZMACleanup(TIFF * tif)339 LZMACleanup(TIFF* tif)
340 {
341 	LZMAState* sp = LState(tif);
342 
343 	assert(sp != 0);
344 
345 	(void)TIFFPredictorCleanup(tif);
346 
347 	tif->tif_tagmethods.vgetfield = sp->vgetparent;
348 	tif->tif_tagmethods.vsetfield = sp->vsetparent;
349 
350 	if (sp->state) {
351 		lzma_end(&sp->stream);
352 		sp->state = 0;
353 	}
354 	_TIFFfree(sp);
355 	tif->tif_data = NULL;
356 
357 	_TIFFSetDefaultCompressionState(tif);
358 }
359 
360 static int
LZMAVSetField(TIFF * tif,uint32 tag,va_list ap)361 LZMAVSetField(TIFF* tif, uint32 tag, va_list ap)
362 {
363 	static const char module[] = "LZMAVSetField";
364 	LZMAState* sp = LState(tif);
365 
366 	switch (tag) {
367 	case TIFFTAG_LZMAPRESET:
368 		sp->preset = (int) va_arg(ap, int);
369 		lzma_lzma_preset(&sp->opt_lzma, sp->preset);
370 		if (sp->state & LSTATE_INIT_ENCODE) {
371 			lzma_ret ret = lzma_stream_encoder(&sp->stream,
372 							   sp->filters,
373 							   sp->check);
374 			if (ret != LZMA_OK) {
375 				TIFFErrorExt(tif->tif_clientdata, module,
376 					     "Liblzma error: %s",
377 					     LZMAStrerror(ret));
378 			}
379 		}
380 		return 1;
381 	default:
382 		return (*sp->vsetparent)(tif, tag, ap);
383 	}
384 	/*NOTREACHED*/
385 }
386 
387 static int
LZMAVGetField(TIFF * tif,uint32 tag,va_list ap)388 LZMAVGetField(TIFF* tif, uint32 tag, va_list ap)
389 {
390 	LZMAState* sp = LState(tif);
391 
392 	switch (tag) {
393 	case TIFFTAG_LZMAPRESET:
394 		*va_arg(ap, int*) = sp->preset;
395 		break;
396 	default:
397 		return (*sp->vgetparent)(tif, tag, ap);
398 	}
399 	return 1;
400 }
401 
402 static const TIFFField lzmaFields[] = {
403 	{ TIFFTAG_LZMAPRESET, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, TIFF_SETGET_UNDEFINED,
404 		FIELD_PSEUDO, TRUE, FALSE, "LZMA2 Compression Preset", NULL },
405 };
406 
407 int
TIFFInitLZMA(TIFF * tif,int scheme)408 TIFFInitLZMA(TIFF* tif, int scheme)
409 {
410 	static const char module[] = "TIFFInitLZMA";
411 	LZMAState* sp;
412 	lzma_stream tmp_stream = LZMA_STREAM_INIT;
413 
414 	assert( scheme == COMPRESSION_LZMA );
415 
416 	/*
417 	 * Merge codec-specific tag information.
418 	 */
419 	if (!_TIFFMergeFields(tif, lzmaFields, TIFFArrayCount(lzmaFields))) {
420 		TIFFErrorExt(tif->tif_clientdata, module,
421 			     "Merging LZMA2 codec-specific tags failed");
422 		return 0;
423 	}
424 
425 	/*
426 	 * Allocate state block so tag methods have storage to record values.
427 	 */
428 	tif->tif_data = (uint8*) _TIFFmalloc(sizeof(LZMAState));
429 	if (tif->tif_data == NULL)
430 		goto bad;
431 	sp = LState(tif);
432 	memcpy(&sp->stream, &tmp_stream, sizeof(lzma_stream));
433 
434 	/*
435 	 * Override parent get/set field methods.
436 	 */
437 	sp->vgetparent = tif->tif_tagmethods.vgetfield;
438 	tif->tif_tagmethods.vgetfield = LZMAVGetField;	/* hook for codec tags */
439 	sp->vsetparent = tif->tif_tagmethods.vsetfield;
440 	tif->tif_tagmethods.vsetfield = LZMAVSetField;	/* hook for codec tags */
441 
442 	/* Default values for codec-specific fields */
443 	sp->preset = LZMA_PRESET_DEFAULT;		/* default comp. level */
444 	sp->check = LZMA_CHECK_NONE;
445 	sp->state = 0;
446 
447 	/* Data filters. So far we are using delta and LZMA2 filters only. */
448 	sp->opt_delta.type = LZMA_DELTA_TYPE_BYTE;
449 	/*
450 	 * The sample size in bytes seems to be reasonable distance for delta
451 	 * filter.
452 	 */
453 	sp->opt_delta.dist = (tif->tif_dir.td_bitspersample % 8) ?
454 		1 : tif->tif_dir.td_bitspersample / 8;
455 	sp->filters[0].id = LZMA_FILTER_DELTA;
456 	sp->filters[0].options = &sp->opt_delta;
457 
458 	lzma_lzma_preset(&sp->opt_lzma, sp->preset);
459 	sp->filters[1].id = LZMA_FILTER_LZMA2;
460 	sp->filters[1].options = &sp->opt_lzma;
461 
462 	sp->filters[2].id = LZMA_VLI_UNKNOWN;
463 	sp->filters[2].options = NULL;
464 
465 	/*
466 	 * Install codec methods.
467 	 */
468 	tif->tif_fixuptags = LZMAFixupTags;
469 	tif->tif_setupdecode = LZMASetupDecode;
470 	tif->tif_predecode = LZMAPreDecode;
471 	tif->tif_decoderow = LZMADecode;
472 	tif->tif_decodestrip = LZMADecode;
473 	tif->tif_decodetile = LZMADecode;
474 	tif->tif_setupencode = LZMASetupEncode;
475 	tif->tif_preencode = LZMAPreEncode;
476 	tif->tif_postencode = LZMAPostEncode;
477 	tif->tif_encoderow = LZMAEncode;
478 	tif->tif_encodestrip = LZMAEncode;
479 	tif->tif_encodetile = LZMAEncode;
480 	tif->tif_cleanup = LZMACleanup;
481 	/*
482 	 * Setup predictor setup.
483 	 */
484 	(void) TIFFPredictorInit(tif);
485 	return 1;
486 bad:
487 	TIFFErrorExt(tif->tif_clientdata, module,
488 		     "No space for LZMA2 state block");
489 	return 0;
490 }
491 #endif /* LZMA_SUPPORT */
492 
493 /* vim: set ts=8 sts=8 sw=8 noet: */
494