xdelta3-decode.h (xdelta3-3.0.10) | : | xdelta3-decode.h (xdelta3-3.0.11) | ||
---|---|---|---|---|
skipping to change at line 100 | skipping to change at line 100 | |||
/* Allocates buffer space for the target window and possibly the | /* Allocates buffer space for the target window and possibly the | |||
* VCD_TARGET copy-window. Also sets the base of the two copy | * VCD_TARGET copy-window. Also sets the base of the two copy | |||
* segments. */ | * segments. */ | |||
static int | static int | |||
xd3_decode_setup_buffers (xd3_stream *stream) | xd3_decode_setup_buffers (xd3_stream *stream) | |||
{ | { | |||
/* If VCD_TARGET is set then the previous buffer may be reused. */ | /* If VCD_TARGET is set then the previous buffer may be reused. */ | |||
if (stream->dec_win_ind & VCD_TARGET) | if (stream->dec_win_ind & VCD_TARGET) | |||
{ | { | |||
/* Note: this implementation is untested, since Xdelta3 itself | ||||
* does not implement an encoder for VCD_TARGET mode. Thus, mark | ||||
* unimplemented until needed. */ | ||||
if (1) | ||||
{ | ||||
stream->msg = "VCD_TARGET not implemented"; | ||||
return XD3_UNIMPLEMENTED; | ||||
} | ||||
/* But this implementation only supports copying from the last | /* But this implementation only supports copying from the last | |||
* target window. If the offset is outside that range, it can't | * target window. If the offset is outside that range, it can't | |||
* be done. */ | * be done. */ | |||
if (stream->dec_cpyoff < stream->dec_laststart) | if (stream->dec_cpyoff < stream->dec_laststart) | |||
{ | { | |||
stream->msg = "unsupported VCD_TARGET offset"; | stream->msg = "unsupported VCD_TARGET offset"; | |||
return XD3_INVALID_INPUT; | return XD3_INVALID_INPUT; | |||
} | } | |||
/* See if the two windows are the same. This indicates the | /* See if the two windows are the same. This indicates the | |||
* first time VCD_TARGET is used. This causes a second buffer | * first time VCD_TARGET is used. This causes a second buffer | |||
* to be allocated, after that the two are swapped in the | * to be allocated, after that the two are swapped in the | |||
* DEC_FINISH case. */ | * DEC_FINISH case. */ | |||
if (stream->dec_lastwin == stream->next_out) | if (stream->dec_lastwin == stream->next_out) | |||
{ | { | |||
stream->next_out = NULL; | stream->next_out = NULL; | |||
stream->space_out = 0; | stream->space_out = 0; | |||
} | } | |||
// TODO: VCD_TARGET mode, this is broken | /* TODO: (See note above, this looks incorrect) */ | |||
stream->dec_cpyaddrbase = stream->dec_lastwin + | stream->dec_cpyaddrbase = stream->dec_lastwin + | |||
(usize_t) (stream->dec_cpyoff - stream->dec_laststart); | (usize_t) (stream->dec_cpyoff - stream->dec_laststart); | |||
} | } | |||
/* See if the current output window is large enough. */ | /* See if the current output window is large enough. */ | |||
if (stream->space_out < stream->dec_tgtlen) | if (stream->space_out < stream->dec_tgtlen) | |||
{ | { | |||
xd3_free (stream, stream->dec_buffer); | xd3_free (stream, stream->dec_buffer); | |||
stream->space_out = | stream->space_out = | |||
skipping to change at line 156 | skipping to change at line 165 | |||
return 0; | return 0; | |||
} | } | |||
static int | static int | |||
xd3_decode_allocate (xd3_stream *stream, | xd3_decode_allocate (xd3_stream *stream, | |||
usize_t size, | usize_t size, | |||
uint8_t **buf_ptr, | uint8_t **buf_ptr, | |||
usize_t *buf_alloc) | usize_t *buf_alloc) | |||
{ | { | |||
IF_DEBUG2 (DP(RINT "[xd3_decode_allocate] size %u alloc %u\n", | ||||
size, *buf_alloc)); | ||||
if (*buf_ptr != NULL && *buf_alloc < size) | if (*buf_ptr != NULL && *buf_alloc < size) | |||
{ | { | |||
xd3_free (stream, *buf_ptr); | xd3_free (stream, *buf_ptr); | |||
*buf_ptr = NULL; | *buf_ptr = NULL; | |||
} | } | |||
if (*buf_ptr == NULL) | if (*buf_ptr == NULL) | |||
{ | { | |||
*buf_alloc = xd3_round_blksize (size, XD3_ALLOCSIZE); | *buf_alloc = xd3_round_blksize (size, XD3_ALLOCSIZE); | |||
skipping to change at line 198 | skipping to change at line 210 | |||
if (stream->avail_in == 0) | if (stream->avail_in == 0) | |||
{ | { | |||
return XD3_INPUT; | return XD3_INPUT; | |||
} | } | |||
if ((copy == 0) && (section->pos == 0)) | if ((copy == 0) && (section->pos == 0)) | |||
{ | { | |||
/* No allocation/copy needed */ | /* No allocation/copy needed */ | |||
section->buf = stream->next_in; | section->buf = stream->next_in; | |||
sect_take = section->size; | sect_take = section->size; | |||
IF_DEBUG1 (DP(RINT "[xd3_decode_section] zerocopy %u @ %u avail %u\n", | ||||
sect_take, section->pos, stream->avail_in)); | ||||
} | } | |||
else | else | |||
{ | { | |||
usize_t sect_need = section->size - section->pos; | usize_t sect_need = section->size - section->pos; | |||
/* Allocate and copy */ | /* Allocate and copy */ | |||
sect_take = xd3_min (sect_need, stream->avail_in); | sect_take = xd3_min (sect_need, stream->avail_in); | |||
if (section->pos == 0) | if (section->pos == 0) | |||
{ | { | |||
skipping to change at line 221 | skipping to change at line 235 | |||
section->size, | section->size, | |||
& section->copied1, | & section->copied1, | |||
& section->alloc1))) | & section->alloc1))) | |||
{ | { | |||
return ret; | return ret; | |||
} | } | |||
section->buf = section->copied1; | section->buf = section->copied1; | |||
} | } | |||
IF_DEBUG2 (DP(RINT "[xd3_decode_section] take %u @ %u [need %u] avail % | ||||
u\n", | ||||
sect_take, section->pos, sect_need, stream->avail_in)); | ||||
XD3_ASSERT (section->pos + sect_take <= section->alloc1); | ||||
memcpy (section->copied1 + section->pos, | memcpy (section->copied1 + section->pos, | |||
stream->next_in, | stream->next_in, | |||
sect_take); | sect_take); | |||
} | } | |||
section->pos += sect_take; | section->pos += sect_take; | |||
stream->dec_winbytes += sect_take; | stream->dec_winbytes += sect_take; | |||
DECODE_INPUT (sect_take); | DECODE_INPUT (sect_take); | |||
} | } | |||
if (section->pos < section->size) | if (section->pos < section->size) | |||
{ | { | |||
IF_DEBUG1 (DP(RINT "[xd3_decode_section] further input required %u\n", sec tion->size - section->pos)); | ||||
stream->msg = "further input required"; | stream->msg = "further input required"; | |||
return XD3_INPUT; | return XD3_INPUT; | |||
} | } | |||
XD3_ASSERT (section->pos == section->size); | XD3_ASSERT (section->pos == section->size); | |||
stream->dec_state = nstate; | stream->dec_state = nstate; | |||
section->buf_max = section->buf + section->size; | section->buf_max = section->buf + section->size; | |||
section->pos = 0; | section->pos = 0; | |||
return 0; | return 0; | |||
skipping to change at line 391 | skipping to change at line 410 | |||
decoder hotspot. Modifies "hinst", see below. */ | decoder hotspot. Modifies "hinst", see below. */ | |||
static int | static int | |||
xd3_decode_output_halfinst (xd3_stream *stream, xd3_hinst *inst) | xd3_decode_output_halfinst (xd3_stream *stream, xd3_hinst *inst) | |||
{ | { | |||
/* This method is reentrant for copy instructions which may return | /* This method is reentrant for copy instructions which may return | |||
* XD3_GETSRCBLK to the caller. Each time through a copy takes the | * XD3_GETSRCBLK to the caller. Each time through a copy takes the | |||
* minimum of inst->size and the available space on whichever block | * minimum of inst->size and the available space on whichever block | |||
* supplies the data */ | * supplies the data */ | |||
usize_t take = inst->size; | usize_t take = inst->size; | |||
if (USIZE_T_OVERFLOW (stream->avail_out, take) || | ||||
stream->avail_out + take > stream->space_out) | ||||
{ | ||||
stream->msg = "overflow while decoding"; | ||||
return XD3_INVALID_INPUT; | ||||
} | ||||
XD3_ASSERT (inst->type != XD3_NOOP); | XD3_ASSERT (inst->type != XD3_NOOP); | |||
switch (inst->type) | switch (inst->type) | |||
{ | { | |||
case XD3_RUN: | case XD3_RUN: | |||
{ | { | |||
/* Only require a single data byte. */ | /* Only require a single data byte. */ | |||
if (stream->data_sect.buf == stream->data_sect.buf_max) | if (stream->data_sect.buf == stream->data_sect.buf_max) | |||
{ | { | |||
stream->msg = "data underflow"; | stream->msg = "data underflow"; | |||
skipping to change at line 462 | skipping to change at line 488 | |||
* instruction can be fulfilled by a contiguous block of | * instruction can be fulfilled by a contiguous block of | |||
* memory then we will set: | * memory then we will set: | |||
* | * | |||
* inst->type = XD3_NOOP; | * inst->type = XD3_NOOP; | |||
* inst->size = 0; | * inst->size = 0; | |||
*/ | */ | |||
if (stream->dec_win_ind & VCD_TARGET) | if (stream->dec_win_ind & VCD_TARGET) | |||
{ | { | |||
/* TODO: Users have requested long-distance copies of | /* TODO: Users have requested long-distance copies of | |||
* similar material within a target (e.g., for dup | * similar material within a target (e.g., for dup | |||
* supression in backups). */ | * supression in backups). This code path is probably | |||
* dead due to XD3_UNIMPLEMENTED in xd3_decode_setup_buffers */ | ||||
inst->size = 0; | inst->size = 0; | |||
inst->type = XD3_NOOP; | inst->type = XD3_NOOP; | |||
stream->msg = "VCD_TARGET not implemented"; | stream->msg = "VCD_TARGET not implemented"; | |||
return XD3_UNIMPLEMENTED; | return XD3_UNIMPLEMENTED; | |||
} | } | |||
else | else | |||
{ | { | |||
/* In this case we have to read a source block, which | /* In this case we have to read a source block, which | |||
* could return control to the caller. We need to | * could return control to the caller. We need to | |||
* know the first block number needed for this | * know the first block number needed for this | |||
skipping to change at line 618 | skipping to change at line 645 | |||
{ | { | |||
usize_t need, more, take; | usize_t need, more, take; | |||
int copy, ret; | int copy, ret; | |||
if ((stream->flags & XD3_JUST_HDR) != 0) | if ((stream->flags & XD3_JUST_HDR) != 0) | |||
{ | { | |||
/* Nothing left to do. */ | /* Nothing left to do. */ | |||
return xd3_decode_finish_window (stream); | return xd3_decode_finish_window (stream); | |||
} | } | |||
/* To avoid copying, need this much data available */ | /* To avoid extra copying, allocate three sections at once (but | |||
need = (stream->inst_sect.size + | * check for overflow). */ | |||
stream->addr_sect.size + | need = stream->inst_sect.size; | |||
stream->data_sect.size); | ||||
if (USIZE_T_OVERFLOW (need, stream->addr_sect.size)) | ||||
{ | ||||
stream->msg = "decoder section size overflow"; | ||||
return XD3_INTERNAL; | ||||
} | ||||
need += stream->addr_sect.size; | ||||
if (USIZE_T_OVERFLOW (need, stream->data_sect.size)) | ||||
{ | ||||
stream->msg = "decoder section size overflow"; | ||||
return XD3_INTERNAL; | ||||
} | ||||
need += stream->data_sect.size; | ||||
/* The window may be entirely processed. */ | /* The window may be entirely processed. */ | |||
XD3_ASSERT (stream->dec_winbytes <= need); | XD3_ASSERT (stream->dec_winbytes <= need); | |||
/* Compute how much more input is needed. */ | /* Compute how much more input is needed. */ | |||
more = (need - stream->dec_winbytes); | more = (need - stream->dec_winbytes); | |||
/* How much to consume. */ | /* How much to consume. */ | |||
take = xd3_min (more, stream->avail_in); | take = xd3_min (more, stream->avail_in); | |||
skipping to change at line 889 | skipping to change at line 929 | |||
stream->acache.s_near, DEC_SAME); | stream->acache.s_near, DEC_SAME); | |||
case DEC_SAME: | case DEC_SAME: | |||
/* Same modes: only if VCD_CODETABLE is set */ | /* Same modes: only if VCD_CODETABLE is set */ | |||
BYTE_CASE((stream->dec_hdr_ind & VCD_CODETABLE) != 0, | BYTE_CASE((stream->dec_hdr_ind & VCD_CODETABLE) != 0, | |||
stream->acache.s_same, DEC_TABDAT); | stream->acache.s_same, DEC_TABDAT); | |||
case DEC_TABDAT: | case DEC_TABDAT: | |||
/* Compressed code table data */ | /* Compressed code table data */ | |||
if ((stream->dec_hdr_ind & VCD_CODETABLE) != 0) | if ((stream->dec_hdr_ind & VCD_CODETABLE) != 0) | |||
{ | { | |||
stream->msg = "VCD_CODETABLE support was removed"; | ||||
return XD3_UNIMPLEMENTED; | return XD3_UNIMPLEMENTED; | |||
} | } | |||
else | else | |||
{ | { | |||
/* Use the default table. */ | /* Use the default table. */ | |||
stream->acache.s_near = __rfc3284_code_table_desc.near_modes; | stream->acache.s_near = __rfc3284_code_table_desc.near_modes; | |||
stream->acache.s_same = __rfc3284_code_table_desc.same_modes; | stream->acache.s_same = __rfc3284_code_table_desc.same_modes; | |||
stream->code_table = xd3_rfc3284_code_table (); | stream->code_table = xd3_rfc3284_code_table (); | |||
} | } | |||
skipping to change at line 913 | skipping to change at line 954 | |||
case DEC_APPLEN: | case DEC_APPLEN: | |||
/* Length of application data */ | /* Length of application data */ | |||
SIZE_CASE((stream->dec_hdr_ind & VCD_APPHEADER) != 0, | SIZE_CASE((stream->dec_hdr_ind & VCD_APPHEADER) != 0, | |||
stream->dec_appheadsz, DEC_APPDAT); | stream->dec_appheadsz, DEC_APPDAT); | |||
case DEC_APPDAT: | case DEC_APPDAT: | |||
/* Application data */ | /* Application data */ | |||
if (stream->dec_hdr_ind & VCD_APPHEADER) | if (stream->dec_hdr_ind & VCD_APPHEADER) | |||
{ | { | |||
/* Note: we add an additional byte for padding, to allow | /* Note: we add an additional byte for padding, to allow | |||
0-termination. */ | 0-termination. Check for overflow: */ | |||
if (USIZE_T_OVERFLOW(stream->dec_appheadsz, 1)) | ||||
{ | ||||
stream->msg = "exceptional appheader size"; | ||||
return XD3_INVALID_INPUT; | ||||
} | ||||
if ((stream->dec_appheader == NULL) && | if ((stream->dec_appheader == NULL) && | |||
(stream->dec_appheader = | (stream->dec_appheader = | |||
(uint8_t*) xd3_alloc (stream, | (uint8_t*) xd3_alloc (stream, | |||
stream->dec_appheadsz+1, 1)) == NULL) | stream->dec_appheadsz+1, 1)) == NULL) | |||
{ | { | |||
return ENOMEM; | return ENOMEM; | |||
} | } | |||
stream->dec_appheader[stream->dec_appheadsz] = 0; | stream->dec_appheader[stream->dec_appheadsz] = 0; | |||
skipping to change at line 1121 | skipping to change at line 1168 | |||
if (src == NULL) | if (src == NULL) | |||
{ | { | |||
stream->msg = "source input required"; | stream->msg = "source input required"; | |||
return XD3_INVALID_INPUT; | return XD3_INVALID_INPUT; | |||
} | } | |||
xd3_blksize_div(stream->dec_cpyoff, src, | xd3_blksize_div(stream->dec_cpyoff, src, | |||
&src->cpyoff_blocks, | &src->cpyoff_blocks, | |||
&src->cpyoff_blkoff); | &src->cpyoff_blkoff); | |||
IF_DEBUG1(DP(RINT | IF_DEBUG2(DP(RINT | |||
"decode cpyoff %"Q"u " | "[decode_cpyoff] %"Q"u " | |||
"cpyblkno %"Q"u " | "cpyblkno %"Q"u " | |||
"cpyblkoff %u " | "cpyblkoff %u " | |||
"blksize %u\n", | "blksize %u\n", | |||
stream->dec_cpyoff, | stream->dec_cpyoff, | |||
src->cpyoff_blocks, | src->cpyoff_blocks, | |||
src->cpyoff_blkoff, | src->cpyoff_blkoff, | |||
src->blksize)); | src->blksize)); | |||
} | } | |||
/* xd3_decode_emit returns XD3_OUTPUT on every success. */ | /* xd3_decode_emit returns XD3_OUTPUT on every success. */ | |||
End of changes. 12 change blocks. | ||||
9 lines changed or deleted | 57 lines changed or added |