コード例 #1
0
ファイル: compress.c プロジェクト: geofft/subversion
/* 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;
  apr_uint64_t size;
  const unsigned char *oldplace = in;

  /* First thing in the string is the original length.  */
  in = svn__decode_uint(&size, in, in + inLen);
  len = (apr_size_t)size;
  if (in == NULL || len != size)
    return svn_error_create(SVN_ERR_SVNDIFF_INVALID_COMPRESSED_DATA, NULL,
                            _("Decompression of zlib compressed data failed: no size"));
  if (len > limit)
    return svn_error_create(SVN_ERR_SVNDIFF_INVALID_COMPRESSED_DATA, NULL,
                            _("Decompression of zlib compressed 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;
}
コード例 #2
0
ファイル: low_level.c プロジェクト: FreeBSDFoundation/freebsd
svn_error_t *
svn_fs_x__parse_properties(apr_hash_t **properties,
                           const svn_string_t *content,
                           apr_pool_t *result_pool)
{
  const apr_byte_t *p = (const apr_byte_t *)content->data;
  const apr_byte_t *end = p + content->len;
  apr_uint64_t count;

  *properties = apr_hash_make(result_pool);

  /* Extract the number of properties we are expected to read. */
  p = svn__decode_uint(&count, p, end);

  /* Read all the properties we find.
     Because prop-name and prop-value are nicely NUL-terminated
     sub-strings of CONTENT, we can simply reference them there.
     I.e. there is no need to copy them around.
   */
  while (p < end)
    {
      apr_uint64_t value_len;
      svn_string_t *value;

      const char *key = (const char *)p;

      /* Note that this may never overflow / segfault because
         CONTENT itself is NUL-terminated. */
      apr_size_t key_len = strlen(key);
      p += key_len + 1;
      if (key[key_len])
        return svn_error_createf(SVN_ERR_FS_CORRUPT_PROPLIST, NULL,
                                 "Property name not NUL terminated");

      if (p >= end)
        return svn_error_createf(SVN_ERR_FS_CORRUPT_PROPLIST, NULL,
                                 "Property value missing");
      p = svn__decode_uint(&value_len, p, end);
      if (value_len >= (end - p))
        return svn_error_createf(SVN_ERR_FS_CORRUPT_PROPLIST, NULL,
                                 "Property value too long");

      value = apr_pcalloc(result_pool, sizeof(*value));
      value->data = (const char *)p;
      value->len = (apr_size_t)value_len;
      if (p[value->len])
        return svn_error_createf(SVN_ERR_FS_CORRUPT_PROPLIST, NULL,
                                 "Property value not NUL terminated");

      p += value->len + 1;

      apr_hash_set(*properties, key, key_len, value);
    }

  /* Check that we read the expected number of properties. */
  if ((apr_uint64_t)apr_hash_count(*properties) != count)
    return svn_error_createf(SVN_ERR_FS_CORRUPT_PROPLIST, NULL,
                             "Property count mismatch");

  return SVN_NO_ERROR;
}