~ubuntu-branches/debian/sid/subversion/sid

« back to all changes in this revision

Viewing changes to subversion/libsvn_delta/text_delta.c

  • Committer: Package Import Robot
  • Author(s): James McCoy
  • Date: 2015-08-07 21:32:47 UTC
  • mfrom: (0.2.15) (4.1.7 experimental)
  • Revision ID: package-import@ubuntu.com-20150807213247-ozyewtmgsr6tkewl
Tags: 1.9.0-1
* Upload to unstable
* New upstream release.
  + Security fixes
    - CVE-2015-3184: Mixed anonymous/authenticated path-based authz with
      httpd 2.4
    - CVE-2015-3187: svn_repos_trace_node_locations() reveals paths hidden
      by authz
* Add >= 2.7 requirement for python-all-dev Build-Depends, needed to run
  tests.
* Remove Build-Conflicts against ruby-test-unit.  (Closes: #791844)
* Remove patches/apache_module_dependency in favor of expressing the
  dependencies in authz_svn.load/dav_svn.load.
* Build-Depend on apache2-dev (>= 2.4.16) to ensure ap_some_authn_required()
  is available when building mod_authz_svn and Depend on apache2-bin (>=
  2.4.16) for runtime support.

Show diffs side-by-side

added added

removed removed

Lines of Context:
366
366
  /* Read the source stream. */
367
367
  if (b->more_source)
368
368
    {
369
 
      SVN_ERR(svn_stream_read(b->source, b->buf, &source_len));
 
369
      SVN_ERR(svn_stream_read_full(b->source, b->buf, &source_len));
370
370
      b->more_source = (source_len == SVN_DELTA_WINDOW_SIZE);
371
371
    }
372
372
  else
373
373
    source_len = 0;
374
374
 
375
375
  /* Read the target stream. */
376
 
  SVN_ERR(svn_stream_read(b->target, b->buf + source_len, &target_len));
 
376
  SVN_ERR(svn_stream_read_full(b->target, b->buf + source_len, &target_len));
377
377
  b->pos += source_len;
378
378
 
379
379
  if (target_len == 0)
522
522
      if (tb->source_len == 0 && !tb->source_done)
523
523
        {
524
524
          tb->source_len = SVN_DELTA_WINDOW_SIZE;
525
 
          SVN_ERR(svn_stream_read(tb->source, tb->buf, &tb->source_len));
 
525
          SVN_ERR(svn_stream_read_full(tb->source, tb->buf, &tb->source_len));
526
526
          if (tb->source_len < SVN_DELTA_WINDOW_SIZE)
527
527
            tb->source_done = TRUE;
528
528
        }
623
623
  return SVN_NO_ERROR;
624
624
}
625
625
 
626
 
/* Copy LEN bytes from SOURCE to TARGET, optimizing for the case where LEN
627
 
 * is often very small.  Return a pointer to the first byte after the copied
628
 
 * target range, unlike standard memcpy(), as a potential further
629
 
 * optimization for the caller.
630
 
 *
631
 
 * memcpy() is hard to tune for a wide range of buffer lengths.  Therefore,
632
 
 * it is often tuned for high throughput on large buffers and relatively
633
 
 * low latency for mid-sized buffers (tens of bytes).  However, the overhead
634
 
 * for very small buffers (<10 bytes) is still high.  Even passing the
635
 
 * parameters, for instance, may take as long as copying 3 bytes.
636
 
 *
637
 
 * Because short copy sequences seem to be a common case, at least in
638
 
 * "format 2" FSFS repositories, we copy them directly.  Larger buffer sizes
639
 
 * aren't hurt measurably by the exta 'if' clause.  */
640
 
static APR_INLINE char *
641
 
fast_memcpy(char *target, const char *source, apr_size_t len)
642
 
{
643
 
  if (len > 7)
644
 
    {
645
 
      memcpy(target, source, len);
646
 
      target += len;
647
 
    }
648
 
  else
649
 
    {
650
 
      /* memcpy is not exactly fast for small block sizes.
651
 
       * Since they are common, let's run optimized code for them. */
652
 
      const char *end = source + len;
653
 
      for (; source != end; source++)
654
 
        *(target++) = *source;
655
 
    }
656
 
 
657
 
  return target;
658
 
}
659
 
 
660
626
/* Copy LEN bytes from SOURCE to TARGET.  Unlike memmove() or memcpy(),
661
627
 * create repeating patterns if the source and target ranges overlap.
662
628
 * Return a pointer to the first byte after the copied target range.  */
