You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2015/11/16 11:15:24 UTC

svn commit: r1714534 - in /subversion/branches/move-tracking-2: ./ subversion/ subversion/include/ subversion/include/private/ subversion/libsvn_delta/ subversion/libsvn_ra_serf/ subversion/libsvn_ra_svn/ subversion/libsvn_subr/ subversion/svnserve/ su...

Author: julianfoad
Date: Mon Nov 16 10:15:23 2015
New Revision: 1714534

URL: http://svn.apache.org/viewvc?rev=1714534&view=rev
Log:
On the 'move-tracking-2' branch: catch up to trunk@1714533.

Modified:
    subversion/branches/move-tracking-2/   (props changed)
    subversion/branches/move-tracking-2/subversion/   (props changed)
    subversion/branches/move-tracking-2/subversion/include/private/svn_sorts_private.h
    subversion/branches/move-tracking-2/subversion/include/svn_error_codes.h
    subversion/branches/move-tracking-2/subversion/include/svn_ra_svn.h
    subversion/branches/move-tracking-2/subversion/libsvn_delta/svndiff.c
    subversion/branches/move-tracking-2/subversion/libsvn_ra_serf/eagain_bucket.c
    subversion/branches/move-tracking-2/subversion/libsvn_ra_serf/sb_bucket.c
    subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/client.c
    subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/deprecated.c
    subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/editorp.c
    subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/marshal.c
    subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/ra_svn.h
    subversion/branches/move-tracking-2/subversion/libsvn_subr/cache-membuffer.c
    subversion/branches/move-tracking-2/subversion/libsvn_subr/compress.c
    subversion/branches/move-tracking-2/subversion/libsvn_subr/prefix_string.c
    subversion/branches/move-tracking-2/subversion/libsvn_subr/skel.c
    subversion/branches/move-tracking-2/subversion/libsvn_subr/sorts.c
    subversion/branches/move-tracking-2/subversion/libsvn_subr/spillbuf.c
    subversion/branches/move-tracking-2/subversion/libsvn_subr/string.c
    subversion/branches/move-tracking-2/subversion/libsvn_subr/subst.c
    subversion/branches/move-tracking-2/subversion/svnserve/serve.c
    subversion/branches/move-tracking-2/subversion/svnserve/server.h
    subversion/branches/move-tracking-2/subversion/svnserve/svnserve.c
    subversion/branches/move-tracking-2/subversion/tests/libsvn_fs/fs-test.c
    subversion/branches/move-tracking-2/subversion/tests/libsvn_subr/string-test.c

Propchange: subversion/branches/move-tracking-2/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Nov 16 10:15:23 2015
@@ -94,4 +94,4 @@
 /subversion/branches/verify-at-commit:1462039-1462408
 /subversion/branches/verify-keep-going:1439280-1546110
 /subversion/branches/wc-collate-path:1402685-1480384
-/subversion/trunk:1606692-1713385
+/subversion/trunk:1606692-1714533

Propchange: subversion/branches/move-tracking-2/subversion/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Nov 16 10:15:23 2015
@@ -82,4 +82,4 @@
 /subversion/branches/verify-at-commit/subversion:1462039-1462408
 /subversion/branches/verify-keep-going/subversion:1439280-1546110
 /subversion/branches/wc-collate-path/subversion:1402685-1480384
-/subversion/trunk/subversion:1606692-1713385
+/subversion/trunk/subversion:1606692-1714533

