Author: kotkov
Date: Wed Mar 14 18:48:37 2018
New Revision: 1826747
URL: http://svn.apache.org/viewvc?rev=1826747&view=rev
Log:
Fix an issue in the svn_txdelta_to_svndiff_stream() API that could cause
unexpected short reads (EOFs) on the stream.
This API is used when performing PUT requests to the server. Consequently,
the bug could result in truncated payload being sent to the server and
failing commits over http://.
* subversion/libsvn_delta/svndiff.c
(svndiff_stream_read_fn): Handle a case where we have received the final
window from the txdelta stream, but the remaining part of the buffer
cannot fully accommodate it during this call to read_fn. Instead of
exiting and triggering an unexpected short read, allow the remaining
part to be read during subsequent calls to read_fn.
* subversion/tests/libsvn_delta
(): Add 'svndiff-stream-test' to svn:ignore.
* subversion/tests/libsvn_delta/svndiff-stream-test.c: New file with a
regression test for this issue.
* build.conf
(svndiff-stream-test): New.
(__ALL_TESTS__): Run svndiff-stream-test.
Added:
subversion/trunk/subversion/tests/libsvn_delta/svndiff-stream-test.c
(with props)
Modified:
subversion/trunk/build.conf
subversion/trunk/subversion/libsvn_delta/svndiff.c
subversion/trunk/subversion/tests/libsvn_delta/ (props changed)
Modified: subversion/trunk/build.conf
URL:
http://svn.apache.org/viewvc/subversion/trunk/build.conf?rev=1826747&r1=1826746&r2=1826747&view=diff
==============================================================================
--- subversion/trunk/build.conf (original)
+++ subversion/trunk/build.conf Wed Mar 14 18:48:37 2018
@@ -1207,6 +1207,14 @@ sources = window-test.c
install = test
libs = libsvn_test libsvn_delta libsvn_subr apriconv apr
+[svndiff-stream-test]
+description = Test svndiff streams
+type = exe
+path = subversion/tests/libsvn_delta
+sources = svndiff-stream-test.c
+install = test
+libs = libsvn_test libsvn_delta libsvn_subr apriconv apr
+
# ----------------------------------------------------------------------------
# Tests for libsvn_client
@@ -1580,6 +1588,7 @@ libs = __ALL__
op-depth-test dirent_uri-test wc-queries-test wc-test
auth-test
parse-diff-test x509-test xml-test afl-x509 compress-test
+ svndiff-stream-test
[__MORE__]
type = project
Modified: subversion/trunk/subversion/libsvn_delta/svndiff.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_delta/svndiff.c?rev=1826747&r1=1826746&r2=1826747&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_delta/svndiff.c (original)
+++ subversion/trunk/subversion/libsvn_delta/svndiff.c Wed Mar 14 18:48:37 2018
@@ -1026,11 +1026,11 @@ svndiff_stream_read_fn(void *baton, char
apr_size_t left = *len;
apr_size_t read = 0;
- while (left && !b->hit_eof)
+ while (left)
{
apr_size_t chunk_size;
- if (b->read_pos == b->window_buffer->len)
+ if (b->read_pos == b->window_buffer->len && !b->hit_eof)
{
svn_txdelta_window_t *window;
@@ -1050,6 +1050,9 @@ svndiff_stream_read_fn(void *baton, char
else
chunk_size = left;
+ if (!chunk_size)
+ break;
+
memcpy(buffer, b->window_buffer->data + b->read_pos, chunk_size);
b->read_pos += chunk_size;
buffer += chunk_size;
Propchange: subversion/trunk/subversion/tests/libsvn_delta/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Wed Mar 14 18:48:37 2018
@@ -8,6 +8,7 @@ vdelta-test
random-test
xml-output-test
svndiff-test
+svndiff-stream-test
window-test
editor-test
combined
Added: subversion/trunk/subversion/tests/libsvn_delta/svndiff-stream-test.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_delta/svndiff-stream-test.c?rev=1826747&view=auto
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_delta/svndiff-stream-test.c (added)
+++ subversion/trunk/subversion/tests/libsvn_delta/svndiff-stream-test.c Wed
Mar 14 18:48:37 2018
@@ -0,0 +1,79 @@
+/*
+ * svndiff-stream-test.c: test svndiff streams
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ */
+
+#include "svn_delta.h"
+#include "../svn_test.h"
+
+static svn_error_t *
+null_window(svn_txdelta_window_t **window,
+ void *baton, apr_pool_t *pool)
+{
+ *window = NULL;
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_txdelta_to_svndiff_stream_small_reads(apr_pool_t *pool)
+{
+ svn_txdelta_stream_t *txstream;
+ svn_stream_t *svndiff_stream;
+ char buf[64];
+ apr_size_t len;
+
+ txstream = svn_txdelta_stream_create(NULL, null_window, NULL, pool);
+ svndiff_stream = svn_txdelta_to_svndiff_stream(txstream, 0, 0, pool);
+
+ len = 3;
+ SVN_ERR(svn_stream_read_full(svndiff_stream, buf, &len));
+ SVN_TEST_INT_ASSERT((int) len, 3);
+ SVN_TEST_ASSERT(memcmp(buf, "SVN", len) == 0);
+
+ len = 1;
+ SVN_ERR(svn_stream_read_full(svndiff_stream, buf, &len));
+ SVN_TEST_INT_ASSERT((int) len, 1);
+ SVN_TEST_ASSERT(memcmp(buf, "\x00", len) == 0);
+
+ /* Test receiving the EOF. */
+ len = sizeof(buf);
+ SVN_ERR(svn_stream_read_full(svndiff_stream, buf, &len));
+ SVN_TEST_INT_ASSERT((int) len, 0);
+
+ /* Test reading after the EOF. */
+ len = sizeof(buf);
+ SVN_ERR(svn_stream_read_full(svndiff_stream, buf, &len));
+ SVN_TEST_INT_ASSERT((int) len, 0);
+
+ return SVN_NO_ERROR;
+}
+
+static int max_threads = -1;
+
+static struct svn_test_descriptor_t test_funcs[] =
+{
+ SVN_TEST_NULL,
+ SVN_TEST_PASS2(test_txdelta_to_svndiff_stream_small_reads,
+ "test svn_txdelta_to_svndiff_stream() small reads"),
+ SVN_TEST_NULL
+};
+
+SVN_TEST_MAIN
Propchange: subversion/trunk/subversion/tests/libsvn_delta/svndiff-stream-test.c
------------------------------------------------------------------------------
svn:eol-style = native