"Fossies" - the Fresh Open Source Software Archive 
Member "xdelta3-3.0.11/xdelta3-decode.h" (9 Dec 2015, 33128 Bytes) of package /linux/misc/xdelta3-3.0.11.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "xdelta3-decode.h" see the
Fossies "Dox" file reference documentation.
1 /* xdelta 3 - delta compression tools and library
2 * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
3 * 2011, 2012, 2013, 2014, 2015. Joshua P. MacDonald
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20 #ifndef _XDELTA3_DECODE_H_
21 #define _XDELTA3_DECODE_H_
22
23 #include "xdelta3-internal.h"
24
25 #define SRCORTGT(x) ((((x) & VCD_SRCORTGT) == VCD_SOURCE) ? \
26 VCD_SOURCE : ((((x) & VCD_SRCORTGT) == \
27 VCD_TARGET) ? VCD_TARGET : 0))
28
29 static inline int
30 xd3_decode_byte (xd3_stream *stream, usize_t *val)
31 {
32 if (stream->avail_in == 0)
33 {
34 stream->msg = "further input required";
35 return XD3_INPUT;
36 }
37
38 (*val) = stream->next_in[0];
39
40 DECODE_INPUT (1);
41 return 0;
42 }
43
44 static inline int
45 xd3_decode_bytes (xd3_stream *stream, uint8_t *buf, usize_t *pos, usize_t size)
46 {
47 usize_t want;
48 usize_t take;
49
50 /* Note: The case where (*pos == size) happens when a zero-length
51 * appheader or code table is transmitted, but there is nothing in
52 * the standard against that. */
53 while (*pos < size)
54 {
55 if (stream->avail_in == 0)
56 {
57 stream->msg = "further input required";
58 return XD3_INPUT;
59 }
60
61 want = size - *pos;
62 take = xd3_min (want, stream->avail_in);
63
64 memcpy (buf + *pos, stream->next_in, (size_t) take);
65
66 DECODE_INPUT (take);
67 (*pos) += take;
68 }
69
70 return 0;
71 }
72
73 /* Initialize the decoder for a new window. The dec_tgtlen value is
74 * preserved across successive window decodings, and the update to
75 * dec_winstart is delayed until a new window actually starts. This
76 * is to avoid throwing an error due to overflow until the last
77 * possible moment. This makes it possible to encode exactly 4GB
78 * through a 32-bit encoder. */
79 static int
80 xd3_decode_init_window (xd3_stream *stream)
81 {
82 stream->dec_cpylen = 0;
83 stream->dec_cpyoff = 0;
84 stream->dec_cksumbytes = 0;
85
86 xd3_init_cache (& stream->acache);
87
88 return 0;
89 }
90
91 /* Allocates buffer space for the target window and possibly the
92 * VCD_TARGET copy-window. Also sets the base of the two copy
93 * segments. */
94 static int
95 xd3_decode_setup_buffers (xd3_stream *stream)
96 {
97 /* If VCD_TARGET is set then the previous buffer may be reused. */
98 if (stream->dec_win_ind & VCD_TARGET)
99 {
100 /* Note: this implementation is untested, since Xdelta3 itself
101 * does not implement an encoder for VCD_TARGET mode. Thus, mark
102 * unimplemented until needed. */
103 if (1)
104 {
105 stream->msg = "VCD_TARGET not implemented";
106 return XD3_UNIMPLEMENTED;
107 }
108
109 /* But this implementation only supports copying from the last
110 * target window. If the offset is outside that range, it can't
111 * be done. */
112 if (stream->dec_cpyoff < stream->dec_laststart)
113 {
114 stream->msg = "unsupported VCD_TARGET offset";
115 return XD3_INVALID_INPUT;
116 }
117
118 /* See if the two windows are the same. This indicates the
119 * first time VCD_TARGET is used. This causes a second buffer
120 * to be allocated, after that the two are swapped in the
121 * DEC_FINISH case. */
122 if (stream->dec_lastwin == stream->next_out)
123 {
124 stream->next_out = NULL;
125 stream->space_out = 0;
126 }
127
128 /* TODO: (See note above, this looks incorrect) */
129 stream->dec_cpyaddrbase = stream->dec_lastwin +
130 (usize_t) (stream->dec_cpyoff - stream->dec_laststart);
131 }
132
133 /* See if the current output window is large enough. */
134 if (stream->space_out < stream->dec_tgtlen)
135 {
136 xd3_free (stream, stream->dec_buffer);
137
138 stream->space_out =
139 xd3_round_blksize (stream->dec_tgtlen, XD3_ALLOCSIZE);
140
141 if ((stream->dec_buffer =
142 (uint8_t*) xd3_alloc (stream, stream->space_out, 1)) == NULL)
143 {
144 return ENOMEM;
145 }
146
147 stream->next_out = stream->dec_buffer;
148 }
149
150 /* dec_tgtaddrbase refers to an invalid base address, but it is
151 * always used with a sufficiently large instruction offset (i.e.,
152 * beyond the copy window). This condition is enforced by
153 * xd3_decode_output_halfinst. */
154 stream->dec_tgtaddrbase = stream->next_out - stream->dec_cpylen;
155
156 return 0;
157 }
158
159 static int
160 xd3_decode_allocate (xd3_stream *stream,
161 usize_t size,
162 uint8_t **buf_ptr,
163 usize_t *buf_alloc)
164 {
165 IF_DEBUG2 (DP(RINT "[xd3_decode_allocate] size %u alloc %u\n",
166 size, *buf_alloc));
167
168 if (*buf_ptr != NULL && *buf_alloc < size)
169 {
170 xd3_free (stream, *buf_ptr);
171 *buf_ptr = NULL;
172 }
173
174 if (*buf_ptr == NULL)
175 {
176 *buf_alloc = xd3_round_blksize (size, XD3_ALLOCSIZE);
177
178 if ((*buf_ptr = (uint8_t*) xd3_alloc (stream, *buf_alloc, 1)) == NULL)
179 {
180 return ENOMEM;
181 }
182 }
183
184 return 0;
185 }
186
187 static int
188 xd3_decode_section (xd3_stream *stream,
189 xd3_desect *section,
190 xd3_decode_state nstate,
191 int copy)
192 {
193 XD3_ASSERT (section->pos <= section->size);
194 XD3_ASSERT (stream->dec_state != nstate);
195
196 if (section->pos < section->size)
197 {
198 usize_t sect_take;
199
200 if (stream->avail_in == 0)
201 {
202 return XD3_INPUT;
203 }
204
205 if ((copy == 0) && (section->pos == 0))
206 {
207 /* No allocation/copy needed */
208 section->buf = stream->next_in;
209 sect_take = section->size;
210 IF_DEBUG1 (DP(RINT "[xd3_decode_section] zerocopy %u @ %u avail %u\n",
211 sect_take, section->pos, stream->avail_in));
212 }
213 else
214 {
215 usize_t sect_need = section->size - section->pos;
216
217 /* Allocate and copy */
218 sect_take = xd3_min (sect_need, stream->avail_in);
219
220 if (section->pos == 0)
221 {
222 int ret;
223
224 if ((ret = xd3_decode_allocate (stream,
225 section->size,
226 & section->copied1,
227 & section->alloc1)))
228 {
229 return ret;
230 }
231
232 section->buf = section->copied1;
233 }
234
235 IF_DEBUG2 (DP(RINT "[xd3_decode_section] take %u @ %u [need %u] avail %u\n",
236 sect_take, section->pos, sect_need, stream->avail_in));
237 XD3_ASSERT (section->pos + sect_take <= section->alloc1);
238
239 memcpy (section->copied1 + section->pos,
240 stream->next_in,
241 sect_take);
242 }
243
244 section->pos += sect_take;
245
246 stream->dec_winbytes += sect_take;
247
248 DECODE_INPUT (sect_take);
249 }
250
251 if (section->pos < section->size)
252 {
253 IF_DEBUG1 (DP(RINT "[xd3_decode_section] further input required %u\n", section->size - section->pos));
254 stream->msg = "further input required";
255 return XD3_INPUT;
256 }
257
258 XD3_ASSERT (section->pos == section->size);
259
260 stream->dec_state = nstate;
261 section->buf_max = section->buf + section->size;
262 section->pos = 0;
263 return 0;
264 }
265
266 /* Decode the size and address for half of an instruction (i.e., a
267 * single opcode). This updates the stream->dec_position, which are
268 * bytes already output prior to processing this instruction. Perform
269 * bounds checking for sizes and copy addresses, which uses the
270 * dec_position (which is why these checks are done here). */
271 static int
272 xd3_decode_parse_halfinst (xd3_stream *stream, xd3_hinst *inst)
273 {
274 int ret;
275
276 /* If the size from the instruction table is zero then read a size value. */
277 if ((inst->size == 0) &&
278 (ret = xd3_read_size (stream,
279 & stream->inst_sect.buf,
280 stream->inst_sect.buf_max,
281 & inst->size)))
282 {
283 return XD3_INVALID_INPUT;
284 }
285
286 /* For copy instructions, read address. */
287 if (inst->type >= XD3_CPY)
288 {
289 IF_DEBUG2 ({
290 static int cnt = 0;
291 XPR(NT "DECODE:%u: COPY at %"Q"u (winoffset %u) size %u winaddr %u\n",
292 cnt++,
293 stream->total_out + (stream->dec_position -
294 stream->dec_cpylen),
295 (stream->dec_position - stream->dec_cpylen),
296 inst->size,
297 inst->addr);
298 });
299
300 if ((ret = xd3_decode_address (stream,
301 stream->dec_position,
302 inst->type - XD3_CPY,
303 & stream->addr_sect.buf,
304 stream->addr_sect.buf_max,
305 & inst->addr)))
306 {
307 return ret;
308 }
309
310 /* Cannot copy an address before it is filled-in. */
311 if (inst->addr >= stream->dec_position)
312 {
313 stream->msg = "address too large";
314 return XD3_INVALID_INPUT;
315 }
316
317 /* Check: a VCD_TARGET or VCD_SOURCE copy cannot exceed the remaining
318 * buffer space in its own segment. */
319 if (inst->addr < stream->dec_cpylen &&
320 inst->addr + inst->size > stream->dec_cpylen)
321 {
322 stream->msg = "size too large";
323 return XD3_INVALID_INPUT;
324 }
325 }
326 else
327 {
328 IF_DEBUG2 ({
329 if (inst->type == XD3_ADD)
330 {
331 static int cnt;
332 XPR(NT "DECODE:%d: ADD at %"Q"u (winoffset %u) size %u\n",
333 cnt++,
334 (stream->total_out + stream->dec_position - stream->dec_cpylen),
335 stream->dec_position - stream->dec_cpylen,
336 inst->size);
337 }
338 else
339 {
340 static int cnt;
341 XD3_ASSERT (inst->type == XD3_RUN);
342 XPR(NT "DECODE:%d: RUN at %"Q"u (winoffset %u) size %u\n",
343 cnt++,
344 stream->total_out + stream->dec_position - stream->dec_cpylen,
345 stream->dec_position - stream->dec_cpylen,
346 inst->size);
347 }
348 });
349 }
350
351 /* Check: The instruction will not overflow the output buffer. */
352 if (stream->dec_position + inst->size > stream->dec_maxpos)
353 {
354 stream->msg = "size too large";
355 return XD3_INVALID_INPUT;
356 }
357
358 stream->dec_position += inst->size;
359 return 0;
360 }
361
362 /* Decode a single opcode and then decode the two half-instructions. */
363 static int
364 xd3_decode_instruction (xd3_stream *stream)
365 {
366 int ret;
367 const xd3_dinst *inst;
368
369 if (stream->inst_sect.buf == stream->inst_sect.buf_max)
370 {
371 stream->msg = "instruction underflow";
372 return XD3_INVALID_INPUT;
373 }
374
375 inst = &stream->code_table[*stream->inst_sect.buf++];
376
377 stream->dec_current1.type = inst->type1;
378 stream->dec_current2.type = inst->type2;
379 stream->dec_current1.size = inst->size1;
380 stream->dec_current2.size = inst->size2;
381
382 /* For each instruction with a real operation, decode the
383 * corresponding size and addresses if necessary. Assume a
384 * code-table may have NOOP in either position, although this is
385 * unlikely. */
386 if (inst->type1 != XD3_NOOP &&
387 (ret = xd3_decode_parse_halfinst (stream, & stream->dec_current1)))
388 {
389 return ret;
390 }
391 if (inst->type2 != XD3_NOOP &&
392 (ret = xd3_decode_parse_halfinst (stream, & stream->dec_current2)))
393 {
394 return ret;
395 }
396 return 0;
397 }
398
399 /* Output the result of a single half-instruction. OPT: This the
400 decoder hotspot. Modifies "hinst", see below. */
401 static int
402 xd3_decode_output_halfinst (xd3_stream *stream, xd3_hinst *inst)
403 {
404 /* This method is reentrant for copy instructions which may return
405 * XD3_GETSRCBLK to the caller. Each time through a copy takes the
406 * minimum of inst->size and the available space on whichever block
407 * supplies the data */
408 usize_t take = inst->size;
409
410 if (USIZE_T_OVERFLOW (stream->avail_out, take) ||
411 stream->avail_out + take > stream->space_out)
412 {
413 stream->msg = "overflow while decoding";
414 return XD3_INVALID_INPUT;
415 }
416
417 XD3_ASSERT (inst->type != XD3_NOOP);
418
419 switch (inst->type)
420 {
421 case XD3_RUN:
422 {
423 /* Only require a single data byte. */
424 if (stream->data_sect.buf == stream->data_sect.buf_max)
425 {
426 stream->msg = "data underflow";
427 return XD3_INVALID_INPUT;
428 }
429
430 memset (stream->next_out + stream->avail_out,
431 stream->data_sect.buf[0],
432 take);
433
434 stream->data_sect.buf += 1;
435 stream->avail_out += take;
436 inst->type = XD3_NOOP;
437 break;
438 }
439 case XD3_ADD:
440 {
441 /* Require at least TAKE data bytes. */
442 if (stream->data_sect.buf + take > stream->data_sect.buf_max)
443 {
444 stream->msg = "data underflow";
445 return XD3_INVALID_INPUT;
446 }
447
448 memcpy (stream->next_out + stream->avail_out,
449 stream->data_sect.buf,
450 take);
451
452 stream->data_sect.buf += take;
453 stream->avail_out += take;
454 inst->type = XD3_NOOP;
455 break;
456 }
457 default:
458 {
459 usize_t i;
460 const uint8_t *src;
461 uint8_t *dst;
462 int overlap;
463
464 /* See if it copies from the VCD_TARGET/VCD_SOURCE window or
465 * the target window. Out-of-bounds checks for the addresses
466 * and sizes are performed in xd3_decode_parse_halfinst. This
467 * if/else must set "overlap", "src", and "dst". */
468 if (inst->addr < stream->dec_cpylen)
469 {
470 /* In both branches we are copying from outside the
471 * current decoder window, the first (VCD_TARGET) is
472 * unimplemented. */
473 overlap = 0;
474
475 /* This branch sets "src". As a side-effect, we modify
476 * "inst" so that if we reenter this method after a
477 * XD3_GETSRCBLK response the state is correct. So if the
478 * instruction can be fulfilled by a contiguous block of
479 * memory then we will set:
480 *
481 * inst->type = XD3_NOOP;
482 * inst->size = 0;
483 */
484 if (stream->dec_win_ind & VCD_TARGET)
485 {
486 /* TODO: Users have requested long-distance copies of
487 * similar material within a target (e.g., for dup
488 * supression in backups). This code path is probably
489 * dead due to XD3_UNIMPLEMENTED in xd3_decode_setup_buffers */
490 inst->size = 0;
491 inst->type = XD3_NOOP;
492 stream->msg = "VCD_TARGET not implemented";
493 return XD3_UNIMPLEMENTED;
494 }
495 else
496 {
497 /* In this case we have to read a source block, which
498 * could return control to the caller. We need to
499 * know the first block number needed for this
500 * copy. */
501 xd3_source *source = stream->src;
502 xoff_t block = source->cpyoff_blocks;
503 usize_t blkoff = source->cpyoff_blkoff;
504 const usize_t blksize = source->blksize;
505 int ret;
506
507 xd3_blksize_add (&block, &blkoff, source, inst->addr);
508 XD3_ASSERT (blkoff < blksize);
509
510 if ((ret = xd3_getblk (stream, block)))
511 {
512 /* could be a XD3_GETSRCBLK failure. */
513 if (ret == XD3_TOOFARBACK)
514 {
515 stream->msg = "non-seekable source in decode";
516 ret = XD3_INTERNAL;
517 }
518 return ret;
519 }
520
521 src = source->curblk + blkoff;
522
523 /* This block is either full, or a partial block that
524 * must contain enough bytes. */
525 if ((source->onblk != blksize) &&
526 (blkoff + take > source->onblk))
527 {
528 IF_DEBUG1 (XPR(NT "[srcfile] short at blkno %"Q"u onblk "
529 "%u blksize %u blkoff %u take %u\n",
530 block,
531 source->onblk,
532 blksize,
533 blkoff,
534 take));
535 stream->msg = "source file too short";
536 return XD3_INVALID_INPUT;
537 }
538
539 XD3_ASSERT (blkoff != blksize);
540
541 /* Check if we have enough data on this block to
542 * finish the instruction. */
543 if (blkoff + take <= blksize)
544 {
545 inst->type = XD3_NOOP;
546 inst->size = 0;
547 }
548 else
549 {
550 take = blksize - blkoff;
551 inst->size -= take;
552 inst->addr += take;
553
554 /* because (blkoff + take > blksize), above */
555 XD3_ASSERT (inst->size != 0);
556 }
557 }
558 }
559 else
560 {
561 /* TODO: the memcpy/overlap optimization, etc. Overlap
562 * here could be more specific, it's whether (inst->addr -
563 * srclen) + inst->size > input_pos ? And is the system
564 * memcpy really any good? */
565 overlap = 1;
566
567 /* For a target-window copy, we know the entire range is
568 * in-memory. The dec_tgtaddrbase is negatively offset by
569 * dec_cpylen because the addresses start beyond that
570 * point. */
571 src = stream->dec_tgtaddrbase + inst->addr;
572 inst->type = XD3_NOOP;
573 inst->size = 0;
574 }
575
576 dst = stream->next_out + stream->avail_out;
577
578 stream->avail_out += take;
579
580 if (overlap)
581 {
582 /* Can't just memcpy here due to possible overlap. */
583 for (i = take; i != 0; i -= 1)
584 {
585 *dst++ = *src++;
586 }
587 }
588 else
589 {
590 memcpy (dst, src, take);
591 }
592 }
593 }
594
595 return 0;
596 }
597
598 static int
599 xd3_decode_finish_window (xd3_stream *stream)
600 {
601 stream->dec_winbytes = 0;
602 stream->dec_state = DEC_FINISH;
603
604 stream->data_sect.pos = 0;
605 stream->inst_sect.pos = 0;
606 stream->addr_sect.pos = 0;
607
608 return XD3_OUTPUT;
609 }
610
611 static int
612 xd3_decode_secondary_sections (xd3_stream *secondary_stream)
613 {
614 #if SECONDARY_ANY
615 int ret;
616 #define DECODE_SECONDARY_SECTION(UPPER,LOWER) \
617 ((secondary_stream->dec_del_ind & VCD_ ## UPPER ## COMP) && \
618 (ret = xd3_decode_secondary (secondary_stream, \
619 & secondary_stream-> LOWER ## _sect, \
620 & xd3_sec_ ## LOWER (secondary_stream))))
621
622 if (DECODE_SECONDARY_SECTION (DATA, data) ||
623 DECODE_SECONDARY_SECTION (INST, inst) ||
624 DECODE_SECONDARY_SECTION (ADDR, addr))
625 {
626 return ret;
627 }
628 #undef DECODE_SECONDARY_SECTION
629 #endif
630 return 0;
631 }
632
633 static int
634 xd3_decode_sections (xd3_stream *stream)
635 {
636 usize_t need, more, take;
637 int copy, ret;
638
639 if ((stream->flags & XD3_JUST_HDR) != 0)
640 {
641 /* Nothing left to do. */
642 return xd3_decode_finish_window (stream);
643 }
644
645 /* To avoid extra copying, allocate three sections at once (but
646 * check for overflow). */
647 need = stream->inst_sect.size;
648
649 if (USIZE_T_OVERFLOW (need, stream->addr_sect.size))
650 {
651 stream->msg = "decoder section size overflow";
652 return XD3_INTERNAL;
653 }
654 need += stream->addr_sect.size;
655
656 if (USIZE_T_OVERFLOW (need, stream->data_sect.size))
657 {
658 stream->msg = "decoder section size overflow";
659 return XD3_INTERNAL;
660 }
661 need += stream->data_sect.size;
662
663 /* The window may be entirely processed. */
664 XD3_ASSERT (stream->dec_winbytes <= need);
665
666 /* Compute how much more input is needed. */
667 more = (need - stream->dec_winbytes);
668
669 /* How much to consume. */
670 take = xd3_min (more, stream->avail_in);
671
672 /* See if the input is completely available, to avoid copy. */
673 copy = (take != more);
674
675 /* If the window is skipped... */
676 if ((stream->flags & XD3_SKIP_WINDOW) != 0)
677 {
678 /* Skip the available input. */
679 DECODE_INPUT (take);
680
681 stream->dec_winbytes += take;
682
683 if (copy)
684 {
685 stream->msg = "further input required";
686 return XD3_INPUT;
687 }
688
689 return xd3_decode_finish_window (stream);
690 }
691
692 /* Process all but the DATA section. */
693 switch (stream->dec_state)
694 {
695 default:
696 stream->msg = "internal error";
697 return XD3_INVALID_INPUT;
698
699 case DEC_DATA:
700 if ((ret = xd3_decode_section (stream, & stream->data_sect,
701 DEC_INST, copy))) { return ret; }
702 case DEC_INST:
703 if ((ret = xd3_decode_section (stream, & stream->inst_sect,
704 DEC_ADDR, copy))) { return ret; }
705 case DEC_ADDR:
706 if ((ret = xd3_decode_section (stream, & stream->addr_sect,
707 DEC_EMIT, copy))) { return ret; }
708 }
709
710 XD3_ASSERT (stream->dec_winbytes == need);
711
712 if ((ret = xd3_decode_secondary_sections (stream))) { return ret; }
713
714 if (stream->flags & XD3_SKIP_EMIT)
715 {
716 return xd3_decode_finish_window (stream);
717 }
718
719 /* OPT: A possible optimization is to avoid allocating memory in
720 * decode_setup_buffers and to avoid a large memcpy when the window
721 * consists of a single VCD_SOURCE copy instruction. */
722 if ((ret = xd3_decode_setup_buffers (stream))) { return ret; }
723
724 return 0;
725 }
726
727 static int
728 xd3_decode_emit (xd3_stream *stream)
729 {
730 int ret;
731
732 /* Produce output: originally structured to allow reentrant code
733 * that fills as much of the output buffer as possible, but VCDIFF
734 * semantics allows to copy from anywhere from the target window, so
735 * instead allocate a sufficiently sized buffer after the target
736 * window length is decoded.
737 *
738 * This code still needs to be reentrant to allow XD3_GETSRCBLK to
739 * return control. This is handled by setting the
740 * stream->dec_currentN instruction types to XD3_NOOP after they
741 * have been processed. */
742 XD3_ASSERT (! (stream->flags & XD3_SKIP_EMIT));
743 XD3_ASSERT (stream->dec_tgtlen <= stream->space_out);
744
745 while (stream->inst_sect.buf != stream->inst_sect.buf_max ||
746 stream->dec_current1.type != XD3_NOOP ||
747 stream->dec_current2.type != XD3_NOOP)
748 {
749 /* Decode next instruction pair. */
750 if ((stream->dec_current1.type == XD3_NOOP) &&
751 (stream->dec_current2.type == XD3_NOOP) &&
752 (ret = xd3_decode_instruction (stream))) { return ret; }
753
754 /* Output dec_current1 */
755 while ((stream->dec_current1.type != XD3_NOOP))
756 {
757 if ((ret = xd3_decode_output_halfinst (stream, & stream->dec_current1)))
758 {
759 return ret;
760 }
761 }
762 /* Output dec_current2 */
763 while (stream->dec_current2.type != XD3_NOOP)
764 {
765 if ((ret = xd3_decode_output_halfinst (stream, & stream->dec_current2)))
766 {
767 return ret;
768 }
769 }
770 }
771
772 if (stream->avail_out != stream->dec_tgtlen)
773 {
774 IF_DEBUG2 (DP(RINT "AVAIL_OUT(%d) != DEC_TGTLEN(%d)\n",
775 stream->avail_out, stream->dec_tgtlen));
776 stream->msg = "wrong window length";
777 return XD3_INVALID_INPUT;
778 }
779
780 if (stream->data_sect.buf != stream->data_sect.buf_max)
781 {
782 stream->msg = "extra data section";
783 return XD3_INVALID_INPUT;
784 }
785
786 if (stream->addr_sect.buf != stream->addr_sect.buf_max)
787 {
788 stream->msg = "extra address section";
789 return XD3_INVALID_INPUT;
790 }
791
792 /* OPT: Should cksum computation be combined with the above loop? */
793 if ((stream->dec_win_ind & VCD_ADLER32) != 0 &&
794 (stream->flags & XD3_ADLER32_NOVER) == 0)
795 {
796 uint32_t a32 = adler32 (1L, stream->next_out, stream->avail_out);
797
798 if (a32 != stream->dec_adler32)
799 {
800 stream->msg = "target window checksum mismatch";
801 return XD3_INVALID_INPUT;
802 }
803 }
804
805 /* Finished with a window. */
806 return xd3_decode_finish_window (stream);
807 }
808
809 int
810 xd3_decode_input (xd3_stream *stream)
811 {
812 int ret;
813
814 if (stream->enc_state != 0)
815 {
816 stream->msg = "encoder/decoder transition";
817 return XD3_INVALID_INPUT;
818 }
819
820 #define BYTE_CASE(expr,x,nstate) \
821 do { \
822 if ( (expr) && \
823 ((ret = xd3_decode_byte (stream, & (x))) != 0) ) { return ret; } \
824 stream->dec_state = (nstate); \
825 } while (0)
826
827 #define OFFSET_CASE(expr,x,nstate) \
828 do { \
829 if ( (expr) && \
830 ((ret = xd3_decode_offset (stream, & (x))) != 0) ) { return ret; } \
831 stream->dec_state = (nstate); \
832 } while (0)
833
834 #define SIZE_CASE(expr,x,nstate) \
835 do { \
836 if ( (expr) && \
837 ((ret = xd3_decode_size (stream, & (x))) != 0) ) { return ret; } \
838 stream->dec_state = (nstate); \
839 } while (0)
840
841 switch (stream->dec_state)
842 {
843 case DEC_VCHEAD:
844 {
845 if ((ret = xd3_decode_bytes (stream, stream->dec_magic,
846 & stream->dec_magicbytes, 4)))
847 {
848 return ret;
849 }
850
851 if (stream->dec_magic[0] != VCDIFF_MAGIC1 ||
852 stream->dec_magic[1] != VCDIFF_MAGIC2 ||
853 stream->dec_magic[2] != VCDIFF_MAGIC3)
854 {
855 stream->msg = "not a VCDIFF input";
856 return XD3_INVALID_INPUT;
857 }
858
859 if (stream->dec_magic[3] != 0)
860 {
861 stream->msg = "VCDIFF input version > 0 is not supported";
862 return XD3_INVALID_INPUT;
863 }
864
865 stream->dec_state = DEC_HDRIND;
866 }
867 case DEC_HDRIND:
868 {
869 if ((ret = xd3_decode_byte (stream, & stream->dec_hdr_ind)))
870 {
871 return ret;
872 }
873
874 if ((stream->dec_hdr_ind & VCD_INVHDR) != 0)
875 {
876 stream->msg = "unrecognized header indicator bits set";
877 return XD3_INVALID_INPUT;
878 }
879
880 stream->dec_state = DEC_SECONDID;
881 }
882
883 case DEC_SECONDID:
884 /* Secondary compressor ID: only if VCD_SECONDARY is set */
885 if ((stream->dec_hdr_ind & VCD_SECONDARY) != 0)
886 {
887 BYTE_CASE (1, stream->dec_secondid, DEC_TABLEN);
888
889 switch (stream->dec_secondid)
890 {
891 case VCD_FGK_ID:
892 FGK_CASE (stream);
893 case VCD_DJW_ID:
894 DJW_CASE (stream);
895 case VCD_LZMA_ID:
896 LZMA_CASE (stream);
897 default:
898 stream->msg = "unknown secondary compressor ID";
899 return XD3_INVALID_INPUT;
900 }
901 }
902
903 case DEC_TABLEN:
904 /* Length of code table data: only if VCD_CODETABLE is set */
905 SIZE_CASE ((stream->dec_hdr_ind & VCD_CODETABLE) != 0,
906 stream->dec_codetblsz, DEC_NEAR);
907
908 /* The codetblsz counts the two NEAR/SAME bytes */
909 if ((stream->dec_hdr_ind & VCD_CODETABLE) != 0) {
910 if (stream->dec_codetblsz <= 2) {
911 stream->msg = "invalid code table size";
912 return ENOMEM;
913 }
914 stream->dec_codetblsz -= 2;
915 }
916 case DEC_NEAR:
917 /* Near modes: only if VCD_CODETABLE is set */
918 BYTE_CASE((stream->dec_hdr_ind & VCD_CODETABLE) != 0,
919 stream->acache.s_near, DEC_SAME);
920 case DEC_SAME:
921 /* Same modes: only if VCD_CODETABLE is set */
922 BYTE_CASE((stream->dec_hdr_ind & VCD_CODETABLE) != 0,
923 stream->acache.s_same, DEC_TABDAT);
924 case DEC_TABDAT:
925 /* Compressed code table data */
926
927 if ((stream->dec_hdr_ind & VCD_CODETABLE) != 0)
928 {
929 stream->msg = "VCD_CODETABLE support was removed";
930 return XD3_UNIMPLEMENTED;
931 }
932 else
933 {
934 /* Use the default table. */
935 stream->acache.s_near = __rfc3284_code_table_desc.near_modes;
936 stream->acache.s_same = __rfc3284_code_table_desc.same_modes;
937 stream->code_table = xd3_rfc3284_code_table ();
938 }
939
940 if ((ret = xd3_alloc_cache (stream))) { return ret; }
941
942 stream->dec_state = DEC_APPLEN;
943
944 case DEC_APPLEN:
945 /* Length of application data */
946 SIZE_CASE((stream->dec_hdr_ind & VCD_APPHEADER) != 0,
947 stream->dec_appheadsz, DEC_APPDAT);
948
949 case DEC_APPDAT:
950 /* Application data */
951 if (stream->dec_hdr_ind & VCD_APPHEADER)
952 {
953 /* Note: we add an additional byte for padding, to allow
954 0-termination. Check for overflow: */
955 if (USIZE_T_OVERFLOW(stream->dec_appheadsz, 1))
956 {
957 stream->msg = "exceptional appheader size";
958 return XD3_INVALID_INPUT;
959 }
960
961 if ((stream->dec_appheader == NULL) &&
962 (stream->dec_appheader =
963 (uint8_t*) xd3_alloc (stream,
964 stream->dec_appheadsz+1, 1)) == NULL)
965 {
966 return ENOMEM;
967 }
968
969 stream->dec_appheader[stream->dec_appheadsz] = 0;
970
971 if ((ret = xd3_decode_bytes (stream, stream->dec_appheader,
972 & stream->dec_appheadbytes,
973 stream->dec_appheadsz)))
974 {
975 return ret;
976 }
977 }
978
979 /* xoff_t -> usize_t is safe because this is the first block. */
980 stream->dec_hdrsize = (usize_t) stream->total_in;
981 stream->dec_state = DEC_WININD;
982
983 case DEC_WININD:
984 {
985 /* Start of a window: the window indicator */
986 if ((ret = xd3_decode_byte (stream, & stream->dec_win_ind)))
987 {
988 return ret;
989 }
990
991 stream->current_window = stream->dec_window_count;
992
993 if (XOFF_T_OVERFLOW (stream->dec_winstart, stream->dec_tgtlen))
994 {
995 stream->msg = "decoder file offset overflow";
996 return XD3_INVALID_INPUT;
997 }
998
999 stream->dec_winstart += stream->dec_tgtlen;
1000
1001 if ((stream->dec_win_ind & VCD_INVWIN) != 0)
1002 {
1003 stream->msg = "unrecognized window indicator bits set";
1004 return XD3_INVALID_INPUT;
1005 }
1006
1007 if ((ret = xd3_decode_init_window (stream))) { return ret; }
1008
1009 stream->dec_state = DEC_CPYLEN;
1010
1011 IF_DEBUG2 (DP(RINT "--------- TARGET WINDOW %"Q"u -----------\n",
1012 stream->current_window));
1013 }
1014
1015 case DEC_CPYLEN:
1016 /* Copy window length: only if VCD_SOURCE or VCD_TARGET is set */
1017 SIZE_CASE(SRCORTGT (stream->dec_win_ind), stream->dec_cpylen,
1018 DEC_CPYOFF);
1019
1020 /* Set the initial, logical decoder position (HERE address) in
1021 * dec_position. This is set to just after the source/copy
1022 * window, as we are just about to output the first byte of
1023 * target window. */
1024 stream->dec_position = stream->dec_cpylen;
1025
1026 case DEC_CPYOFF:
1027 /* Copy window offset: only if VCD_SOURCE or VCD_TARGET is set */
1028
1029 OFFSET_CASE(SRCORTGT (stream->dec_win_ind), stream->dec_cpyoff,
1030 DEC_ENCLEN);
1031
1032 /* Copy offset and copy length may not overflow. */
1033 if (XOFF_T_OVERFLOW (stream->dec_cpyoff, stream->dec_cpylen))
1034 {
1035 stream->msg = "decoder copy window overflows a file offset";
1036 return XD3_INVALID_INPUT;
1037 }
1038
1039 /* Check copy window bounds: VCD_TARGET window may not exceed
1040 current position. */
1041 if ((stream->dec_win_ind & VCD_TARGET) &&
1042 (stream->dec_cpyoff + (xoff_t) stream->dec_cpylen >
1043 stream->dec_winstart))
1044 {
1045 stream->msg = "VCD_TARGET window out of bounds";
1046 return XD3_INVALID_INPUT;
1047 }
1048
1049 case DEC_ENCLEN:
1050 /* Length of the delta encoding */
1051 SIZE_CASE(1, stream->dec_enclen, DEC_TGTLEN);
1052 case DEC_TGTLEN:
1053 /* Length of target window */
1054 SIZE_CASE(1, stream->dec_tgtlen, DEC_DELIND);
1055
1056 /* Set the maximum decoder position, beyond which we should not
1057 * decode any data. This is the maximum value for dec_position.
1058 * This may not exceed the size of a usize_t. */
1059 if (USIZE_T_OVERFLOW (stream->dec_cpylen, stream->dec_tgtlen))
1060 {
1061 stream->msg = "decoder target window overflows a usize_t";
1062 return XD3_INVALID_INPUT;
1063 }
1064
1065 /* Check for malicious files. */
1066 if (stream->dec_tgtlen > XD3_HARDMAXWINSIZE)
1067 {
1068 stream->msg = "hard window size exceeded";
1069 return XD3_INVALID_INPUT;
1070 }
1071
1072 stream->dec_maxpos = stream->dec_cpylen + stream->dec_tgtlen;
1073
1074 case DEC_DELIND:
1075 /* Delta indicator */
1076 BYTE_CASE(1, stream->dec_del_ind, DEC_DATALEN);
1077
1078 if ((stream->dec_del_ind & VCD_INVDEL) != 0)
1079 {
1080 stream->msg = "unrecognized delta indicator bits set";
1081 return XD3_INVALID_INPUT;
1082 }
1083
1084 /* Delta indicator is only used with secondary compression. */
1085 if ((stream->dec_del_ind != 0) && (stream->sec_type == NULL))
1086 {
1087 stream->msg = "invalid delta indicator bits set";
1088 return XD3_INVALID_INPUT;
1089 }
1090
1091 /* Section lengths */
1092 case DEC_DATALEN:
1093 SIZE_CASE(1, stream->data_sect.size, DEC_INSTLEN);
1094 case DEC_INSTLEN:
1095 SIZE_CASE(1, stream->inst_sect.size, DEC_ADDRLEN);
1096 case DEC_ADDRLEN:
1097 SIZE_CASE(1, stream->addr_sect.size, DEC_CKSUM);
1098
1099 case DEC_CKSUM:
1100 /* Window checksum. */
1101 if ((stream->dec_win_ind & VCD_ADLER32) != 0)
1102 {
1103 int i;
1104
1105 if ((ret = xd3_decode_bytes (stream, stream->dec_cksum,
1106 & stream->dec_cksumbytes, 4)))
1107 {
1108 return ret;
1109 }
1110
1111 for (i = 0; i < 4; i += 1)
1112 {
1113 stream->dec_adler32 =
1114 (stream->dec_adler32 << 8) | stream->dec_cksum[i];
1115 }
1116 }
1117
1118 stream->dec_state = DEC_DATA;
1119
1120 /* Check dec_enclen for redundency, otherwise it is not really used. */
1121 {
1122 usize_t enclen_check =
1123 (1 + (xd3_sizeof_size (stream->dec_tgtlen) +
1124 xd3_sizeof_size (stream->data_sect.size) +
1125 xd3_sizeof_size (stream->inst_sect.size) +
1126 xd3_sizeof_size (stream->addr_sect.size)) +
1127 stream->data_sect.size +
1128 stream->inst_sect.size +
1129 stream->addr_sect.size +
1130 ((stream->dec_win_ind & VCD_ADLER32) ? 4 : 0));
1131
1132 if (stream->dec_enclen != enclen_check)
1133 {
1134 stream->msg = "incorrect encoding length (redundent)";
1135 return XD3_INVALID_INPUT;
1136 }
1137 }
1138
1139 /* Returning here gives the application a chance to inspect the
1140 * header, skip the window, etc. */
1141 if (stream->current_window == 0) { return XD3_GOTHEADER; }
1142 else { return XD3_WINSTART; }
1143
1144 case DEC_DATA:
1145 case DEC_INST:
1146 case DEC_ADDR:
1147 /* Next read the three sections. */
1148 if ((ret = xd3_decode_sections (stream))) { return ret; }
1149
1150 case DEC_EMIT:
1151
1152 /* To speed VCD_SOURCE block-address calculations, the source
1153 * cpyoff_blocks and cpyoff_blkoff are pre-computed. */
1154 if (stream->dec_win_ind & VCD_SOURCE)
1155 {
1156 xd3_source *src = stream->src;
1157
1158 if (src == NULL)
1159 {
1160 stream->msg = "source input required";
1161 return XD3_INVALID_INPUT;
1162 }
1163
1164 xd3_blksize_div(stream->dec_cpyoff, src,
1165 &src->cpyoff_blocks,
1166 &src->cpyoff_blkoff);
1167
1168 IF_DEBUG2(DP(RINT
1169 "[decode_cpyoff] %"Q"u "
1170 "cpyblkno %"Q"u "
1171 "cpyblkoff %u "
1172 "blksize %u\n",
1173 stream->dec_cpyoff,
1174 src->cpyoff_blocks,
1175 src->cpyoff_blkoff,
1176 src->blksize));
1177 }
1178
1179 /* xd3_decode_emit returns XD3_OUTPUT on every success. */
1180 if ((ret = xd3_decode_emit (stream)) == XD3_OUTPUT)
1181 {
1182 stream->total_out += (xoff_t) stream->avail_out;
1183 }
1184
1185 return ret;
1186
1187 case DEC_FINISH:
1188 {
1189 if (stream->dec_win_ind & VCD_TARGET)
1190 {
1191 if (stream->dec_lastwin == NULL)
1192 {
1193 stream->dec_lastwin = stream->next_out;
1194 stream->dec_lastspace = stream->space_out;
1195 }
1196 else
1197 {
1198 xd3_swap_uint8p (& stream->dec_lastwin,
1199 & stream->next_out);
1200 xd3_swap_usize_t (& stream->dec_lastspace,
1201 & stream->space_out);
1202 }
1203 }
1204
1205 stream->dec_lastlen = stream->dec_tgtlen;
1206 stream->dec_laststart = stream->dec_winstart;
1207 stream->dec_window_count += 1;
1208
1209 /* Note: the updates to dec_winstart & current_window are
1210 * deferred until after the next DEC_WININD byte is read. */
1211 stream->dec_state = DEC_WININD;
1212 return XD3_WINFINISH;
1213 }
1214
1215 default:
1216 stream->msg = "invalid state";
1217 return XD3_INVALID_INPUT;
1218 }
1219 }
1220
1221 #endif // _XDELTA3_DECODE_H_