Modified: subversion/branches/move-tracking-2/subversion/include/private/svn_sorts_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/include/private/svn_sorts_private.h?rev=1714534&r1=1714533&r2=1714534&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/include/private/svn_sorts_private.h (original)
+++ subversion/branches/move-tracking-2/subversion/include/private/svn_sorts_private.h Mon Nov 16 10:15:23 2015
@@ -53,12 +53,12 @@ struct svn_sort__item_t {
 /** Sort @a ht according to its keys, return an @c apr_array_header_t
  * containing @c svn_sort__item_t structures holding those keys and values
  * (i.e. for each @c svn_sort__item_t @a item in the returned array,
- * @a item->key and @a item->size are the hash key, and @a item->value points to
+ * @a item.key and @a item.size are the hash key, and @a item.value points to
  * the hash value).
  *
  * Storage is shared with the original hash, not copied.
  *
- * @a comparison_func should take two @c svn_sort__item_t's and return an
+ * @a comparison_func should take pointers to two items and return an
  * integer greater than, equal to, or less than 0, according as the first item
  * is greater than, equal to, or less than the second.
  *

Modified: subversion/branches/move-tracking-2/subversion/include/svn_error_codes.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/include/svn_error_codes.h?rev=1714534&r1=1714533&r2=1714534&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/include/svn_error_codes.h (original)
+++ subversion/branches/move-tracking-2/subversion/include/svn_error_codes.h Mon Nov 16 10:15:23 2015
@@ -1542,6 +1542,16 @@ SVN_ERROR_START
              SVN_ERR_RA_SVN_CATEGORY_START + 8,
              "Editor drive was aborted")
 
+  /** @since New in 1.10  */
+  SVN_ERRDEF(SVN_ERR_RA_SVN_REQUEST_SIZE,
+             SVN_ERR_RA_SVN_CATEGORY_START + 9,
+             "Client request too long")
+
+  /** @since New in 1.10  */
+  SVN_ERRDEF(SVN_ERR_RA_SVN_RESPONSE_SIZE,
+             SVN_ERR_RA_SVN_CATEGORY_START + 10,
+             "Server response too long")
+
   /* libsvn_auth errors */
 
        /* this error can be used when an auth provider doesn't have

Modified: subversion/branches/move-tracking-2/subversion/include/svn_ra_svn.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/include/svn_ra_svn.h?rev=1714534&r1=1714533&r2=1714534&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/include/svn_ra_svn.h (original)
+++ subversion/branches/move-tracking-2/subversion/include/svn_ra_svn.h Mon Nov 16 10:15:23 2015
@@ -189,13 +189,38 @@ typedef svn_error_t *(*svn_ra_svn_edit_c
  * It defines the number of bytes that must have been sent since the last
  * check before the next check will be made.
  *
+ * If @a max_in is not 0, error out and close the connection whenever more
+ * than @a max_in bytes are received for a command (e.g. a client request).
+ * If @a max_out is not 0, error out and close the connection whenever more
+ * than @a max_out bytes have been send as response to some command.
+ *
+ * @note The limits enforced may vary slightly by +/- the I/O buffer size. 
+ *
  * @note If @a out_stream is an wrapped apr_file_t* the backing file will be
  * used for some operations.
  *
  * Allocate the result in @a pool.
  *
+ * @since New in 1.10
+ */
+svn_ra_svn_conn_t *svn_ra_svn_create_conn5(apr_socket_t *sock,
+                                           svn_stream_t *in_stream,
+                                           svn_stream_t *out_stream,
+                                           int compression_level,
+                                           apr_size_t zero_copy_limit,
+                                           apr_size_t error_check_interval,
+                                           apr_uint64_t max_in,
+                                           apr_uint64_t max_out,
+                                           apr_pool_t *result_pool);
+
+
+/** Similar to svn_ra_svn_create_conn5() but with @a max_in and @a max_out
+ * set to 0.
+ *
  * @since New in 1.9
+ * @deprecated Provided for backward compatibility with the 1.9 API.
  */
+SVN_DEPRECATED
 svn_ra_svn_conn_t *svn_ra_svn_create_conn4(apr_socket_t *sock,
                                            svn_stream_t *in_stream,
                                            svn_stream_t *out_stream,

Modified: subversion/branches/move-tracking-2/subversion/libsvn_delta/svndiff.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_delta/svndiff.c?rev=1714534&r1=1714533&r2=1714534&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_delta/svndiff.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_delta/svndiff.c Mon Nov 16 10:15:23 2015
@@ -689,8 +689,8 @@ write_handler(void *baton,
           /* Check for source windows which slide backwards.  */
           if (sview_len > 0
               && (sview_offset < db->last_sview_offset
-              || (sview_offset + sview_len
-                  < db->last_sview_offset + db->last_sview_len)))
+                  || (sview_offset + sview_len
+                      < db->last_sview_offset + db->last_sview_len)))
             return svn_error_create(
                      SVN_ERR_SVNDIFF_BACKWARD_VIEW, NULL,
                      _("Svndiff has backwards-sliding source views"));
@@ -710,7 +710,7 @@ write_handler(void *baton,
         }
 
       /* Wait for more data if we don't have enough bytes for the
-         whole window.  */
+         whole window. */
       if ((apr_size_t) (end - p) < db->inslen + db->newlen)
         return SVN_NO_ERROR;
 

Modified: subversion/branches/move-tracking-2/subversion/libsvn_ra_serf/eagain_bucket.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_ra_serf/eagain_bucket.c?rev=1714534&r1=1714533&r2=1714534&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_ra_serf/eagain_bucket.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_ra_serf/eagain_bucket.c Mon Nov 16 10:15:23 2015
@@ -66,7 +66,7 @@ eagain_bucket_read(serf_bucket_t *bucket
   return APR_EAGAIN;
 }
 
-
+#if !SERF_VERSION_AT_LEAST(1, 4, 0)
 static apr_status_t
 eagain_bucket_readline(serf_bucket_t *bucket,
                        int acceptable,
@@ -79,6 +79,7 @@ eagain_bucket_readline(serf_bucket_t *bu
                                          "Not implemented."));
   return APR_ENOTIMPL;
 }
+#endif
 
 
 static apr_status_t