663
629
static APR_INLINE char *
664
630
patterning_copy(char *target, const char *source, apr_size_t len)
665
631
{
666
 
  const char *end = source + len;
667
 
 
668
 
  /* On many machines, we can do "chunky" copies. */
669
 
 
670
 
#if SVN_UNALIGNED_ACCESS_IS_OK
671
 
 
672
 
  if (end + sizeof(apr_uint32_t) <= target)
673
 
    {
674
 
      /* Source and target are at least 4 bytes apart, so we can copy in
675
 
       * 4-byte chunks.  */
676
 
      for (; source + sizeof(apr_uint32_t) <= end;
677
 
           source += sizeof(apr_uint32_t),
678
 
           target += sizeof(apr_uint32_t))
679
 
      *(apr_uint32_t *)(target) = *(apr_uint32_t *)(source);
680
 
    }
681
 
 
682
 
#endif
683
 
 
684
 
  /* fall through to byte-wise copy (either for the below-chunk-size tail
685
 
   * or the whole copy) */
686
 
  for (; source != end; source++)
687
 
    *(target++) = *source;
 
632
  /* If the source and target overlap, repeat the overlapping pattern
 
633
     in the target buffer. Always copy from the source buffer because
 
634
     presumably it will be in the L1 cache after the first iteration
 
635
     and doing this should avoid pipeline stalls due to write/read
 
636
     dependencies. */
 
637
  const apr_size_t overlap = target - source;
 
638
  while (len > overlap)
 
639
    {
 
640
      memcpy(target, source, overlap);
 
641
      target += overlap;
 
642
      len -= overlap;
 
643
    }
 
644
 
 
645
  /* Copy any remaining source pattern. */
 
646
  if (len)
 
647
    {
 
648
      memcpy(target, source, len);
 
649
      target += len;
 
650
    }
688
651
 
689
652
  return target;
690
653
}
697
660
  const svn_txdelta_op_t *op;
698
661
  apr_size_t tpos = 0;
699
662
 
 
663
  /* Nothing to do for empty buffers.
 
664
   * This check allows for NULL TBUF in that case. */
 
665
  if (*tlen == 0)
 
666
    return;
 
667
 
700
668
  for (op = window->ops; op < window->ops + window->num_ops; op++)
701
669
    {
702
670
      const apr_size_t buf_len = (op->length < *tlen - tpos
711
679
          /* Copy from source area.  */
712
680
          assert(sbuf);
713
681
          assert(op->offset + op->length <= window->sview_len);
714
 
          fast_memcpy(tbuf + tpos, sbuf + op->offset, buf_len);
 
682
          memcpy(tbuf + tpos, sbuf + op->offset, buf_len);
715
683
          break;
716
684
 
717
685
        case svn_txdelta_target:
728
696
        case svn_txdelta_new:
729
697
          /* Copy from window new area.  */
730
698
          assert(op->offset + op->length <= window->new_data->len);
731
 
          fast_memcpy(tbuf + tpos,
732
 
                      window->new_data->data + op->offset,
733
 
                      buf_len);
 
699
          memcpy(tbuf + tpos,
 
700
                 window->new_data->data + op->offset,
 
701
                 buf_len);
734
702
          break;
735
703
 
736
704
        default:
747
715
  *tlen = tpos;
748
716
}
749
717
 
750
 
/* This is a private interlibrary compatibility wrapper. */
751
 
void
752
 
svn_txdelta__apply_instructions(svn_txdelta_window_t *window,
753
 
                                const char *sbuf, char *tbuf,
754
 
                                apr_size_t *tlen);
755
 
void
756
 
svn_txdelta__apply_instructions(svn_txdelta_window_t *window,
757
 
                                const char *sbuf, char *tbuf,
758
 
                                apr_size_t *tlen)
759
 
{
760
 
  svn_txdelta_apply_instructions(window, sbuf, tbuf, tlen);
761
 
}
762
 
 
763
 
 
764
718
/* Apply WINDOW to the streams given by APPL.  */
765
719
static svn_error_t *
766
720
apply_window(svn_txdelta_window_t *window, void *baton)
819
773
  if (ab->sbuf_len < window->sview_len)
820
774
    {
821
775
      len = window->sview_len - ab->sbuf_len;
822
 
      err = svn_stream_read(ab->source, ab->sbuf + ab->sbuf_len, &len);
 
776
      err = svn_stream_read_full(ab->source, ab->sbuf + ab->sbuf_len, &len);
823
777
      if (err == SVN_NO_ERROR && len != window->sview_len - ab->sbuf_len)
824
778
        err = svn_error_create(SVN_ERR_INCOMPLETE_DATA, NULL,
825
779
                               "Delta source ended unexpectedly");
836
790
 
837
791
  /* Write out the output. */
838
792
 
839
 
  /* ### We've also considered just adding two (optionally null)
840
 
     arguments to svn_stream_create(): read_checksum and
841
 
     write_checksum.  Then instead of every caller updating an md5
842
 
     context when it calls svn_stream_write() or svn_stream_read(),
843
 
     streams would do it automatically, and verify the checksum in
844
 
     svn_stream_closed().  But this might be overkill for issue #689;
845
 
     so for now we just update the context here. */
 
793
  /* Just update the context here. */
846
794
  if (ab->result_digest)
847
795
    apr_md5_update(&(ab->md5_context), ab->tbuf, len);
848
796
 
936
884
    {
937
885
      apr_size_t read_len = SVN__STREAM_CHUNK_SIZE;
938
886
 
939
 
      SVN_ERR(svn_stream_read(stream, read_buf, &read_len));
 
887
      SVN_ERR(svn_stream_read_full(stream, read_buf, &read_len));
940
888
      if (read_len == 0)
941
889
        break;
942
890