Fix issue #2119.  Avoid assertion failures or other weirdness if non-canonical
paths are received over ra_svn protocol.

* subversion/libsvn_ra_svn/client.c (ra_svn_open): Canonicalize repos root.
  Only check length of repos_root if it was returned.  Capitalize error
  message.
  (ra_svn_get_dir, ra_svn_log2, ra_svn_get_locations, ra_svn_get_file_revs):
  Canonicalize paths received from the server.
* subversion/libsvn_ra_svn/editorp.c, editor.c: Include svn_path.h.
  (ra_svn_handle_delete_entry, ra_svn_handle_add_dir, ra_svn_handle_open_dir,
  ra_svn_handle_add_file, ra_svn_handle_open_file): Canonicalize paths
  read from the connection.
* subversion/svnserve/serve.c (set_path, delete_path, link_path, get_file,
  get_dir, update, switch_cmd, status, diff, log_cmd, check_path,
  get_locations, get_file_revs, serve): Canonicalize paths from the client.


Index: subversion/libsvn_ra_svn/client.c
===================================================================
--- subversion/libsvn_ra_svn/client.c	(revision 12045)
+++ subversion/libsvn_ra_svn/client.c	(arbetskopia)
@@ -633,12 +633,17 @@
   /* Read the repository's uuid and root URL. */
   SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, "c?c", &conn->uuid,
                                        &conn->repos_root));
-  /* We should check that the returned string is a prefix of url, since that's
-     the API guarantee, but this isn't true for 1.0 servers.  Checking the
-     length prevents client crashes. */
-  if (strlen(conn->repos_root) > strlen(url))
-    return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
-                            _("impossibly long repository root from server"));
+  if (conn->repos_root)
+    {
+      conn->repos_root = svn_path_canonicalize(conn->repos_root, pool);
+      /* We should check that the returned string is a prefix of url, since
+         that's the API guarantee, but this isn't true for 1.0 servers.
+         Checking the length prevents client crashes. */
+      if (strlen(conn->repos_root) > strlen(url))
+        return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
+                                _("Impossibly long repository root from "
+                                  "server"));
+    }
 
   *baton = sess;
   return SVN_NO_ERROR;
@@ -896,6 +901,7 @@
       SVN_ERR(svn_ra_svn_parse_tuple(elt->u.list, pool, "cwnbr(?c)(?c)",
                                      &name, &kind, &size, &has_props,
                                      &crev, &cdate, &cauthor));
+      name = svn_path_canonicalize(name, pool);
       dirent = apr_palloc(pool, sizeof(*dirent));
       SVN_ERR(interpret_kind(kind, pool, &dirent->kind));
       dirent->size = size;/* FIXME: svn_filesize_t */
@@ -1064,6 +1070,9 @@
               SVN_ERR(svn_ra_svn_parse_tuple(elt->u.list, subpool, "cw(?cr)",
                                              &cpath, &action, &copy_path,
                                              &copy_rev));
+              cpath = svn_path_canonicalize(cpath, subpool);
+              if (copy_path)
+                copy_path = svn_path_canonicalize(copy_path, subpool);
               change = apr_palloc(subpool, sizeof(*change));
               change->action = *action;
               change->copyfrom_path = copy_path;
@@ -1171,6 +1180,7 @@
         {
           SVN_ERR(svn_ra_svn_parse_tuple (item->u.list, pool, "rc",
                                           &revision, &ret_path));
+          ret_path = svn_path_canonicalize(ret_path, pool);
           apr_hash_set(*locations, apr_pmemdup(pool, &revision,
                                                sizeof(revision)),
                        sizeof(revision), ret_path);
@@ -1237,6 +1247,7 @@
       SVN_ERR(svn_ra_svn_parse_tuple(item->u.list, rev_pool,
                                      "crll", &p, &rev, &rev_proplist,
                                      &proplist));
+      p = svn_path_canonicalize(p, rev_pool);
       SVN_ERR(parse_proplist(rev_proplist, rev_pool, &rev_props));
       SVN_ERR(parse_prop_diffs(proplist, rev_pool, &props));
 
Index: subversion/libsvn_ra_svn/editorp.c
===================================================================
--- subversion/libsvn_ra_svn/editorp.c	(revision 12045)
+++ subversion/libsvn_ra_svn/editorp.c	(arbetskopia)
@@ -29,6 +29,7 @@
 #include "svn_types.h"
 #include "svn_string.h"
 #include "svn_error.h"
+#include "svn_path.h"
 #include "svn_delta.h"
 #include "svn_ra_svn.h"
 #include "svn_pools.h"
@@ -459,6 +460,7 @@
 
   SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "c(?r)c", &path, &rev, &token));
   SVN_ERR(lookup_token(ds, token, FALSE, &entry));