@@ -98,7 +99,11 @@ eagain_bucket_peek(serf_bucket_t *bucket
 static const serf_bucket_type_t delay_bucket_vtable = {
     "BUF-EAGAIN",
     eagain_bucket_read,
+#if SERF_VERSION_AT_LEAST(1, 4, 0)
+    serf_default_readline,
+#else
     eagain_bucket_readline,
+#endif
     serf_default_read_iovec,
     serf_default_read_for_sendfile,
     serf_default_read_bucket,

Modified: subversion/branches/move-tracking-2/subversion/libsvn_ra_serf/sb_bucket.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_ra_serf/sb_bucket.c?rev=1714534&r1=1714533&r2=1714534&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_ra_serf/sb_bucket.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_ra_serf/sb_bucket.c Mon Nov 16 10:15:23 2015
@@ -117,7 +117,7 @@ sb_bucket_read(serf_bucket_t *bucket, ap
   return *data == NULL ? APR_EOF : APR_SUCCESS;
 }
 
-
+#if !SERF_VERSION_AT_LEAST(1, 4, 0)
 static apr_status_t
 sb_bucket_readline(serf_bucket_t *bucket, int acceptable,
                    int *found,
@@ -128,6 +128,7 @@ sb_bucket_readline(serf_bucket_t *bucket
                                          "Not implemented."));
   return APR_ENOTIMPL;
 }
+#endif
 
 
 static apr_status_t
@@ -159,7 +160,11 @@ sb_bucket_peek(serf_bucket_t *bucket,
 static const serf_bucket_type_t sb_bucket_vtable = {
     "SPILLBUF",
     sb_bucket_read,
+#if SERF_VERSION_AT_LEAST(1, 4, 0)
+    serf_default_readline,
+#else
     sb_bucket_readline,
+#endif
     serf_default_read_iovec,
     serf_default_read_for_sendfile,
     serf_default_read_bucket,

Modified: subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/client.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/client.c?rev=1714534&r1=1714533&r2=1714534&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/client.c Mon Nov 16 10:15:23 2015
@@ -471,9 +471,9 @@ static void handle_child_process_error(a
   in_stream = svn_stream_from_aprfile2(in_file, FALSE, pool);
   out_stream = svn_stream_from_aprfile2(out_file, FALSE, pool);
 
-  conn = svn_ra_svn_create_conn4(NULL, in_stream, out_stream,
+  conn = svn_ra_svn_create_conn5(NULL, in_stream, out_stream,
                                  SVN_DELTA_COMPRESSION_LEVEL_DEFAULT, 0,
-                                 0, pool);
+                                 0, 0, 0, pool);
   err = svn_error_wrap_apr(status, _("Error in child process: %s"), desc);
   svn_error_clear(svn_ra_svn__write_cmd_failure(conn, pool, err));
   svn_error_clear(err);
@@ -542,13 +542,13 @@ static svn_error_t *make_tunnel(const ch
   apr_file_inherit_unset(proc->out);
 
   /* Guard against dotfile output to stdout on the server. */
-  *conn = svn_ra_svn_create_conn4(NULL,
+  *conn = svn_ra_svn_create_conn5(NULL,
                                   svn_stream_from_aprfile2(proc->out, FALSE,
                                                            pool),
                                   svn_stream_from_aprfile2(proc->in, FALSE,
                                                            pool),
                                   SVN_DELTA_COMPRESSION_LEVEL_DEFAULT,
-                                  0, 0, pool);
+                                  0, 0, 0, 0, pool);
   err = svn_ra_svn__skip_leading_garbage(*conn, pool);
   if (err)
     return svn_error_quick_wrap(
@@ -674,9 +674,9 @@ static svn_error_t *open_session(svn_ra_
           apr_pool_cleanup_register(pool, td, close_tunnel_cleanup,
                                     apr_pool_cleanup_null);
 
-          conn = svn_ra_svn_create_conn4(NULL, td->response, td->request,
+          conn = svn_ra_svn_create_conn5(NULL, td->response, td->request,
                                          SVN_DELTA_COMPRESSION_LEVEL_DEFAULT,
-                                         0, 0, pool);
+                                         0, 0, 0, 0, pool);
           SVN_ERR(svn_ra_svn__skip_leading_garbage(conn, pool));
         }
     }
@@ -688,9 +688,9 @@ static svn_error_t *open_session(svn_ra_
       SVN_ERR(make_connection(uri->hostname,
                               uri->port ? uri->port : SVN_RA_SVN_PORT,
                               &sock, pool));
-      conn = svn_ra_svn_create_conn4(sock, NULL, NULL,
+      conn = svn_ra_svn_create_conn5(sock, NULL, NULL,
                                      SVN_DELTA_COMPRESSION_LEVEL_DEFAULT,
-                                     0, 0, pool);
+                                     0, 0, 0, 0, pool);
     }
 
   /* Build the useragent string, querying the client for any
@@ -1956,6 +1956,7 @@ static svn_error_t *ra_svn_get_locations
   svn_ra_svn_conn_t *conn = sess_baton->conn;
   svn_revnum_t revision;
   svn_boolean_t is_done;
+  apr_pool_t *iterpool;
   int i;
 
   /* Transmit the parameters. */
@@ -1976,12 +1977,14 @@ static svn_error_t *ra_svn_get_locations
   /* Read the hash items. */
   is_done = FALSE;
   *locations = apr_hash_make(pool);
+  iterpool = svn_pool_create(pool);
   while (!is_done)
     {
       svn_ra_svn__item_t *item;
       const char *ret_path;
 
-      SVN_ERR(svn_ra_svn__read_item(conn, pool, &item));
+      svn_pool_clear(iterpool);
+      SVN_ERR(svn_ra_svn__read_item(conn, iterpool, &item));
       if (is_done_response(item))
         is_done = 1;
       else if (item->kind != SVN_RA_SVN_LIST)
@@ -1991,6 +1994,8 @@ static svn_error_t *ra_svn_get_locations
         {
           SVN_ERR(svn_ra_svn__parse_tuple(&item->u.list, "rc",
                                           &revision, &ret_path));
+
+          /* This also makes RET_PATH live in POOL rather than ITERPOOL. */
           ret_path = svn_fspath__canonicalize(ret_path, pool);
           apr_hash_set(*locations, apr_pmemdup(pool, &revision,
                                                sizeof(revision)),
@@ -1998,6 +2003,8 @@ static svn_error_t *ra_svn_get_locations
         }
     }
 
+  svn_pool_destroy(iterpool);
+
   /* Read the response. This is so the server would have a chance to
    * report an error. */
   return svn_error_trace(svn_ra_svn__read_cmd_response(conn, pool, ""));

Modified: subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/deprecated.c?rev=1714534&r1=1714533&r2=1714534&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/deprecated.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/deprecated.c Mon Nov 16 10:15:23 2015
@@ -262,6 +262,20 @@ svn_ra_svn_write_cmd_failure(svn_ra_svn_
 
 /* From marshal.c */
 svn_ra_svn_conn_t *
+svn_ra_svn_create_conn4(apr_socket_t *sock,
+                        svn_stream_t *in_stream,
+                        svn_stream_t *out_stream,
+                        int compression_level,
+                        apr_size_t zero_copy_limit,
+                        apr_size_t error_check_interval,
+                        apr_pool_t *pool)
+{
+  return svn_ra_svn_create_conn5(sock, in_stream, out_stream,
+                                 compression_level, zero_copy_limit,
+                                 error_check_interval, 0, 0, pool);
+}
+
+svn_ra_svn_conn_t *
 svn_ra_svn_create_conn3(apr_socket_t *sock,
                         apr_file_t *in_file,
                         apr_file_t *out_file,
@@ -279,7 +293,8 @@ svn_ra_svn_create_conn3(apr_socket_t *so
     out_stream = svn_stream_from_aprfile2(out_file, FALSE, pool);
 
   return svn_ra_svn_create_conn4(sock, in_stream, out_stream,
-                                 compression_level, 0, 0, pool);
+                                 compression_level, zero_copy_limit,
+                                 error_check_interval, pool);
 }
 
 svn_ra_svn_conn_t *

Modified: subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/editorp.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/editorp.c?rev=1714534&r1=1714533&r2=1714534&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/editorp.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/editorp.c Mon Nov 16 10:15:23 2015
@@ -1106,6 +1106,10 @@ svn_error_t *svn_ra_svn_drive_editor2(sv
   while (!state.done)
     {
       svn_pool_clear(subpool);
+
+      /* WRT to applying I/O limits, treat each editor command as a separate
+       * protocol command. */
+      svn_ra_svn__reset_command_io_counters(conn);
       if (editor)
         {
           cmd_handler_t handler;

Modified: subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/marshal.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/marshal.c?rev=1714534&r1=1714533&r2=1714534&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/marshal.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/marshal.c Mon Nov 16 10:15:23 2015
@@ -179,12 +179,14 @@ svn_ra_svn__to_private_array(const apr_a
 
 /* --- CONNECTION INITIALIZATION --- */
 
-svn_ra_svn_conn_t *svn_ra_svn_create_conn4(apr_socket_t *sock,
+svn_ra_svn_conn_t *svn_ra_svn_create_conn5(apr_socket_t *sock,
                                            svn_stream_t *in_stream,
                                            svn_stream_t *out_stream,
                                            int compression_level,
                                            apr_size_t zero_copy_limit,
                                            apr_size_t error_check_interval,
+                                           apr_uint64_t max_in,
+                                           apr_uint64_t max_out,
                                            apr_pool_t *result_pool)
 {
   svn_ra_svn_conn_t *conn;
@@ -204,6 +206,10 @@ svn_ra_svn_conn_t *svn_ra_svn_create_con
   conn->written_since_error_check = 0;
   conn->error_check_interval = error_check_interval;
   conn->may_check_for_error = error_check_interval == 0;
+  conn->max_in = max_in;
+  conn->current_in = 0;
+  conn->max_out = max_out;
+  conn->current_out = 0;
   conn->block_handler = NULL;
   conn->block_baton = NULL;
   conn->capabilities = apr_hash_make(result_pool);
@@ -312,8 +318,33 @@ svn_error_t *svn_ra_svn__data_available(
   return svn_ra_svn__stream_data_available(conn->stream, data_available);
 }
 
+void
+svn_ra_svn__reset_command_io_counters(svn_ra_svn_conn_t *conn)
+{
+  conn->current_in = 0;
+  conn->current_out = 0;
+}
+
+
 /* --- WRITE BUFFER MANAGEMENT --- */
 
+/* Return an error object if CONN exceeded its send or receive limits. */
+static svn_error_t *
+check_io_limits(svn_ra_svn_conn_t *conn)
+{
+  if (conn->max_in && (conn->current_in > conn->max_in))
+    return svn_error_create(SVN_ERR_RA_SVN_REQUEST_SIZE, NULL,
+                            "The client request size exceeds the "
+                            "configured limit");
+
+  if (conn->max_out && (conn->current_out > conn->max_out))
+    return svn_error_create(SVN_ERR_RA_SVN_RESPONSE_SIZE, NULL,
+                            "The server response size exceeds the "
+                            "configured limit");
+
+  return SVN_NO_ERROR;
+}
+
 /* Write data to socket or output file as appropriate. */
 static svn_error_t *writebuf_output(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
                                     const char *data, apr_size_t len)
@@ -323,6 +354,12 @@ static svn_error_t *writebuf_output(svn_
   apr_pool_t *subpool = NULL;
   svn_ra_svn__session_baton_t *session = conn->session;
 
+  /* Limit the size of the response, if a limit has been configured.
+   * This is to limit the server load in case users e.g. accidentally ran
+   * an export on the root folder. */
+  conn->current_out += len;
+  SVN_ERR(check_io_limits(conn));
+
   while (data < end)
     {
       count = end - data;
@@ -441,12 +478,19 @@ static svn_error_t *readbuf_input(svn_ra
 {
   svn_ra_svn__session_baton_t *session = conn->session;
 
+  /* First, give the user a chance to cancel the request before we do. */
   if (session && session->callbacks && session->callbacks->cancel_func)
     SVN_ERR((session->callbacks->cancel_func)(session->callbacks_baton));
 
+  /* Limit our memory usage, if a limit has been configured.  Note that
+   * we first read the whole request into memory before process it. */
+  SVN_ERR(check_io_limits(conn));
+
+  /* Actually fill the buffer. */
   SVN_ERR(svn_ra_svn__stream_read(conn->stream, data, len));
   if (*len == 0)
     return svn_error_create(SVN_ERR_RA_SVN_CONNECTION_CLOSED, NULL, NULL);
+  conn->current_in += *len;
 
   if (session)
     {
@@ -492,9 +536,13 @@ static svn_error_t *readbuf_fill(svn_ra_
   apr_size_t len;
 
   SVN_ERR_ASSERT(conn->read_ptr == conn->read_end);
+
+  /* Make sure we tell the other side everything we have to say before
+   * reading / waiting for an answer. */
   if (conn->write_pos)
     SVN_ERR(writebuf_flush(conn, pool));
 
+  /* Fill (some of the) buffer. */
   len = sizeof(conn->read_buf);
   SVN_ERR(readbuf_input(conn, conn->read_buf, &len, pool));
   conn->read_ptr = conn->read_buf;
@@ -1141,7 +1189,7 @@ static svn_error_t *read_string(svn_ra_s
   char *dest;
 
   /* We can't store strings longer than the maximum size of apr_size_t,
-   * so check for wrapping */
+   * so check before using the truncated value. */
   if (len64 > APR_SIZE_MAX)
     return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
                             _("String length larger than maximum"));
@@ -1156,6 +1204,16 @@ static svn_error_t *read_string(svn_ra_s
     }
   else
     {
+      svn_stringbuf_t *stringbuf;
+
+      /* Don't even attempt to read anything that exceeds the I/O limit.
+       * So, we can terminate the transfer at an early point, saving
+       * everybody's time and resources. */
+      if (conn->max_in && (conn->max_in < len64))
+        return svn_error_create(SVN_ERR_RA_SVN_REQUEST_SIZE, NULL,
+                                "The client request size exceeds the "
+                                "configured limit");
+
       /* Read the string in chunks.  The chunk size is large enough to avoid
        * re-allocation in typical cases, and small enough to ensure we do
        * not pre-allocate an unreasonable amount of memory if (perhaps due
@@ -1164,7 +1222,7 @@ static svn_error_t *read_string(svn_ra_s
        * start small and wait for all that data to actually show up.  This
        * does not fully prevent DOS attacks but makes them harder (you have
        * to actually send gigabytes of data). */
-      svn_stringbuf_t *stringbuf = svn_stringbuf_create_empty(pool);
+      stringbuf = svn_stringbuf_create_empty(pool);
 
       /* Read string data directly into the string structure.
        * Do it iteratively.  */
@@ -1791,7 +1849,12 @@ svn_ra_svn__has_command(svn_boolean_t *h
                         svn_ra_svn_conn_t *conn,
                         apr_pool_t *pool)
 {
-  svn_error_t *err = svn_ra_svn__has_item(has_command, conn, pool);
+  svn_error_t *err;
+
+  /* Don't make whitespace between commands trigger I/O limitiations. */
+  svn_ra_svn__reset_command_io_counters(conn);
+
+  err = svn_ra_svn__has_item(has_command, conn, pool);
   if (err && err->apr_err == SVN_ERR_RA_SVN_CONNECTION_CLOSED)
     {
       *terminated = TRUE;
@@ -1817,6 +1880,10 @@ svn_ra_svn__handle_command(svn_boolean_t
   const svn_ra_svn__cmd_entry_t *command;
 
   *terminate = FALSE;
+
+  /* Limit I/O for every command separately. */
+  svn_ra_svn__reset_command_io_counters(conn);
+
   err = svn_ra_svn__read_tuple(conn, pool, "wl", &cmdname, &params);
   if (err)
     {
@@ -1848,6 +1915,13 @@ svn_ra_svn__handle_command(svn_boolean_t
                                                baton);
         }
 
+      /* The command implementation may have swallowed or wrapped the I/O
+       * error not knowing that we may no longer be able to send data.
+       *
+       * So, check again for the limit violations and exit the command
+       * processing quickly if we may have truncated data. */
+      err = svn_error_compose_create(check_io_limits(conn), err);
+
       *terminate = command->terminate;
     }
   else

Modified: subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/ra_svn.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/ra_svn.h?rev=1714534&r1=1714533&r2=1714534&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/ra_svn.h (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/ra_svn.h Mon Nov 16 10:15:23 2015
@@ -96,6 +96,12 @@ struct svn_ra_svn_conn_st {
   apr_size_t error_check_interval;
   svn_boolean_t may_check_for_error;
 
+  /* I/O limits and tracking */
+  apr_uint64_t max_in;
+  apr_uint64_t current_in;
+  apr_uint64_t max_out;
+  apr_uint64_t current_out;
+
   /* repository info */
   const char *uuid;
   const char *repos_root;
@@ -151,6 +157,12 @@ void svn_ra_svn__set_block_handler(svn_r
 svn_error_t *svn_ra_svn__data_available(svn_ra_svn_conn_t *conn,
                                        svn_boolean_t *data_available);
 
+/* Signal a new request / response pair on CONN.  That resets the I/O
+ * counters we use to limit the size of individual requests / response pairs.
+ */
+void
+svn_ra_svn__reset_command_io_counters(svn_ra_svn_conn_t *conn);
+
 /* CRAM-MD5 client implementation. */
 svn_error_t *svn_ra_svn__cram_client(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
                                      const char *user, const char *password,

Modified: subversion/branches/move-tracking-2/subversion/libsvn_subr/cache-membuffer.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_subr/cache-membuffer.c?rev=1714534&r1=1714533&r2=1714534&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_subr/cache-membuffer.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_subr/cache-membuffer.c Mon Nov 16 10:15:23 2015
@@ -353,7 +353,8 @@ prefix_pool_get_internal(apr_uint32_t *p
     }
 
   bytes_needed = prefix_len + 1 + OVERHEAD;
-  if (prefix_pool->bytes_used + bytes_needed > prefix_pool->values_max)
+  assert(prefix_pool->bytes_max >= prefix_pool->bytes_used);
+  if (prefix_pool->bytes_max - prefix_pool->bytes_used > bytes_needed)
     {
       *prefix_idx = NO_INDEX;
       return SVN_NO_ERROR;
@@ -1664,12 +1665,12 @@ ensure_data_insertable_l2(svn_membuffer_
 
       /* leave function as soon as the insertion window is large enough
        */
-      if (end >= to_fit_in->size + cache->l2.current_data)
+      if (end - cache->l2.current_data >= to_fit_in->size)
         return TRUE;
 
       /* Don't be too eager to cache data.  If a lot of data has been moved
        * around, the current item has probably a relatively low priority.
-       * We must also limit the effort spent here (if even in case of faulty
+       * We must also limit the effort spent here (even in case of faulty
        * heuristics).  Therefore, give up after some time.
        */
       if (moved_size > 4 * to_fit_in->size && moved_count > 7)
@@ -1789,7 +1790,7 @@ ensure_data_insertable_l1(svn_membuffer_
 
       /* leave function as soon as the insertion window is large enough
        */
-      if (end >= size + cache->l1.current_data)
+      if (end - cache->l1.current_data >= size)
         return TRUE;
 
       /* Enlarge the insertion window
@@ -2678,9 +2679,11 @@ membuffer_cache_set_partial_internal(svn
           if (item_data != orig_data)
             {
               /* Remove the old entry and try to make space for the new one.
+               * Note that the key has already been stored in the past, i.e.
+               * it is shorter than the MAX_ENTRY_SIZE.
                */
               drop_entry(cache, entry);
-              if (   (cache->max_entry_size >= item_size + key_len)
+              if (   (cache->max_entry_size - key_len >= item_size)
                   && ensure_data_insertable_l1(cache, item_size + key_len))
                 {
                   /* Write the new entry.
@@ -3371,6 +3374,11 @@ svn_cache__create_membuffer_cache(svn_ca
   prefix_orig_len = strlen(prefix) + 1;
   prefix_len = ALIGN_VALUE(prefix_orig_len);
 
+  /* Paranoia check to ensure pointer arithmetics work as expected. */
+  if (prefix_orig_len >= SVN_MAX_OBJECT_SIZE)
+    return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
+                            _("Prefix too long"));
+
   /* Construct the folded prefix key. */
   SVN_ERR(svn_checksum(&checksum,
                        svn_checksum_md5,

Modified: subversion/branches/move-tracking-2/subversion/libsvn_subr/compress.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_subr/compress.c?rev=1714534&r1=1714533&r2=1714534&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_subr/compress.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_subr/compress.c Mon Nov 16 10:15:23 2015
@@ -100,7 +100,7 @@ svn__decode_uint(apr_uint64_t *val,
 {
   apr_uint64_t temp = 0;
 
-  if (p + SVN__MAX_ENCODED_UINT_LEN < end)
+  if (end - p > SVN__MAX_ENCODED_UINT_LEN)
     end = p + SVN__MAX_ENCODED_UINT_LEN;
 
   /* Decode bytes until we're done. */

Modified: subversion/branches/move-tracking-2/subversion/libsvn_subr/prefix_string.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_subr/prefix_string.c?rev=1714534&r1=1714533&r2=1714534&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_subr/prefix_string.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_subr/prefix_string.c Mon Nov 16 10:15:23 2015
@@ -228,7 +228,7 @@ svn_prefix_string__create(svn_prefix_tre
     }
 
   /* add sub-node(s) and final string */
-  while (node->length + 7 < len)
+  while (len - node->length > 7)
     {
       new_node = apr_pcalloc(tree->pool, sizeof(*new_node));
       new_node->key.prefix = node;

Modified: subversion/branches/move-tracking-2/subversion/libsvn_subr/skel.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_subr/skel.c?rev=1714534&r1=1714533&r2=1714534&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_subr/skel.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_subr/skel.c Mon Nov 16 10:15:23 2015
@@ -380,7 +380,7 @@ explicit_atom(const char *data,
   data++;
 
   /* Check the length.  */
-  if (data + size > end)
+  if (end - data < size)
     return NULL;
 
   /* Allocate the skel representing this string.  */

Modified: subversion/branches/move-tracking-2/subversion/libsvn_subr/sorts.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_subr/sorts.c?rev=1714534&r1=1714533&r2=1714534&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_subr/sorts.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_subr/sorts.c Mon Nov 16 10:15:23 2015
@@ -333,7 +333,7 @@ svn_sort__array_delete(apr_array_header_
   if (delete_index >= 0
       && delete_index < arr->nelts
       && elements_to_delete > 0
-      && (elements_to_delete + delete_index) <= arr->nelts)
+      && (arr->nelts - delete_index) >= elements_to_delete)
     {
       /* If we are not deleting a block of elements that extends to the end
          of the array, then we need to move the remaining elements to keep

Modified: subversion/branches/move-tracking-2/subversion/libsvn_subr/spillbuf.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_subr/spillbuf.c?rev=1714534&r1=1714533&r2=1714534&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_subr/spillbuf.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_subr/spillbuf.c Mon Nov 16 10:15:23 2015
@@ -242,7 +242,7 @@ svn_spillbuf__write(svn_spillbuf_t *buf,
      will grow too large. Create the file and place the pending data into
      the temporary file.  */
   if (buf->spill == NULL
-      && (buf->memory_size + len) > buf->maxsize)
+      && ((buf->maxsize - buf->memory_size) < len))
     {
       SVN_ERR(svn_io_open_unique_file3(&buf->spill,
                                        &buf->filename,

Modified: subversion/branches/move-tracking-2/subversion/libsvn_subr/string.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_subr/string.c?rev=1714534&r1=1714533&r2=1714534&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_subr/string.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_subr/string.c Mon Nov 16 10:15:23 2015
@@ -677,7 +677,7 @@ svn_stringbuf_remove(svn_stringbuf_t *st
 {
   if (pos > str->len)
     pos = str->len;
-  if (pos + count > str->len)
+  if (count > str->len - pos)
     count = str->len - pos;
 
   memmove(str->data + pos, str->data + pos + count, str->len - pos - count + 1);
@@ -705,7 +705,7 @@ svn_stringbuf_replace(svn_stringbuf_t *s
 
   if (pos > str->len)
     pos = str->len;
-  if (pos + old_count > str->len)
+  if (old_count > str->len - pos)
     old_count = str->len - pos;
 
   if (old_count < new_count)

Modified: subversion/branches/move-tracking-2/subversion/libsvn_subr/subst.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_subr/subst.c?rev=1714534&r1=1714533&r2=1714534&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_subr/subst.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_subr/subst.c Mon Nov 16 10:15:23 2015
@@ -1127,7 +1127,7 @@ translate_chunk(svn_stream_t *dst,
                 {
                   /* Check 4 bytes at once to allow for efficient pipelining
                     and to reduce loop condition overhead. */
-                  while ((p + len + 4) <= end)
+                  while ((end - p) >= (len + 4))
                     {
                       if (interesting[(unsigned char)p[len]]
                           || interesting[(unsigned char)p[len+1]]
@@ -1157,7 +1157,7 @@ translate_chunk(svn_stream_t *dst,
             }
           while (b->nl_translation_skippable ==
                    svn_tristate_true &&       /* can potentially skip EOLs */
-                 p + len + 2 < end &&         /* not too close to EOF */
+                 (end - p) > (len + 2) &&     /* not too close to EOF */
                  eol_unchanged(b, p + len));  /* EOL format already ok */
 
           while ((p + len) < end && !interesting[(unsigned char)p[len]])

Modified: subversion/branches/move-tracking-2/subversion/svnserve/serve.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/svnserve/serve.c?rev=1714534&r1=1714533&r2=1714534&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svnserve/serve.c (original)
+++ subversion/branches/move-tracking-2/subversion/svnserve/serve.c Mon Nov 16 10:15:23 2015
@@ -627,11 +627,12 @@ create_fs_access(server_baton_t *b, apr_
  * On authentication failure, report failure to the client and set
  * *success to FALSE.  On communications failure, return an error.
  * If NEEDS_USERNAME is TRUE, don't allow anonymous authentication. */
-static svn_error_t *auth(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
+static svn_error_t *auth(svn_boolean_t *success,
+                         svn_ra_svn_conn_t *conn,
                          const char *mech, const char *mecharg,
                          server_baton_t *b, enum access_type required,
                          svn_boolean_t needs_username,
-                         svn_boolean_t *success)
+                         apr_pool_t *scratch_pool)
 {
   const char *user;
   *success = FALSE;
@@ -640,10 +641,10 @@ static svn_error_t *auth(svn_ra_svn_conn
       && b->client_info->tunnel_user && strcmp(mech, "EXTERNAL") == 0)
     {
       if (*mecharg && strcmp(mecharg, b->client_info->tunnel_user) != 0)
-        return svn_ra_svn__write_tuple(conn, pool, "w(c)", "failure",
+        return svn_ra_svn__write_tuple(conn, scratch_pool, "w(c)", "failure",
                                        "Requested username does not match");
       b->client_info->user = b->client_info->tunnel_user;
-      SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w()", "success"));
+      SVN_ERR(svn_ra_svn__write_tuple(conn, scratch_pool, "w()", "success"));
       *success = TRUE;
       return SVN_NO_ERROR;
     }
@@ -651,7 +652,7 @@ static svn_error_t *auth(svn_ra_svn_conn
   if (b->repository->anon_access >= required
       && strcmp(mech, "ANONYMOUS") == 0 && ! needs_username)
     {
-      SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w()", "success"));
+      SVN_ERR(svn_ra_svn__write_tuple(conn, scratch_pool, "w()", "success"));
       *success = TRUE;
       return SVN_NO_ERROR;
     }
@@ -659,13 +660,13 @@ static svn_error_t *auth(svn_ra_svn_conn
   if (b->repository->auth_access >= required
       && b->repository->pwdb && strcmp(mech, "CRAM-MD5") == 0)
     {
-      SVN_ERR(svn_ra_svn_cram_server(conn, pool, b->repository->pwdb,
+      SVN_ERR(svn_ra_svn_cram_server(conn, scratch_pool, b->repository->pwdb,
                                      &user, success));
       b->client_info->user = apr_pstrdup(b->pool, user);
       return SVN_NO_ERROR;
     }
 
-  return svn_ra_svn__write_tuple(conn, pool, "w(c)", "failure",
+  return svn_ra_svn__write_tuple(conn, scratch_pool, "w(c)", "failure",
                                 "Must authenticate with listed mechanism");
 }
 
@@ -677,19 +678,26 @@ internal_auth_request(svn_ra_svn_conn_t
 {
   svn_boolean_t success;
   const char *mech, *mecharg;
+  apr_pool_t *iterpool;
 
   SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w((!", "success"));
   SVN_ERR(send_mechs(conn, pool, b, required, needs_username));
   SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "!)c)", b->repository->realm));
+
+  iterpool = svn_pool_create(pool);
   do
     {
+      svn_pool_clear(iterpool);
+
       SVN_ERR(svn_ra_svn__read_tuple(conn, pool, "w(?c)", &mech, &mecharg));
       if (!*mech)
         break;
-      SVN_ERR(auth(conn, pool, mech, mecharg, b, required, needs_username,
-                   &success));
+      SVN_ERR(auth(&success, conn, mech, mecharg, b, required,
+                   needs_username, iterpool));
     }
   while (!success);
+  svn_pool_destroy(iterpool);
+
   return SVN_NO_ERROR;
 }
 
@@ -4115,10 +4123,12 @@ serve_interruptable(svn_boolean_t *termi
 
       /* create the connection, configure ports etc. */
       connection->conn
-        = svn_ra_svn_create_conn4(connection->usock, NULL, NULL,
+        = svn_ra_svn_create_conn5(connection->usock, NULL, NULL,
                                   connection->params->compression_level,
                                   connection->params->zero_copy_limit,
                                   connection->params->error_check_interval,
+                                  connection->params->max_request_size,
+                                  connection->params->max_response_size,
                                   connection->pool);
 
       /* Construct server baton and open the repository for the first time. */

Modified: subversion/branches/move-tracking-2/subversion/svnserve/server.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/svnserve/server.h?rev=1714534&r1=1714533&r2=1714534&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svnserve/server.h (original)
+++ subversion/branches/move-tracking-2/subversion/svnserve/server.h Mon Nov 16 10:15:23 2015
@@ -152,6 +152,12 @@ typedef struct serve_params_t {
      coming in from the client. */
   apr_size_t error_check_interval;
 
+  /* If not 0, error out on requests exceeding this value. */
+  apr_uint64_t max_request_size;
+
+  /* If not 0, stop sending a response once it exceeds this value. */
+  apr_uint64_t max_response_size;
+
   /* Use virtual-host-based path to repo. */
   svn_boolean_t vhost;
 } serve_params_t;

Modified: subversion/branches/move-tracking-2/subversion/svnserve/svnserve.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/svnserve/svnserve.c?rev=1714534&r1=1714533&r2=1714534&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svnserve/svnserve.c (original)
+++ subversion/branches/move-tracking-2/subversion/svnserve/svnserve.c Mon Nov 16 10:15:23 2015
@@ -155,6 +155,15 @@ enum run_mode {
  */
 #define ACCEPT_BACKLOG 128
 
+/* Default limit to the client request size in MBytes.  This effectively
+ * limits the size of a paths and individual property values to about
+ * this value.
+ *
+ * Note that (MAX_REQUEST_SIZE + 4M) * THREADPOOL_MAX_SIZE is roughly
+ * the peak memory usage of the RA layer.
+ */
+#define MAX_REQUEST_SIZE 16
+
 #ifdef WIN32
 static apr_os_sock_t winservice_svnserve_accept_socket = INVALID_SOCKET;
 
@@ -210,6 +219,8 @@ void winservice_notify_stop(void)
 #define SVNSERVE_OPT_MIN_THREADS     271
 #define SVNSERVE_OPT_MAX_THREADS     272
 #define SVNSERVE_OPT_BLOCK_READ      273
+#define SVNSERVE_OPT_MAX_REQUEST     274
+#define SVNSERVE_OPT_MAX_RESPONSE    275
 
 /* Text macro because we can't use #ifdef sections inside a N_("...")
    macro expansion. */
@@ -345,6 +356,29 @@ static const apr_getopt_option_t svnserv
         "Default is " APR_STRINGIFY(THREADPOOL_MAX_SIZE) "."
         ONLY_AVAILABLE_WITH_THEADS)},
 #endif
+    {"max-request-size", SVNSERVE_OPT_MAX_REQUEST, 1,
+     N_("Maximum acceptable size of a client request in MB.\n"
+        "                             "
+        "This implicitly limits the length of paths and\n"
+        "                             "
+        "property values that can be sent to the server.\n"
+        "                             "
+        "Also the peak memory usage for protocol handling\n"
+        "                             "
+        "per server thread or sub-process.\n"
+        "                             "
+        "0 disables the size check; default is "
+        APR_STRINGIFY(MAX_REQUEST_SIZE) ".")},
+    {"max-response-size", SVNSERVE_OPT_MAX_RESPONSE, 1,
+     N_("Maximum acceptable server response size in MB.\n"
+        "                             "
+        "Longer responses get truncated and return an\n"
+        "                             "
+        "error.  This limits the server load e.g. when\n"
+        "                             "
+        "checking out at the wrong path level.\n"
+        "                             "
+        "Default is 0 (disabled).")},
     {"foreground",        SVNSERVE_OPT_FOREGROUND, 0,
      N_("run in foreground (useful for debugging)\n"
         "                             "
@@ -728,6 +762,8 @@ sub_main(int *exit_code, int argc, const
   params.memory_cache_size = (apr_uint64_t)-1;
   params.zero_copy_limit = 0;
   params.error_check_interval = 4096;
+  params.max_request_size = MAX_REQUEST_SIZE * 0x100000;
+  params.max_response_size = 0;
 
   while (1)
     {
@@ -891,6 +927,14 @@ sub_main(int *exit_code, int argc, const
           }
           break;
 
+        case SVNSERVE_OPT_MAX_REQUEST:
+          params.max_request_size = 0x100000 * apr_strtoi64(arg, NULL, 0);
+          break;
+
+        case SVNSERVE_OPT_MAX_RESPONSE:
+          params.max_response_size = 0x100000 * apr_strtoi64(arg, NULL, 0);
+          break;
+
         case SVNSERVE_OPT_MIN_THREADS:
           min_thread_count = (apr_size_t)apr_strtoi64(arg, NULL, 0);
           break;
@@ -1039,10 +1083,12 @@ sub_main(int *exit_code, int argc, const
        * the pool cleanup handlers that call sasl_dispose() (connection_pool)
        * and sasl_done() (pool) are run in the right order. See issue #3664. */
       connection_pool = svn_pool_create(pool);
-      conn = svn_ra_svn_create_conn4(NULL, stdin_stream, stdout_stream,
+      conn = svn_ra_svn_create_conn5(NULL, stdin_stream, stdout_stream,
                                      params.compression_level,
                                      params.zero_copy_limit,
                                      params.error_check_interval,
+                                     params.max_request_size,
+                                     params.max_response_size,
                                      connection_pool);
       err = serve(conn, &params, connection_pool);
       svn_pool_destroy(connection_pool);

Modified: subversion/branches/move-tracking-2/subversion/tests/libsvn_fs/fs-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/tests/libsvn_fs/fs-test.c?rev=1714534&r1=1714533&r2=1714534&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/tests/libsvn_fs/fs-test.c (original)
+++ subversion/branches/move-tracking-2/subversion/tests/libsvn_fs/fs-test.c Mon Nov 16 10:15:23 2015
@@ -5960,6 +5960,9 @@ purge_txn_test(const svn_test_opts_t *op
   return SVN_NO_ERROR;
 }
 
+/* Test svn_fs_{contents,props}_{different,changed}().
+ * ### This currently only tests them on revision roots, not on txn roots.
+ */
 static svn_error_t *
 compare_contents(const svn_test_opts_t *opts,
                  apr_pool_t *pool)

Modified: subversion/branches/move-tracking-2/subversion/tests/libsvn_subr/string-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/tests/libsvn_subr/string-test.c?rev=1714534&r1=1714533&r2=1714534&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/tests/libsvn_subr/string-test.c (original)
+++ subversion/branches/move-tracking-2/subversion/tests/libsvn_subr/string-test.c Mon Nov 16 10:15:23 2015
@@ -634,7 +634,15 @@ test_stringbuf_remove(apr_pool_t *pool)
   SVN_TEST_STRING_ASSERT(a->data, "stell");
 
   svn_stringbuf_remove(a, 1200, 393);
-  return expect_stringbuf_equal(a, "stell", pool);
+  SVN_ERR(expect_stringbuf_equal(a, "stell", pool));
+
+  svn_stringbuf_remove(a, APR_SIZE_MAX, 2);
+  SVN_ERR(expect_stringbuf_equal(a, "stell", pool));
+
+  svn_stringbuf_remove(a, 1, APR_SIZE_MAX);
+  SVN_ERR(expect_stringbuf_equal(a, "s", pool));
+
+  return SVN_NO_ERROR;
 }
 
 static svn_error_t *
@@ -672,6 +680,12 @@ test_stringbuf_replace(apr_pool_t *pool)
                     svn_stringbuf_ncreate("test hello\0-\0world!\0-\0!",
                                           23, pool)));
 
+  svn_stringbuf_replace(a, 1, APR_SIZE_MAX, "x", 1);
+  SVN_ERR(expect_stringbuf_equal(a, "tx", pool));
+
+  svn_stringbuf_replace(a, APR_SIZE_MAX, APR_SIZE_MAX, "y", 1);
+  SVN_ERR(expect_stringbuf_equal(a, "txy", pool));
+
   return SVN_NO_ERROR;
 }