Planeshift
|
00001 /* xdelta 3 - delta compression tools and library 00002 * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007. Joshua P. MacDonald 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation; either version 2 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software 00016 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 */ 00018 00019 #ifndef _XDELTA3_DECODE_H_ 00020 #define _XDELTA3_DECODE_H_ 00021 00022 #define SRCORTGT(x) ((((x) & VCD_SRCORTGT) == VCD_SOURCE) ? \ 00023 VCD_SOURCE : ((((x) & VCD_SRCORTGT) == \ 00024 VCD_TARGET) ? VCD_TARGET : 0)) 00025 00026 /* Initialize the decoder for a new window. The dec_tgtlen value is 00027 * preserved across successive window decodings, and the update to 00028 * dec_winstart is delayed until a new window actually starts. This 00029 * is to avoid throwing an error due to overflow until the last 00030 * possible moment. This makes it possible to encode exactly 4GB 00031 * through a 32-bit encoder. */ 00032 static int 00033 xd3_decode_init_window (xd3_stream *stream) 00034 { 00035 stream->dec_cpylen = 0; 00036 stream->dec_cpyoff = 0; 00037 stream->dec_cksumbytes = 0; 00038 00039 xd3_init_cache (& stream->acache); 00040 00041 return 0; 00042 } 00043 00044 /* Allocates buffer space for the target window and possibly the 00045 * VCD_TARGET copy-window. Also sets the base of the two copy 00046 * segments. */ 00047 static int 00048 xd3_decode_setup_buffers (xd3_stream *stream) 00049 { 00050 /* If VCD_TARGET is set then the previous buffer may be reused. */ 00051 if (stream->dec_win_ind & VCD_TARGET) 00052 { 00053 /* But this implementation only supports copying from the last 00054 * target window. If the offset is outside that range, it can't 00055 * be done. */ 00056 if (stream->dec_cpyoff < stream->dec_laststart) 00057 { 00058 stream->msg = "unsupported VCD_TARGET offset"; 00059 return XD3_INVALID_INPUT; 00060 } 00061 00062 /* See if the two windows are the same. This indicates the 00063 * first time VCD_TARGET is used. This causes a second buffer 00064 * to be allocated, after that the two are swapped in the 00065 * DEC_FINISH case. */ 00066 if (stream->dec_lastwin == stream->next_out) 00067 { 00068 stream->next_out = NULL; 00069 stream->space_out = 0; 00070 } 00071 00072 // TODO: VCD_TARGET mode, this is broken 00073 stream->dec_cpyaddrbase = stream->dec_lastwin + 00074 (usize_t) (stream->dec_cpyoff - stream->dec_laststart); 00075 } 00076 00077 /* See if the current output window is large enough. */ 00078 if (stream->space_out < stream->dec_tgtlen) 00079 { 00080 xd3_free (stream, stream->dec_buffer); 00081 00082 stream->space_out = 00083 xd3_round_blksize (stream->dec_tgtlen, XD3_ALLOCSIZE); 00084 00085 if ((stream->dec_buffer = 00086 (uint8_t*) xd3_alloc (stream, stream->space_out, 1)) == NULL) 00087 { 00088 return ENOMEM; 00089 } 00090 00091 stream->next_out = stream->dec_buffer; 00092 } 00093 00094 /* dec_tgtaddrbase refers to an invalid base address, but it is 00095 * always used with a sufficiently large instruction offset (i.e., 00096 * beyond the copy window). This condition is enforced by 00097 * xd3_decode_output_halfinst. */ 00098 stream->dec_tgtaddrbase = stream->next_out - stream->dec_cpylen; 00099 00100 return 0; 00101 } 00102 00103 static int 00104 xd3_decode_allocate (xd3_stream *stream, 00105 usize_t size, 00106 uint8_t **buf_ptr, 00107 usize_t *buf_alloc) 00108 { 00109 if (*buf_ptr != NULL && *buf_alloc < size) 00110 { 00111 xd3_free (stream, *buf_ptr); 00112 *buf_ptr = NULL; 00113 } 00114 00115 if (*buf_ptr == NULL) 00116 { 00117 *buf_alloc = xd3_round_blksize (size, XD3_ALLOCSIZE); 00118 00119 if ((*buf_ptr = (uint8_t*) xd3_alloc (stream, *buf_alloc, 1)) == NULL) 00120 { 00121 return ENOMEM; 00122 } 00123 } 00124 00125 return 0; 00126 } 00127 00128 static int 00129 xd3_decode_section (xd3_stream *stream, 00130 xd3_desect *section, 00131 xd3_decode_state nstate, 00132 int copy) 00133 { 00134 XD3_ASSERT (section->pos <= section->size); 00135 XD3_ASSERT (stream->dec_state != nstate); 00136 00137 if (section->pos < section->size) 00138 { 00139 usize_t sect_take; 00140 00141 if (stream->avail_in == 0) 00142 { 00143 return XD3_INPUT; 00144 } 00145 00146 if ((copy == 0) && (section->pos == 0)) 00147 { 00148 /* No allocation/copy needed */ 00149 section->buf = stream->next_in; 00150 sect_take = section->size; 00151 } 00152 else 00153 { 00154 usize_t sect_need = section->size - section->pos; 00155 00156 /* Allocate and copy */ 00157 sect_take = min (sect_need, stream->avail_in); 00158 00159 if (section->pos == 0) 00160 { 00161 int ret; 00162 00163 if ((ret = xd3_decode_allocate (stream, 00164 section->size, 00165 & section->copied1, 00166 & section->alloc1))) 00167 { 00168 return ret; 00169 } 00170 00171 section->buf = section->copied1; 00172 } 00173 00174 memcpy (section->copied1 + section->pos, 00175 stream->next_in, 00176 sect_take); 00177 } 00178 00179 section->pos += sect_take; 00180 00181 stream->dec_winbytes += sect_take; 00182 00183 DECODE_INPUT (sect_take); 00184 } 00185 00186 if (section->pos < section->size) 00187 { 00188 stream->msg = "further input required"; 00189 return XD3_INPUT; 00190 } 00191 00192 XD3_ASSERT (section->pos == section->size); 00193 00194 stream->dec_state = nstate; 00195 section->buf_max = section->buf + section->size; 00196 section->pos = 0; 00197 return 0; 00198 } 00199 00200 /* Decode the size and address for half of an instruction (i.e., a 00201 * single opcode). This updates the stream->dec_position, which are 00202 * bytes already output prior to processing this instruction. Perform 00203 * bounds checking for sizes and copy addresses, which uses the 00204 * dec_position (which is why these checks are done here). */ 00205 static int 00206 xd3_decode_parse_halfinst (xd3_stream *stream, xd3_hinst *inst) 00207 { 00208 int ret; 00209 00210 /* If the size from the instruction table is zero then read a size value. */ 00211 if ((inst->size == 0) && 00212 (ret = xd3_read_size (stream, 00213 & stream->inst_sect.buf, 00214 stream->inst_sect.buf_max, 00215 & inst->size))) 00216 { 00217 return XD3_INVALID_INPUT; 00218 } 00219 00220 /* For copy instructions, read address. */ 00221 if (inst->type >= XD3_CPY) 00222 { 00223 IF_DEBUG2 ({ 00224 static int cnt = 0; 00225 DP(RINT "DECODE:%u: COPY at %"Q"u (winoffset %u) size %u winaddr %u\n", 00226 cnt++, 00227 stream->total_out + (stream->dec_position - 00228 stream->dec_cpylen), 00229 (stream->dec_position - stream->dec_cpylen), 00230 inst->size, 00231 inst->addr); 00232 }); 00233 00234 if ((ret = xd3_decode_address (stream, 00235 stream->dec_position, 00236 inst->type - XD3_CPY, 00237 & stream->addr_sect.buf, 00238 stream->addr_sect.buf_max, 00239 & inst->addr))) 00240 { 00241 return ret; 00242 } 00243 00244 /* Cannot copy an address before it is filled-in. */ 00245 if (inst->addr >= stream->dec_position) 00246 { 00247 stream->msg = "address too large"; 00248 return XD3_INVALID_INPUT; 00249 } 00250 00251 /* Check: a VCD_TARGET or VCD_SOURCE copy cannot exceed the remaining 00252 * buffer space in its own segment. */ 00253 if (inst->addr < stream->dec_cpylen && 00254 inst->addr + inst->size > stream->dec_cpylen) 00255 { 00256 stream->msg = "size too large"; 00257 return XD3_INVALID_INPUT; 00258 } 00259 } 00260 else 00261 { 00262 IF_DEBUG2 ({ 00263 if (inst->type == XD3_ADD) 00264 { 00265 static int cnt; 00266 DP(RINT "DECODE:%d: ADD at %"Q"u (winoffset %u) size %u\n", 00267 cnt++, 00268 (stream->total_out + stream->dec_position - stream->dec_cpylen), 00269 stream->dec_position - stream->dec_cpylen, 00270 inst->size); 00271 } 00272 else 00273 { 00274 static int cnt; 00275 XD3_ASSERT (inst->type == XD3_RUN); 00276 DP(RINT "DECODE:%d: RUN at %"Q"u (winoffset %u) size %u\n", 00277 cnt++, 00278 stream->total_out + stream->dec_position - stream->dec_cpylen, 00279 stream->dec_position - stream->dec_cpylen, 00280 inst->size); 00281 } 00282 }); 00283 } 00284 00285 /* Check: The instruction will not overflow the output buffer. */ 00286 if (stream->dec_position + inst->size > stream->dec_maxpos) 00287 { 00288 stream->msg = "size too large"; 00289 return XD3_INVALID_INPUT; 00290 } 00291 00292 stream->dec_position += inst->size; 00293 return 0; 00294 } 00295 00296 /* Decode a single opcode and then decode the two half-instructions. */ 00297 static int 00298 xd3_decode_instruction (xd3_stream *stream) 00299 { 00300 int ret; 00301 const xd3_dinst *inst; 00302 00303 if (stream->inst_sect.buf == stream->inst_sect.buf_max) 00304 { 00305 stream->msg = "instruction underflow"; 00306 return XD3_INVALID_INPUT; 00307 } 00308 00309 inst = &stream->code_table[*stream->inst_sect.buf++]; 00310 00311 stream->dec_current1.type = inst->type1; 00312 stream->dec_current2.type = inst->type2; 00313 stream->dec_current1.size = inst->size1; 00314 stream->dec_current2.size = inst->size2; 00315 00316 /* For each instruction with a real operation, decode the 00317 * corresponding size and addresses if necessary. Assume a 00318 * code-table may have NOOP in either position, although this is 00319 * unlikely. */ 00320 if (inst->type1 != XD3_NOOP && 00321 (ret = xd3_decode_parse_halfinst (stream, & stream->dec_current1))) 00322 { 00323 return ret; 00324 } 00325 if (inst->type2 != XD3_NOOP && 00326 (ret = xd3_decode_parse_halfinst (stream, & stream->dec_current2))) 00327 { 00328 return ret; 00329 } 00330 return 0; 00331 } 00332 00333 /* Output the result of a single half-instruction. OPT: This the 00334 decoder hotspot. Modifies "hinst", see below. */ 00335 static int 00336 xd3_decode_output_halfinst (xd3_stream *stream, xd3_hinst *inst) 00337 { 00338 /* This method is reentrant for copy instructions which may return 00339 * XD3_GETSRCBLK to the caller. Each time through a copy takes the 00340 * minimum of inst->size and the available space on whichever block 00341 * supplies the data */ 00342 usize_t take = inst->size; 00343 00344 XD3_ASSERT (inst->type != XD3_NOOP); 00345 00346 switch (inst->type) 00347 { 00348 case XD3_RUN: 00349 { 00350 /* Only require a single data byte. */ 00351 if (stream->data_sect.buf == stream->data_sect.buf_max) 00352 { 00353 stream->msg = "data underflow"; 00354 return XD3_INVALID_INPUT; 00355 } 00356 00357 memset (stream->next_out + stream->avail_out, 00358 stream->data_sect.buf[0], 00359 take); 00360 00361 stream->data_sect.buf += 1; 00362 stream->avail_out += take; 00363 inst->type = XD3_NOOP; 00364 break; 00365 } 00366 case XD3_ADD: 00367 { 00368 /* Require at least TAKE data bytes. */ 00369 if (stream->data_sect.buf + take > stream->data_sect.buf_max) 00370 { 00371 stream->msg = "data underflow"; 00372 return XD3_INVALID_INPUT; 00373 } 00374 00375 memcpy (stream->next_out + stream->avail_out, 00376 stream->data_sect.buf, 00377 take); 00378 00379 stream->data_sect.buf += take; 00380 stream->avail_out += take; 00381 inst->type = XD3_NOOP; 00382 break; 00383 } 00384 default: 00385 { 00386 usize_t i; 00387 const uint8_t *src; 00388 uint8_t *dst; 00389 int overlap; 00390 00391 /* See if it copies from the VCD_TARGET/VCD_SOURCE window or 00392 * the target window. Out-of-bounds checks for the addresses 00393 * and sizes are performed in xd3_decode_parse_halfinst. This 00394 * if/else must set "overlap", "src", and "dst". */ 00395 if (inst->addr < stream->dec_cpylen) 00396 { 00397 /* In both branches we are copying from outside the 00398 * current decoder window, the first (VCD_TARGET) is 00399 * unimplemented. */ 00400 overlap = 0; 00401 00402 /* This branch sets "src". As a side-effect, we modify 00403 * "inst" so that if we reenter this method after a 00404 * XD3_GETSRCBLK response the state is correct. So if the 00405 * instruction can be fulfilled by a contiguous block of 00406 * memory then we will set: 00407 * 00408 * inst->type = XD3_NOOP; 00409 * inst->size = 0; 00410 */ 00411 if (stream->dec_win_ind & VCD_TARGET) 00412 { 00413 /* TODO: Users have requested long-distance copies of 00414 * similar material within a target (e.g., for dup 00415 * supression in backups). */ 00416 inst->size = 0; 00417 inst->type = XD3_NOOP; 00418 stream->msg = "VCD_TARGET not implemented"; 00419 return XD3_UNIMPLEMENTED; 00420 } 00421 else 00422 { 00423 /* In this case we have to read a source block, which 00424 * could return control to the caller. We need to 00425 * know the first block number needed for this 00426 * copy. */ 00427 xd3_source *source = stream->src; 00428 xoff_t block = source->cpyoff_blocks; 00429 usize_t blkoff = source->cpyoff_blkoff; 00430 const usize_t blksize = source->blksize; 00431 int ret; 00432 00433 xd3_blksize_add (&block, &blkoff, source, inst->addr); 00434 XD3_ASSERT (blkoff < blksize); 00435 00436 if ((ret = xd3_getblk (stream, block))) 00437 { 00438 /* could be a XD3_GETSRCBLK failure. */ 00439 if (ret == XD3_TOOFARBACK) 00440 { 00441 stream->msg = "non-seekable source in decode"; 00442 ret = XD3_INTERNAL; 00443 } 00444 return ret; 00445 } 00446 00447 src = source->curblk + blkoff; 00448 00449 /* This block is either full, or a partial block that 00450 * must contain enough bytes. */ 00451 if ((source->onblk != blksize) && 00452 (blkoff + take > source->onblk)) 00453 { 00454 IF_DEBUG1(DP(RINT "[srcfile] short at blkno %"Q"u onblk " 00455 "%u blksize %u blkoff %u take %u\n", 00456 block, 00457 source->onblk, 00458 blksize, 00459 blkoff, 00460 take)); 00461 stream->msg = "source file too short"; 00462 return XD3_INVALID_INPUT; 00463 } 00464 00465 XD3_ASSERT (blkoff != blksize); 00466 00467 /* Check if we have enough data on this block to 00468 * finish the instruction. */ 00469 if (blkoff + take <= blksize) 00470 { 00471 inst->type = XD3_NOOP; 00472 inst->size = 0; 00473 } 00474 else 00475 { 00476 take = blksize - blkoff; 00477 inst->size -= take; 00478 inst->addr += take; 00479 00480 /* because (blkoff + take > blksize), above */ 00481 XD3_ASSERT (inst->size != 0); 00482 } 00483 } 00484 } 00485 else 00486 { 00487 /* TODO: the memcpy/overlap optimization, etc. Overlap 00488 * here could be more specific, it's whether (inst->addr - 00489 * srclen) + inst->size > input_pos ? And is the system 00490 * memcpy really any good? */ 00491 overlap = 1; 00492 00493 /* For a target-window copy, we know the entire range is 00494 * in-memory. The dec_tgtaddrbase is negatively offset by 00495 * dec_cpylen because the addresses start beyond that 00496 * point. */ 00497 src = stream->dec_tgtaddrbase + inst->addr; 00498 inst->type = XD3_NOOP; 00499 inst->size = 0; 00500 } 00501 00502 dst = stream->next_out + stream->avail_out; 00503 00504 stream->avail_out += take; 00505 00506 if (overlap) 00507 { 00508 /* Can't just memcpy here due to possible overlap. */ 00509 for (i = take; i != 0; i -= 1) 00510 { 00511 *dst++ = *src++; 00512 } 00513 } 00514 else 00515 { 00516 memcpy (dst, src, take); 00517 } 00518 } 00519 } 00520 00521 return 0; 00522 } 00523 00524 static int 00525 xd3_decode_finish_window (xd3_stream *stream) 00526 { 00527 stream->dec_winbytes = 0; 00528 stream->dec_state = DEC_FINISH; 00529 00530 stream->data_sect.pos = 0; 00531 stream->inst_sect.pos = 0; 00532 stream->addr_sect.pos = 0; 00533 00534 return XD3_OUTPUT; 00535 } 00536 00537 static int 00538 xd3_decode_secondary_sections (xd3_stream *secondary_stream) 00539 { 00540 #if SECONDARY_ANY 00541 int ret; 00542 #define DECODE_SECONDARY_SECTION(UPPER,LOWER) \ 00543 ((secondary_stream->dec_del_ind & VCD_ ## UPPER ## COMP) && \ 00544 (ret = xd3_decode_secondary (secondary_stream, \ 00545 & secondary_stream-> LOWER ## _sect, \ 00546 & xd3_sec_ ## LOWER (secondary_stream)))) 00547 00548 if (DECODE_SECONDARY_SECTION (DATA, data) || 00549 DECODE_SECONDARY_SECTION (INST, inst) || 00550 DECODE_SECONDARY_SECTION (ADDR, addr)) 00551 { 00552 return ret; 00553 } 00554 #undef DECODE_SECONDARY_SECTION 00555 #endif 00556 return 0; 00557 } 00558 00559 static int 00560 xd3_decode_sections (xd3_stream *stream) 00561 { 00562 usize_t need, more, take; 00563 int copy, ret; 00564 00565 if ((stream->flags & XD3_JUST_HDR) != 0) 00566 { 00567 /* Nothing left to do. */ 00568 return xd3_decode_finish_window (stream); 00569 } 00570 00571 /* To avoid copying, need this much data available */ 00572 need = (stream->inst_sect.size + 00573 stream->addr_sect.size + 00574 stream->data_sect.size); 00575 00576 /* The window may be entirely processed. */ 00577 XD3_ASSERT (stream->dec_winbytes <= need); 00578 00579 /* Compute how much more input is needed. */ 00580 more = (need - stream->dec_winbytes); 00581 00582 /* How much to consume. */ 00583 take = min (more, stream->avail_in); 00584 00585 /* See if the input is completely available, to avoid copy. */ 00586 copy = (take != more); 00587 00588 /* If the window is skipped... */ 00589 if ((stream->flags & XD3_SKIP_WINDOW) != 0) 00590 { 00591 /* Skip the available input. */ 00592 DECODE_INPUT (take); 00593 00594 stream->dec_winbytes += take; 00595 00596 if (copy) 00597 { 00598 stream->msg = "further input required"; 00599 return XD3_INPUT; 00600 } 00601 00602 return xd3_decode_finish_window (stream); 00603 } 00604 00605 /* Process all but the DATA section. */ 00606 switch (stream->dec_state) 00607 { 00608 default: 00609 stream->msg = "internal error"; 00610 return XD3_INVALID_INPUT; 00611 00612 case DEC_DATA: 00613 if ((ret = xd3_decode_section (stream, & stream->data_sect, 00614 DEC_INST, copy))) { return ret; } 00615 case DEC_INST: 00616 if ((ret = xd3_decode_section (stream, & stream->inst_sect, 00617 DEC_ADDR, copy))) { return ret; } 00618 case DEC_ADDR: 00619 if ((ret = xd3_decode_section (stream, & stream->addr_sect, 00620 DEC_EMIT, copy))) { return ret; } 00621 } 00622 00623 XD3_ASSERT (stream->dec_winbytes == need); 00624 00625 if ((ret = xd3_decode_secondary_sections (stream))) { return ret; } 00626 00627 if (stream->flags & XD3_SKIP_EMIT) 00628 { 00629 return xd3_decode_finish_window (stream); 00630 } 00631 00632 /* OPT: A possible optimization is to avoid allocating memory in 00633 * decode_setup_buffers and to avoid a large memcpy when the window 00634 * consists of a single VCD_SOURCE copy instruction. */ 00635 if ((ret = xd3_decode_setup_buffers (stream))) { return ret; } 00636 00637 return 0; 00638 } 00639 00640 static int 00641 xd3_decode_emit (xd3_stream *stream) 00642 { 00643 int ret; 00644 00645 /* Produce output: originally structured to allow reentrant code 00646 * that fills as much of the output buffer as possible, but VCDIFF 00647 * semantics allows to copy from anywhere from the target window, so 00648 * instead allocate a sufficiently sized buffer after the target 00649 * window length is decoded. 00650 * 00651 * This code still needs to be reentrant to allow XD3_GETSRCBLK to 00652 * return control. This is handled by setting the 00653 * stream->dec_currentN instruction types to XD3_NOOP after they 00654 * have been processed. */ 00655 XD3_ASSERT (! (stream->flags & XD3_SKIP_EMIT)); 00656 XD3_ASSERT (stream->dec_tgtlen <= stream->space_out); 00657 00658 while (stream->inst_sect.buf != stream->inst_sect.buf_max || 00659 stream->dec_current1.type != XD3_NOOP || 00660 stream->dec_current2.type != XD3_NOOP) 00661 { 00662 /* Decode next instruction pair. */ 00663 if ((stream->dec_current1.type == XD3_NOOP) && 00664 (stream->dec_current2.type == XD3_NOOP) && 00665 (ret = xd3_decode_instruction (stream))) { return ret; } 00666 00667 /* Output dec_current1 */ 00668 while ((stream->dec_current1.type != XD3_NOOP)) 00669 { 00670 if ((ret = xd3_decode_output_halfinst (stream, & stream->dec_current1))) 00671 { 00672 return ret; 00673 } 00674 } 00675 /* Output dec_current2 */ 00676 while (stream->dec_current2.type != XD3_NOOP) 00677 { 00678 if ((ret = xd3_decode_output_halfinst (stream, & stream->dec_current2))) 00679 { 00680 return ret; 00681 } 00682 } 00683 } 00684 00685 if (stream->avail_out != stream->dec_tgtlen) 00686 { 00687 IF_DEBUG2 (DP(RINT "AVAIL_OUT(%d) != DEC_TGTLEN(%d)\n", 00688 stream->avail_out, stream->dec_tgtlen)); 00689 stream->msg = "wrong window length"; 00690 return XD3_INVALID_INPUT; 00691 } 00692 00693 if (stream->data_sect.buf != stream->data_sect.buf_max) 00694 { 00695 stream->msg = "extra data section"; 00696 return XD3_INVALID_INPUT; 00697 } 00698 00699 if (stream->addr_sect.buf != stream->addr_sect.buf_max) 00700 { 00701 stream->msg = "extra address section"; 00702 return XD3_INVALID_INPUT; 00703 } 00704 00705 /* OPT: Should cksum computation be combined with the above loop? */ 00706 if ((stream->dec_win_ind & VCD_ADLER32) != 0 && 00707 (stream->flags & XD3_ADLER32_NOVER) == 0) 00708 { 00709 uint32_t a32 = adler32 (1L, stream->next_out, stream->avail_out); 00710 00711 if (a32 != stream->dec_adler32) 00712 { 00713 stream->msg = "target window checksum mismatch"; 00714 return XD3_INVALID_INPUT; 00715 } 00716 } 00717 00718 /* Finished with a window. */ 00719 return xd3_decode_finish_window (stream); 00720 } 00721 00722 int 00723 xd3_decode_input (xd3_stream *stream) 00724 { 00725 int ret; 00726 00727 if (stream->enc_state != 0) 00728 { 00729 stream->msg = "encoder/decoder transition"; 00730 return XD3_INVALID_INPUT; 00731 } 00732 00733 #define BYTE_CASE(expr,x,nstate) \ 00734 do { \ 00735 if ( (expr) && \ 00736 ((ret = xd3_decode_byte (stream, & (x))) != 0) ) { return ret; } \ 00737 stream->dec_state = (nstate); \ 00738 } while (0) 00739 00740 #define OFFSET_CASE(expr,x,nstate) \ 00741 do { \ 00742 if ( (expr) && \ 00743 ((ret = xd3_decode_offset (stream, & (x))) != 0) ) { return ret; } \ 00744 stream->dec_state = (nstate); \ 00745 } while (0) 00746 00747 #define SIZE_CASE(expr,x,nstate) \ 00748 do { \ 00749 if ( (expr) && \ 00750 ((ret = xd3_decode_size (stream, & (x))) != 0) ) { return ret; } \ 00751 stream->dec_state = (nstate); \ 00752 } while (0) 00753 00754 switch (stream->dec_state) 00755 { 00756 case DEC_VCHEAD: 00757 { 00758 if ((ret = xd3_decode_bytes (stream, stream->dec_magic, 00759 & stream->dec_magicbytes, 4))) 00760 { 00761 return ret; 00762 } 00763 00764 if (stream->dec_magic[0] != VCDIFF_MAGIC1 || 00765 stream->dec_magic[1] != VCDIFF_MAGIC2 || 00766 stream->dec_magic[2] != VCDIFF_MAGIC3) 00767 { 00768 stream->msg = "not a VCDIFF input"; 00769 return XD3_INVALID_INPUT; 00770 } 00771 00772 if (stream->dec_magic[3] != 0) 00773 { 00774 stream->msg = "VCDIFF input version > 0 is not supported"; 00775 return XD3_INVALID_INPUT; 00776 } 00777 00778 stream->dec_state = DEC_HDRIND; 00779 } 00780 case DEC_HDRIND: 00781 { 00782 if ((ret = xd3_decode_byte (stream, & stream->dec_hdr_ind))) 00783 { 00784 return ret; 00785 } 00786 00787 if ((stream->dec_hdr_ind & VCD_INVHDR) != 0) 00788 { 00789 stream->msg = "unrecognized header indicator bits set"; 00790 return XD3_INVALID_INPUT; 00791 } 00792 00793 stream->dec_state = DEC_SECONDID; 00794 } 00795 00796 case DEC_SECONDID: 00797 /* Secondary compressor ID: only if VCD_SECONDARY is set */ 00798 if ((stream->dec_hdr_ind & VCD_SECONDARY) != 0) 00799 { 00800 BYTE_CASE (1, stream->dec_secondid, DEC_TABLEN); 00801 00802 switch (stream->dec_secondid) 00803 { 00804 case VCD_FGK_ID: 00805 FGK_CASE (stream); 00806 case VCD_DJW_ID: 00807 DJW_CASE (stream); 00808 default: 00809 stream->msg = "unknown secondary compressor ID"; 00810 return XD3_INVALID_INPUT; 00811 } 00812 } 00813 00814 case DEC_TABLEN: 00815 /* Length of code table data: only if VCD_CODETABLE is set */ 00816 SIZE_CASE ((stream->dec_hdr_ind & VCD_CODETABLE) != 0, 00817 stream->dec_codetblsz, DEC_NEAR); 00818 00819 /* The codetblsz counts the two NEAR/SAME bytes */ 00820 if ((stream->dec_hdr_ind & VCD_CODETABLE) != 0) { 00821 if (stream->dec_codetblsz <= 2) { 00822 stream->msg = "invalid code table size"; 00823 return ENOMEM; 00824 } 00825 stream->dec_codetblsz -= 2; 00826 } 00827 case DEC_NEAR: 00828 /* Near modes: only if VCD_CODETABLE is set */ 00829 BYTE_CASE((stream->dec_hdr_ind & VCD_CODETABLE) != 0, 00830 stream->acache.s_near, DEC_SAME); 00831 case DEC_SAME: 00832 /* Same modes: only if VCD_CODETABLE is set */ 00833 BYTE_CASE((stream->dec_hdr_ind & VCD_CODETABLE) != 0, 00834 stream->acache.s_same, DEC_TABDAT); 00835 case DEC_TABDAT: 00836 /* Compressed code table data */ 00837 00838 if ((stream->dec_hdr_ind & VCD_CODETABLE) != 0) 00839 { 00840 /* Get the code table data. */ 00841 if ((stream->dec_codetbl == NULL) && 00842 (stream->dec_codetbl = 00843 (uint8_t*) xd3_alloc (stream, 00844 stream->dec_codetblsz, 1)) == NULL) 00845 { 00846 return ENOMEM; 00847 } 00848 00849 if ((ret = xd3_decode_bytes (stream, stream->dec_codetbl, 00850 & stream->dec_codetblbytes, 00851 stream->dec_codetblsz))) 00852 { 00853 return ret; 00854 } 00855 00856 if ((ret = xd3_apply_table_encoding (stream, stream->dec_codetbl, 00857 stream->dec_codetblbytes))) 00858 { 00859 return ret; 00860 } 00861 } 00862 else 00863 { 00864 /* Use the default table. */ 00865 stream->acache.s_near = __rfc3284_code_table_desc.near_modes; 00866 stream->acache.s_same = __rfc3284_code_table_desc.same_modes; 00867 stream->code_table = xd3_rfc3284_code_table (); 00868 } 00869 00870 if ((ret = xd3_alloc_cache (stream))) { return ret; } 00871 00872 stream->dec_state = DEC_APPLEN; 00873 00874 case DEC_APPLEN: 00875 /* Length of application data */ 00876 SIZE_CASE((stream->dec_hdr_ind & VCD_APPHEADER) != 0, 00877 stream->dec_appheadsz, DEC_APPDAT); 00878 00879 case DEC_APPDAT: 00880 /* Application data */ 00881 if (stream->dec_hdr_ind & VCD_APPHEADER) 00882 { 00883 /* Note: we add an additional byte for padding, to allow 00884 0-termination. */ 00885 if ((stream->dec_appheader == NULL) && 00886 (stream->dec_appheader = 00887 (uint8_t*) xd3_alloc (stream, 00888 stream->dec_appheadsz+1, 1)) == NULL) 00889 { 00890 return ENOMEM; 00891 } 00892 00893 stream->dec_appheader[stream->dec_appheadsz] = 0; 00894 00895 if ((ret = xd3_decode_bytes (stream, stream->dec_appheader, 00896 & stream->dec_appheadbytes, 00897 stream->dec_appheadsz))) 00898 { 00899 return ret; 00900 } 00901 } 00902 00903 /* xoff_t -> usize_t is safe because this is the first block. */ 00904 stream->dec_hdrsize = (usize_t) stream->total_in; 00905 stream->dec_state = DEC_WININD; 00906 00907 case DEC_WININD: 00908 { 00909 /* Start of a window: the window indicator */ 00910 if ((ret = xd3_decode_byte (stream, & stream->dec_win_ind))) 00911 { 00912 return ret; 00913 } 00914 00915 stream->current_window = stream->dec_window_count; 00916 00917 if (XOFF_T_OVERFLOW (stream->dec_winstart, stream->dec_tgtlen)) 00918 { 00919 stream->msg = "decoder file offset overflow"; 00920 return XD3_INVALID_INPUT; 00921 } 00922 00923 stream->dec_winstart += stream->dec_tgtlen; 00924 00925 if ((stream->dec_win_ind & VCD_INVWIN) != 0) 00926 { 00927 stream->msg = "unrecognized window indicator bits set"; 00928 return XD3_INVALID_INPUT; 00929 } 00930 00931 if ((ret = xd3_decode_init_window (stream))) { return ret; } 00932 00933 stream->dec_state = DEC_CPYLEN; 00934 00935 IF_DEBUG2 (DP(RINT "--------- TARGET WINDOW %"Q"u -----------\n", 00936 stream->current_window)); 00937 } 00938 00939 case DEC_CPYLEN: 00940 /* Copy window length: only if VCD_SOURCE or VCD_TARGET is set */ 00941 SIZE_CASE(SRCORTGT (stream->dec_win_ind), stream->dec_cpylen, 00942 DEC_CPYOFF); 00943 00944 /* Set the initial, logical decoder position (HERE address) in 00945 * dec_position. This is set to just after the source/copy 00946 * window, as we are just about to output the first byte of 00947 * target window. */ 00948 stream->dec_position = stream->dec_cpylen; 00949 00950 case DEC_CPYOFF: 00951 /* Copy window offset: only if VCD_SOURCE or VCD_TARGET is set */ 00952 OFFSET_CASE(SRCORTGT (stream->dec_win_ind), stream->dec_cpyoff, 00953 DEC_ENCLEN); 00954 00955 /* Copy offset and copy length may not overflow. */ 00956 if (XOFF_T_OVERFLOW (stream->dec_cpyoff, stream->dec_cpylen)) 00957 { 00958 stream->msg = "decoder copy window overflows a file offset"; 00959 return XD3_INVALID_INPUT; 00960 } 00961 00962 /* Check copy window bounds: VCD_TARGET window may not exceed 00963 current position. */ 00964 if ((stream->dec_win_ind & VCD_TARGET) && 00965 (stream->dec_cpyoff + (xoff_t) stream->dec_cpylen > 00966 stream->dec_winstart)) 00967 { 00968 stream->msg = "VCD_TARGET window out of bounds"; 00969 return XD3_INVALID_INPUT; 00970 } 00971 00972 case DEC_ENCLEN: 00973 /* Length of the delta encoding */ 00974 SIZE_CASE(1, stream->dec_enclen, DEC_TGTLEN); 00975 case DEC_TGTLEN: 00976 /* Length of target window */ 00977 SIZE_CASE(1, stream->dec_tgtlen, DEC_DELIND); 00978 00979 /* Set the maximum decoder position, beyond which we should not 00980 * decode any data. This is the maximum value for dec_position. 00981 * This may not exceed the size of a usize_t. */ 00982 if (USIZE_T_OVERFLOW (stream->dec_cpylen, stream->dec_tgtlen)) 00983 { 00984 stream->msg = "decoder target window overflows a usize_t"; 00985 return XD3_INVALID_INPUT; 00986 } 00987 00988 /* Check for malicious files. */ 00989 if (stream->dec_tgtlen > XD3_HARDMAXWINSIZE) 00990 { 00991 stream->msg = "hard window size exceeded"; 00992 return XD3_INVALID_INPUT; 00993 } 00994 00995 stream->dec_maxpos = stream->dec_cpylen + stream->dec_tgtlen; 00996 00997 case DEC_DELIND: 00998 /* Delta indicator */ 00999 BYTE_CASE(1, stream->dec_del_ind, DEC_DATALEN); 01000 01001 if ((stream->dec_del_ind & VCD_INVDEL) != 0) 01002 { 01003 stream->msg = "unrecognized delta indicator bits set"; 01004 return XD3_INVALID_INPUT; 01005 } 01006 01007 /* Delta indicator is only used with secondary compression. */ 01008 if ((stream->dec_del_ind != 0) && (stream->sec_type == NULL)) 01009 { 01010 stream->msg = "invalid delta indicator bits set"; 01011 return XD3_INVALID_INPUT; 01012 } 01013 01014 /* Section lengths */ 01015 case DEC_DATALEN: 01016 SIZE_CASE(1, stream->data_sect.size, DEC_INSTLEN); 01017 case DEC_INSTLEN: 01018 SIZE_CASE(1, stream->inst_sect.size, DEC_ADDRLEN); 01019 case DEC_ADDRLEN: 01020 SIZE_CASE(1, stream->addr_sect.size, DEC_CKSUM); 01021 01022 case DEC_CKSUM: 01023 /* Window checksum. */ 01024 if ((stream->dec_win_ind & VCD_ADLER32) != 0) 01025 { 01026 int i; 01027 01028 if ((ret = xd3_decode_bytes (stream, stream->dec_cksum, 01029 & stream->dec_cksumbytes, 4))) 01030 { 01031 return ret; 01032 } 01033 01034 for (i = 0; i < 4; i += 1) 01035 { 01036 stream->dec_adler32 = 01037 (stream->dec_adler32 << 8) | stream->dec_cksum[i]; 01038 } 01039 } 01040 01041 stream->dec_state = DEC_DATA; 01042 01043 /* Check dec_enclen for redundency, otherwise it is not really used. */ 01044 { 01045 usize_t enclen_check = 01046 (1 + (xd3_sizeof_size (stream->dec_tgtlen) + 01047 xd3_sizeof_size (stream->data_sect.size) + 01048 xd3_sizeof_size (stream->inst_sect.size) + 01049 xd3_sizeof_size (stream->addr_sect.size)) + 01050 stream->data_sect.size + 01051 stream->inst_sect.size + 01052 stream->addr_sect.size + 01053 ((stream->dec_win_ind & VCD_ADLER32) ? 4 : 0)); 01054 01055 if (stream->dec_enclen != enclen_check) 01056 { 01057 stream->msg = "incorrect encoding length (redundent)"; 01058 return XD3_INVALID_INPUT; 01059 } 01060 } 01061 01062 /* Returning here gives the application a chance to inspect the 01063 * header, skip the window, etc. */ 01064 if (stream->current_window == 0) { return XD3_GOTHEADER; } 01065 else { return XD3_WINSTART; } 01066 01067 case DEC_DATA: 01068 case DEC_INST: 01069 case DEC_ADDR: 01070 /* Next read the three sections. */ 01071 if ((ret = xd3_decode_sections (stream))) { return ret; } 01072 01073 case DEC_EMIT: 01074 01075 /* To speed VCD_SOURCE block-address calculations, the source 01076 * cpyoff_blocks and cpyoff_blkoff are pre-computed. */ 01077 if (stream->dec_win_ind & VCD_SOURCE) 01078 { 01079 xd3_source *src = stream->src; 01080 01081 if (src == NULL) 01082 { 01083 stream->msg = "source input required"; 01084 return XD3_INVALID_INPUT; 01085 } 01086 01087 xd3_blksize_div(stream->dec_cpyoff, src, 01088 &src->cpyoff_blocks, 01089 &src->cpyoff_blkoff); 01090 01091 IF_DEBUG2(DP(RINT 01092 "decode cpyoff %"Q"u " 01093 "cpyblkno %"Q"u " 01094 "cpyblkoff %u " 01095 "blksize %u\n", 01096 stream->dec_cpyoff, 01097 src->cpyoff_blocks, 01098 src->cpyoff_blkoff, 01099 src->blksize)); 01100 } 01101 01102 /* xd3_decode_emit returns XD3_OUTPUT on every success. */ 01103 if ((ret = xd3_decode_emit (stream)) == XD3_OUTPUT) 01104 { 01105 stream->total_out += (xoff_t) stream->avail_out; 01106 } 01107 01108 return ret; 01109 01110 case DEC_FINISH: 01111 { 01112 if (stream->dec_win_ind & VCD_TARGET) 01113 { 01114 if (stream->dec_lastwin == NULL) 01115 { 01116 stream->dec_lastwin = stream->next_out; 01117 stream->dec_lastspace = stream->space_out; 01118 } 01119 else 01120 { 01121 xd3_swap_uint8p (& stream->dec_lastwin, 01122 & stream->next_out); 01123 xd3_swap_usize_t (& stream->dec_lastspace, 01124 & stream->space_out); 01125 } 01126 } 01127 01128 stream->dec_lastlen = stream->dec_tgtlen; 01129 stream->dec_laststart = stream->dec_winstart; 01130 stream->dec_window_count += 1; 01131 01132 /* Note: the updates to dec_winstart & current_window are 01133 * deferred until after the next DEC_WININD byte is read. */ 01134 stream->dec_state = DEC_WININD; 01135 return XD3_WINFINISH; 01136 } 01137 01138 default: 01139 stream->msg = "invalid state"; 01140 return XD3_INVALID_INPUT; 01141 } 01142 } 01143 01144 #endif // _XDELTA3_DECODE_H_