+  path = svn_path_canonicalize(path, entry->pool);
   SVN_CMD_ERR(ds->editor->delete_entry(path, rev, entry->baton, pool));
   return SVN_NO_ERROR;
 }
@@ -478,6 +480,9 @@
                                  &child_token, &copy_path, &copy_rev));
   SVN_ERR(lookup_token(ds, token, FALSE, &entry));
   subpool = svn_pool_create(entry->pool);
+  path = svn_path_canonicalize(path, subpool);
+  if (copy_path)
+    copy_path = svn_path_canonicalize(copy_path, subpool);
   SVN_CMD_ERR(ds->editor->add_directory(path, entry->baton, copy_path,
                                         copy_rev, subpool, &child_baton));
   store_token(ds, child_baton, child_token, FALSE, subpool);
@@ -499,6 +504,7 @@
                                  &child_token, &rev));
   SVN_ERR(lookup_token(ds, token, FALSE, &entry));
   subpool = svn_pool_create(entry->pool);
+  path = svn_path_canonicalize(path, subpool);
   SVN_CMD_ERR(ds->editor->open_directory(path, entry->baton, rev, subpool,
                                          &child_baton));
   store_token(ds, child_baton, child_token, FALSE, subpool);
@@ -554,6 +560,9 @@
                                  &file_token, &copy_path, &copy_rev));
   SVN_ERR(lookup_token(ds, token, FALSE, &entry));
   ds->file_refs++;
+  path = svn_path_canonicalize(path, ds->file_pool);
+  if (copy_path)
+    copy_path = svn_path_canonicalize(copy_path, ds->file_pool);
   file_entry = store_token(ds, NULL, file_token, TRUE, ds->file_pool);
   SVN_CMD_ERR(ds->editor->add_file(path, entry->baton, copy_path, copy_rev,
                                    ds->file_pool, &file_entry->baton));
@@ -573,6 +582,7 @@
                                  &file_token, &rev));
   SVN_ERR(lookup_token(ds, token, FALSE, &entry));
   ds->file_refs++;
+  path = svn_path_canonicalize(path, ds->file_pool);
   file_entry = store_token(ds, NULL, file_token, TRUE, ds->file_pool);
   SVN_CMD_ERR(ds->editor->open_file(path, entry->baton, rev, ds->file_pool,
                                     &file_entry->baton));
Index: subversion/libsvn_ra_svn/editor.c
===================================================================
--- subversion/libsvn_ra_svn/editor.c	(revision 12045)
+++ subversion/libsvn_ra_svn/editor.c	(arbetskopia)
@@ -29,6 +29,7 @@
 #include "svn_types.h"
 #include "svn_string.h"
 #include "svn_error.h"
+#include "svn_path.h"
 #include "svn_delta.h"
 #include "svn_ra_svn.h"
 #include "svn_pools.h"
@@ -429,6 +430,7 @@
 
   SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "c(?r)c", &path, &rev, &token));
   SVN_ERR(lookup_token(ds, token, &entry, pool));
+  path = svn_path_canonicalize(path, entry->pool);
   SVN_CMD_ERR(ds->editor->delete_entry(path, rev, entry->baton, entry->pool));
   SVN_ERR(svn_ra_svn_write_cmd_response(conn, pool, ""));
   return SVN_NO_ERROR;
@@ -450,6 +452,9 @@
                                  &child_token, &copy_path, &copy_rev));
   SVN_ERR(lookup_token(ds, token, &entry, pool));
   subpool = svn_pool_create(entry->pool);
