Alien-SVN

 view release on metacpan or  search on metacpan

src/subversion/subversion/libsvn_delta/svndiff.c  view on Meta::CPAN

                        svn_stream_t *output,
                        int svndiff_version,
                        apr_pool_t *pool)
{
  svn_txdelta_to_svndiff3(handler, handler_baton, output, svndiff_version,
                          SVN_DELTA_COMPRESSION_LEVEL_DEFAULT, pool);
}

void
svn_txdelta_to_svndiff(svn_stream_t *output,
                       apr_pool_t *pool,
                       svn_txdelta_window_handler_t *handler,
                       void **handler_baton)
{
  svn_txdelta_to_svndiff3(handler, handler_baton, output, 0,
                          SVN_DELTA_COMPRESSION_LEVEL_DEFAULT, pool);
}


/* ----- svndiff to text delta ----- */

/* An svndiff parser object.  */
struct decode_baton
{
  /* Once the svndiff parser has enough data buffered to create a
     "window", it passes this window to the caller's consumer routine.  */
  svn_txdelta_window_handler_t consumer_func;
  void *consumer_baton;

  /* Pool to create subpools from; each developing window will be a
     subpool.  */
  apr_pool_t *pool;

  /* The current subpool which contains our current window-buffer.  */
  apr_pool_t *subpool;

  /* The actual svndiff data buffer, living within subpool.  */
  svn_stringbuf_t *buffer;

  /* The offset and size of the last source view, so that we can check
     to make sure the next one isn't sliding backwards.  */
  svn_filesize_t last_sview_offset;
  apr_size_t last_sview_len;

  /* We have to discard four bytes at the beginning for the header.
     This field keeps track of how many of those bytes we have read.  */
  apr_size_t header_bytes;

  /* Do we want an error to occur when we close the stream that
     indicates we didn't send the whole svndiff data?  If you plan to
     not transmit the whole svndiff data stream, you will want this to
     be FALSE. */
  svn_boolean_t error_on_early_close;

  /* svndiff version in use by delta.  */
  unsigned char version;
};


/* Decode an svndiff-encoded integer into *VAL and return a pointer to
   the byte after the integer.  The bytes to be decoded live in the
   range [P..END-1].  If these bytes do not contain a whole encoded
   integer, return NULL; in this case *VAL is undefined.

   See the comment for encode_int() earlier in this file for more detail on
   the encoding format.  */
static const unsigned char *
decode_file_offset(svn_filesize_t *val,
                   const unsigned char *p,
                   const unsigned char *end)
{
  svn_filesize_t temp = 0;

  if (p + MAX_ENCODED_INT_LEN < end)
    end = p + MAX_ENCODED_INT_LEN;
  /* Decode bytes until we're done.  */
  while (p < end)
    {
      /* Don't use svn_filesize_t here, because this might be 64 bits
       * on 32 bit targets. Optimizing compilers may or may not be
       * able to reduce that to the effective code below. */
      unsigned int c = *p++;

      temp = (temp << 7) | (c & 0x7f);
      if (c < 0x80)
      {
        *val = temp;
        return p;
      }
    }

  return NULL;
}


/* Same as above, only decode into a size variable. */
static const unsigned char *
decode_size(apr_size_t *val,
            const unsigned char *p,
            const unsigned char *end)
{
  apr_size_t temp = 0;

  if (p + MAX_ENCODED_INT_LEN < end)
    end = p + MAX_ENCODED_INT_LEN;
  /* Decode bytes until we're done.  */
  while (p < end)
    {
      apr_size_t c = *p++;

      temp = (temp << 7) | (c & 0x7f);
      if (c < 0x80)
      {
        *val = temp;
        return p;
      }
    }

  return NULL;
}

/* Decode the possibly-zlib compressed string of length INLEN that is in
   IN, into OUT.  We expect an integer is prepended to IN that specifies
   the original size, and that if encoded size == original size, that the
   remaining data is not compressed.
   In that case, we will simply return pointer into IN as data pointer for
   OUT, COPYLESS_ALLOWED has been set.  The, the caller is expected not to
   modify the contents of OUT.
   An error is returned if the decoded length exceeds the given LIMIT.
 */
static svn_error_t *
zlib_decode(const unsigned char *in, apr_size_t inLen, svn_stringbuf_t *out,
            apr_size_t limit)
{
  apr_size_t len;
  const unsigned char *oldplace = in;

  /* First thing in the string is the original length.  */
  in = decode_size(&len, in, in + inLen);
  if (in == NULL)
    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,

src/subversion/subversion/libsvn_delta/svndiff.c  view on Meta::CPAN

  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);

      switch (op.action_code)
        {
        case svn_txdelta_source:
          if (op.length > sview_len - op.offset ||
              op.offset > sview_len)
            return svn_error_createf
              (SVN_ERR_SVNDIFF_INVALID_OPS, NULL,
               _("Invalid diff stream: "
                 "[src] insn %d overflows the source view"), n);
          break;
        case svn_txdelta_target:
          if (op.offset >= tpos)
            return svn_error_createf
              (SVN_ERR_SVNDIFF_INVALID_OPS, NULL,
               _("Invalid diff stream: "
                 "[tgt] insn %d starts beyond the target view position"), n);
          break;
        case svn_txdelta_new:
          if (op.length > new_len - npos)
            return svn_error_createf
              (SVN_ERR_SVNDIFF_INVALID_OPS, NULL,
               _("Invalid diff stream: "
                 "[new] insn %d overflows the new data section"), n);
          npos += op.length;
          break;
        }
      tpos += op.length;
      n++;
    }
  if (tpos != tview_len)
    return svn_error_create(SVN_ERR_SVNDIFF_INVALID_OPS, NULL,
                            _("Delta does not fill the target window"));
  if (npos != new_len)
    return svn_error_create(SVN_ERR_SVNDIFF_INVALID_OPS, NULL,
                            _("Delta does not contain enough new data"));

  *ninst = n;
  return SVN_NO_ERROR;
}

/* Given the five integer fields of a window header and a pointer to
   the remainder of the window contents, fill in a delta window
   structure *WINDOW.  New allocations will be performed in POOL;
   the new_data field of *WINDOW will refer directly to memory pointed
   to by DATA. */
static svn_error_t *
decode_window(svn_txdelta_window_t *window, svn_filesize_t sview_offset,
              apr_size_t sview_len, apr_size_t tview_len, apr_size_t inslen,
              apr_size_t newlen, const unsigned char *data, apr_pool_t *pool,
              unsigned int version)
{



( run in 1.143 second using v1.01-cache-2.11-cpan-df04353d9ac )