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