You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2013/05/10 11:11:25 UTC

svn commit: r1480948 - in /subversion/branches/1.7.x-issue4340-repos: ./ subversion/libsvn_repos/commit.c subversion/tests/libsvn_repos/repos-test.c

Author: stsp
Date: Fri May 10 09:11:24 2013
New Revision: 1480948

URL: http://svn.apache.org/r1480948
Log:
On the 1.7.x-issue4340-repos branch, merge r1461760 from trunk, resolving
some semantic conflicts.

* subversion/tests/libsvn_repos/repos-test.c
  (filename_with_control_chars): Account for the lack of the
   SVN_TEST_ASSERT_ERROR macro on the 1.7.x branch.
   Also, update a comment to use the current synopsis of issue #4340.

Modified:
    subversion/branches/1.7.x-issue4340-repos/   (props changed)
    subversion/branches/1.7.x-issue4340-repos/subversion/libsvn_repos/commit.c
    subversion/branches/1.7.x-issue4340-repos/subversion/tests/libsvn_repos/repos-test.c

Propchange: subversion/branches/1.7.x-issue4340-repos/
------------------------------------------------------------------------------
  Merged /subversion/trunk:r1461760

Modified: subversion/branches/1.7.x-issue4340-repos/subversion/libsvn_repos/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x-issue4340-repos/subversion/libsvn_repos/commit.c?rev=1480948&r1=1480947&r2=1480948&view=diff
==============================================================================
--- subversion/branches/1.7.x-issue4340-repos/subversion/libsvn_repos/commit.c (original)
+++ subversion/branches/1.7.x-issue4340-repos/subversion/libsvn_repos/commit.c Fri May 10 09:11:24 2013
@@ -35,6 +35,7 @@
 #include "svn_fs.h"
 #include "svn_repos.h"
 #include "svn_checksum.h"
+#include "svn_ctype.h"
 #include "svn_props.h"
 #include "svn_mergeinfo.h"
 #include "repos.h"
@@ -196,6 +197,77 @@ make_dir_baton(struct edit_baton *edit_b
   return db;
 }
 
+/* Return a copy of PATH, allocated from POOL, for which control
+   characters have been escaped using the form \NNN (where NNN is the
+   octal representation of the byte's ordinal value).  */
+static const char *
+illegal_path_escape(const char *path, apr_pool_t *pool)
+{
+  svn_stringbuf_t *retstr;
+  apr_size_t i, copied = 0;
+  int c;
+
+  /* At least one control character:
+      strlen - 1 (control) + \ + N + N + N + null . */
+  retstr = svn_stringbuf_create_ensure(strlen(path) + 4, pool);
+  for (i = 0; path[i]; i++)
+    {
+      c = (unsigned char)path[i];
+      if (! svn_ctype_iscntrl(c))
+        continue;
+
+      /* If we got here, we're looking at a character that isn't
+         supported by the (or at least, our) URI encoding scheme.  We
+         need to escape this character.  */
+
+      /* First things first, copy all the good stuff that we haven't
+         yet copied into our output buffer. */
+      if (i - copied)
+        svn_stringbuf_appendbytes(retstr, path + copied,
+                                  i - copied);
+
+      /* Make sure buffer is big enough for '\' 'N' 'N' 'N' (and NUL) */
+      svn_stringbuf_ensure(retstr, retstr->len + 4);
+      /*### The backslash separator doesn't work too great with Windows,
+         but it's what we'll use for consistency with invalid utf8
+         formatting (until someone has a better idea) */
+      apr_snprintf(retstr->data + retstr->len, 5, "\\%03o", (unsigned char)c);
+      retstr->len += 4;
+
+      /* Finally, update our copy counter. */
+      copied = i + 1;
+    }
+
+  /* If we didn't encode anything, we don't need to duplicate the string. */
+  if (retstr->len == 0)
+    return path;
+
+  /* Anything left to copy? */
+  if (i - copied)
+    svn_stringbuf_appendbytes(retstr, path + copied, i - copied);
+
+  /* retstr is null-terminated either by apr_snprintf or the svn_stringbuf
+     functions. */
+
+  return retstr->data;
+}
+
+static svn_error_t *
+check_cntrl(const char *path,
+            apr_pool_t *pool)
+{
+  const char *c;
+
+  for (c = path; *c; c++)
+    {
+      if (svn_ctype_iscntrl(*c))
+        return svn_error_createf(SVN_ERR_FS_PATH_SYNTAX, NULL,
+           _("Invalid control character '0x%02x' in path '%s'"),
+           (unsigned char)*c, illegal_path_escape(path, pool));
+    }
+
+  return SVN_NO_ERROR;
+}
 
 /* This function is the shared guts of add_file() and add_directory(),
    which see for the meanings of the parameters.  The only extra
@@ -216,6 +288,9 @@ add_file_or_directory(const char *path,
   svn_boolean_t was_copied = FALSE;
   const char *full_path;
 
+  /* Reject paths which contain control characters (related to issue #4340). */
+  SVN_ERR(check_cntrl(path, pool));
+
   full_path = svn_fspath__join(eb->base_path,
                                svn_relpath_canonicalize(path, pool), pool);
 

