Alien-SVN
view release on metacpan or search on metacpan
src/subversion/subversion/libsvn_delta/svndiff.c view on Meta::CPAN
return svn_error_create(SVN_ERR_SVNDIFF_INVALID_COMPRESSED_DATA, NULL,
_("Decompression of svndiff data failed: no size"));
if (len > limit)
return svn_error_create(SVN_ERR_SVNDIFF_INVALID_COMPRESSED_DATA, NULL,
_("Decompression of svndiff data failed: "
"size too large"));
/* We need to subtract the size of the encoded original length off the
* still remaining input length. */
inLen -= (in - oldplace);
if (inLen == len)
{
svn_stringbuf_ensure(out, len);
memcpy(out->data, in, len);
out->data[len] = 0;
out->len = len;
return SVN_NO_ERROR;
}
else
{
unsigned long zlen = len;
int zerr;
svn_stringbuf_ensure(out, len);
zerr = uncompress((unsigned char *)out->data, &zlen, in, inLen);
if (zerr != Z_OK)
return svn_error_trace(svn_error__wrap_zlib(
zerr, "uncompress",
_("Decompression of svndiff data failed")));
/* Zlib should not produce something that has a different size than the
original length we stored. */
if (zlen != len)
return svn_error_create(SVN_ERR_SVNDIFF_INVALID_COMPRESSED_DATA,
NULL,
_("Size of uncompressed data "
"does not match stored original length"));
out->data[zlen] = 0;
out->len = zlen;
}
return SVN_NO_ERROR;
}
/* Decode an instruction into OP, returning a pointer to the text
after the instruction. Note that if the action code is
svn_txdelta_new, the offset field of *OP will not be set. */
static const unsigned char *
decode_instruction(svn_txdelta_op_t *op,
const unsigned char *p,
const unsigned char *end)
{
apr_size_t c;
apr_size_t action;
if (p == end)
return NULL;
/* We need this more than once */
c = *p++;
/* Decode the instruction selector. */
action = (c >> 6) & 0x3;
if (action >= 0x3)
return NULL;
/* This relies on enum svn_delta_action values to match and never to be
redefined. */
op->action_code = (enum svn_delta_action)(action);
/* Decode the length and offset. */
op->length = c & 0x3f;
if (op->length == 0)
{
p = decode_size(&op->length, p, end);
if (p == NULL)
return NULL;
}
if (action != svn_txdelta_new)
{
p = decode_size(&op->offset, p, end);
if (p == NULL)
return NULL;
}
return p;
}
/* Count the instructions in the range [P..END-1] and make sure they
are valid for the given window lengths. Return an error if the
instructions are invalid; otherwise set *NINST to the number of
instructions. */
static svn_error_t *
count_and_verify_instructions(int *ninst,
const unsigned char *p,
const unsigned char *end,
apr_size_t sview_len,
apr_size_t tview_len,
apr_size_t new_len)
{
int n = 0;
svn_txdelta_op_t op;
apr_size_t tpos = 0, npos = 0;
while (p < end)
{
p = decode_instruction(&op, p, end);
/* Detect any malformed operations from the instruction stream. */
if (p == NULL)
return svn_error_createf
(SVN_ERR_SVNDIFF_INVALID_OPS, NULL,
_("Invalid diff stream: insn %d cannot be decoded"), n);
else if (op.length == 0)
return svn_error_createf
(SVN_ERR_SVNDIFF_INVALID_OPS, NULL,
_("Invalid diff stream: insn %d has length zero"), n);
else if (op.length > tview_len - tpos)
return svn_error_createf
(SVN_ERR_SVNDIFF_INVALID_OPS, NULL,
_("Invalid diff stream: insn %d overflows the target view"), n);
( run in 0.466 second using v1.01-cache-2.11-cpan-140bd7fdf52 )