+  path = svn_path_canonicalize(path, subpool);
+  if (copy_path)
+    copy_path = svn_path_canonicalize(copy_path, subpool);
   SVN_CMD_ERR(ds->editor->add_directory(path, entry->baton, copy_path,
                                         copy_rev, subpool, &child_baton));
   store_token(ds, child_baton, child_token, subpool);
@@ -473,6 +478,7 @@
                                  &child_token, &rev));
   SVN_ERR(lookup_token(ds, token, &entry, pool));
   subpool = svn_pool_create(entry->pool);
+  path = svn_path_canonicalize(path, subpool);
   SVN_CMD_ERR(ds->editor->open_directory(path, entry->baton, rev, subpool,
                                          &child_baton));
   store_token(ds, child_baton, child_token, subpool);
@@ -541,6 +547,9 @@
 
   /* File may outlive parent directory, so use ds->pool here. */
   subpool = svn_pool_create(ds->pool);
+  path = svn_path_canonicalize(path, subpool);
+  if (copy_path)
+    copy_path = svn_path_canonicalize(copy_path, subpool);
   file_entry = store_token(ds, NULL, file_token, subpool);
   file_entry->err = ds->editor->add_file(path, entry->baton, copy_path,
                                          copy_rev, subpool,
@@ -565,6 +574,7 @@
 
   /* File may outlive parent directory, so use ds->pool here. */
   subpool = svn_pool_create(ds->pool);
+  path = svn_path_canonicalize(path, subpool);
   file_entry = store_token(ds, NULL, file_token, subpool);
   file_entry->err = ds->editor->open_file(path, entry->baton, rev, subpool,
                                           &file_entry->baton);
Index: subversion/svnserve/serve.c
===================================================================
--- subversion/svnserve/serve.c	(revision 12045)
+++ subversion/svnserve/serve.c	(arbetskopia)
@@ -240,6 +240,7 @@
 
   SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "crb",
                                  &path, &rev, &start_empty));
+  path = svn_path_canonicalize(path, pool);
   if (!b->err)
     b->err = svn_repos_set_path(b->report_baton, path, rev, start_empty, pool);
   return SVN_NO_ERROR;
@@ -252,6 +253,7 @@
   const char *path;
 
   SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "c", &path));
+  path = svn_path_canonicalize(path, pool);
   if (!b->err)
     b->err = svn_repos_delete_path(b->report_baton, path, pool);
   return SVN_NO_ERROR;
@@ -267,7 +269,8 @@
 
   SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "ccrb",
                                  &path, &url, &rev, &start_empty));
-  url = svn_path_uri_decode(url, pool);
+  path = svn_path_canonicalize(path, pool);
+  url = svn_path_uri_decode(svn_path_canonicalize(url, pool), pool);
   if (!b->err)
     b->err = get_fs_path(b->repos_url, url, &fs_path, pool);
   if (!b->err)
@@ -599,6 +602,7 @@
   /* Parse arguments. */
   SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "c(?r)bb", &path, &rev,
                                  &want_props, &want_contents));
+  path = svn_path_canonicalize(path, pool);
   SVN_ERR(trivial_auth_request(conn, pool, b));
   if (!SVN_IS_VALID_REVNUM(rev))
     SVN_CMD_ERR(svn_fs_youngest_rev(&rev, b->fs, pool));
@@ -672,6 +676,7 @@
 
   SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "c(?r)bb", &path, &rev,
                                  &want_props, &want_contents));
+  path = svn_path_canonicalize(path, pool);
   SVN_ERR(trivial_auth_request(conn, pool, b));
   if (!SVN_IS_VALID_REVNUM(rev))
     SVN_CMD_ERR(svn_fs_youngest_rev(&rev, b->fs, pool));
@@ -769,6 +774,7 @@
   /* Parse the arguments. */
   SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "(?r)cb", &rev, &target,
                                  &recurse));