Modified: subversion/branches/1.7.x-issue4340-repos/subversion/tests/libsvn_repos/repos-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x-issue4340-repos/subversion/tests/libsvn_repos/repos-test.c?rev=1480948&r1=1480947&r2=1480948&view=diff
==============================================================================
--- subversion/branches/1.7.x-issue4340-repos/subversion/tests/libsvn_repos/repos-test.c (original)
+++ subversion/branches/1.7.x-issue4340-repos/subversion/tests/libsvn_repos/repos-test.c Fri May 10 09:11:24 2013
@@ -2526,6 +2526,104 @@ issue_4060(const svn_test_opts_t *opts,
   return SVN_NO_ERROR;
 }
 
+
+/* Related to issue 4340, "filenames containing \n corrupt FSFS repositories" */
+static svn_error_t *
+filename_with_control_chars(const svn_test_opts_t *opts,
+                            apr_pool_t *pool)
+{
+  apr_pool_t *subpool = svn_pool_create(pool);
+  svn_repos_t *repos;
+  svn_fs_t *fs;
+  svn_fs_txn_t *txn;
+  svn_fs_root_t *txn_root;
+  svn_revnum_t youngest_rev = 0;
+  svn_error_t *err;
+  static const char *bad_paths[] = {
+    "/bar\t",
+    "/bar\n",
+    "/\barb\az",
+    "/\x02 baz",
+    NULL,
+  };
+  const char *p;
+  int i;
+  void *edit_baton;
+  void *root_baton;
+  void *out_baton;
+  const svn_delta_editor_t *editor;
+
+  /* Create the repository. */
+  SVN_ERR(svn_test__create_repos(&repos, "test-repos-filename-with-cntrl-chars",
+                                 opts, pool));
+  fs = svn_repos_fs(repos);
+
+  /* Revision 1:  Add a directory /foo  */
+  SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, subpool));
+  SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool));
+  SVN_ERR(svn_fs_make_dir(txn_root, "/foo", subpool));
+  SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, subpool));
+  SVN_TEST_ASSERT(SVN_IS_VALID_REVNUM(youngest_rev));
+  svn_pool_clear(subpool);
+
+  /* Checks for control characters are implemented in the commit editor,
+   * not in the FS API. */
+  SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, pool));
+  SVN_ERR(svn_repos_get_commit_editor4(&editor, &edit_baton, repos,
+                                       txn, "file://test", "/",
+                                       "plato", "test commit",
+                                       dummy_commit_cb, NULL, NULL, NULL,
+                                       pool));
+
+  SVN_ERR(editor->open_root(edit_baton, 1, pool, &root_baton));
+
+  /* Attempt to copy /foo to a bad path P. This should fail. */
+  i = 0;
+  do
+    {
+      p = bad_paths[i++];
+      if (p == NULL)
+        break;
+      svn_pool_clear(subpool);
+      err = editor->add_directory(p, root_baton, "/foo", 1, subpool,
+                                  &out_baton);
+      SVN_TEST_ASSERT(err && err->apr_err == SVN_ERR_FS_PATH_SYNTAX);
+      svn_error_clear(err);
+  } while (p);
+
+  /* Attempt to add a file with bad path P. This should fail. */
+  i = 0;
+  do
+    {
+      p = bad_paths[i++];
+      if (p == NULL)
+        break;
+      svn_pool_clear(subpool);
+      err = editor->add_file(p, root_baton, NULL, SVN_INVALID_REVNUM,
+                             subpool, &out_baton);
+      SVN_TEST_ASSERT(err && err->apr_err == SVN_ERR_FS_PATH_SYNTAX);
+      svn_error_clear(err);
+  } while (p);
+
+
+  /* Attempt to add a directory with bad path P. This should fail. */
+  i = 0;
+  do
+    {
+      p = bad_paths[i++];
+      if (p == NULL)
+        break;
+      svn_pool_clear(subpool);
+      err = editor->add_directory(p, root_baton, NULL, SVN_INVALID_REVNUM,
+                                  subpool, &out_baton);
+      SVN_TEST_ASSERT(err && err->apr_err == SVN_ERR_FS_PATH_SYNTAX);
+      svn_error_clear(err);
+  } while (p);
+
+  SVN_ERR(editor->abort_edit(edit_baton, subpool));
+
+  return SVN_NO_ERROR;
+}
 
 /* The test table.  */
 
@@ -2562,5 +2660,7 @@ struct svn_test_descriptor_t test_funcs[
                        "test svn_repos_get_file_revsN"),
     SVN_TEST_OPTS_PASS(issue_4060,
                        "test issue 4060"),
+    SVN_TEST_OPTS_PASS(filename_with_control_chars,
+                       "test filenames with control characters"),
     SVN_TEST_NULL
   };