+  target = svn_path_canonicalize(target, pool);
   SVN_ERR(trivial_auth_request(conn, pool, b));
   if (!SVN_IS_VALID_REVNUM(rev))
     SVN_CMD_ERR(svn_fs_youngest_rev(&rev, b->fs, pool));
@@ -788,6 +794,8 @@
   /* Parse the arguments. */
   SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "(?r)cbc", &rev, &target,
                                  &recurse, &switch_url));
+  target = svn_path_canonicalize(target, pool);
+  switch_url = svn_path_canonicalize(switch_url, pool);
   SVN_ERR(trivial_auth_request(conn, pool, b));
   if (!SVN_IS_VALID_REVNUM(rev))
     SVN_CMD_ERR(svn_fs_youngest_rev(&rev, b->fs, pool));
@@ -810,6 +818,7 @@
   /* Parse the arguments. */
   SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "cb?(?r)",
                                  &target, &recurse, &rev));
+  target = svn_path_canonicalize(target, pool);
   SVN_ERR(trivial_auth_request(conn, pool, b));
   if (!SVN_IS_VALID_REVNUM(rev))
     SVN_CMD_ERR(svn_fs_youngest_rev(&rev, b->fs, pool));
@@ -828,6 +837,8 @@
   /* Parse the arguments. */
   SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "(?r)cbbc", &rev, &target,
                                  &recurse, &ignore_ancestry, &versus_url));
+  target = svn_path_canonicalize(target, pool);
+  versus_url = svn_path_canonicalize(versus_url, pool);
   SVN_ERR(trivial_auth_request(conn, pool, b));
   if (!SVN_IS_VALID_REVNUM(rev))
     SVN_CMD_ERR(svn_fs_youngest_rev(&rev, b->fs, pool));
@@ -907,7 +918,10 @@
       if (elt->kind != SVN_RA_SVN_STRING)
         return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
                                 "Log path entry not a string");
-      full_path = svn_path_join(b->fs_path, elt->u.string->data, pool);
+      full_path = svn_path_join(b->fs_path,
+                                svn_path_canonicalize(elt->u.string->data,
+                                                      pool),
+                                pool);
       *((const char **) apr_array_push(full_paths)) = full_path;
     }
   SVN_ERR(trivial_auth_request(conn, pool, b));
@@ -940,6 +954,7 @@
   svn_node_kind_t kind;
 
   SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "c(?r)", &path, &rev));
+  path = svn_path_canonicalize(path, pool);
   SVN_ERR(trivial_auth_request(conn, pool, b));
   if (!SVN_IS_VALID_REVNUM(rev))
     SVN_CMD_ERR(svn_fs_youngest_rev(&rev, b->fs, pool));
@@ -971,6 +986,7 @@
   SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "crl", &relative_path,
                                  &peg_revision,
                                  &loc_revs_proto));
+  relative_path = svn_path_canonicalize(relative_path, pool);
 
   abs_path = svn_path_join(b->fs_path, relative_path, pool);
 
@@ -1099,6 +1115,7 @@
   /* Parse arguments. */
   SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "c(?r)(?r)",
                                  &path, &start_rev, &end_rev));
+  path = svn_path_canonicalize(path, pool);
   SVN_ERR(trivial_auth_request(conn, pool, b));
   full_path = svn_path_join(b->fs_path, path, pool);
 
@@ -1342,6 +1359,7 @@
       if (!success)
         return svn_ra_svn_flush(conn, pool);
       SVN_ERR(svn_ra_svn_read_tuple(conn, pool, "c", &client_url));
+      client_url = svn_path_canonicalize(client_url, pool);
       err = find_repos(client_url, params->root, &b, pool);
       if (!err && current_access(&b) == NO_ACCESS)
         err = svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL,
@@ -1360,6 +1378,7 @@
        * URL, and then we do an auth request. */
       SVN_ERR(svn_ra_svn_parse_tuple(item->u.list, pool, "nlc", &ver,
                                      &caplist, &client_url));
+      client_url = svn_path_canonicalize(client_url, pool);
       SVN_ERR(svn_ra_svn_set_capabilities(conn, caplist));
       err = find_repos(client_url, params->root, &b, pool);
       if (!err)
