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/03/27 19:13:36 UTC
svn commit: r1461760 - in /subversion/trunk/subversion:
libsvn_repos/commit.c tests/libsvn_repos/repos-test.c
Author: stsp
Date: Wed Mar 27 18:13:36 2013
New Revision: 1461760
URL: http://svn.apache.org/r1461760
Log:
Reject paths containing control characters at the repos layer.
Newly added paths are checked by the repos commit editor, and rejected
if they contain control characters.
Related to issue #4340.
* subversion/libsvn_repos/commit.c
(illegal_path_escape): New, copied from libsvn_subr/path.c.
Going forward, we could make this function public in libsvn_subr.
But a static copy in this file will make backports easier for now.
(check_cntrl): New, based on svn_path_check_valid().
(add_file_or_directory): Reject paths which contain control characters.
* subversion/tests/libsvn_repos/repos-test.c
(filename_with_control_chars): New test.
(test_funcs): Add new test.
Modified:
subversion/trunk/subversion/libsvn_repos/commit.c
subversion/trunk/subversion/tests/libsvn_repos/repos-test.c
Modified: subversion/trunk/subversion/libsvn_repos/commit.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_repos/commit.c?rev=1461760&r1=1461759&r2=1461760&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_repos/commit.c (original)
+++ subversion/trunk/subversion/libsvn_repos/commit.c Wed Mar 27 18:13:36 2013
@@ -36,6 +36,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 "svn_private_config.h"
@@ -258,6 +259,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
@@ -278,6 +350,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/trunk/subversion/tests/libsvn_repos/repos-test.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_repos/repos-test.c?rev=1461760&r1=1461759&r2=1461760&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_repos/repos-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_repos/repos-test.c Wed Mar 27 18:13:36 2013
@@ -3164,6 +3164,101 @@ test_delete_repos(const svn_test_opts_t
return SVN_NO_ERROR;
}
+
+/* Related to issue 4340, "fs layer should reject filenames with trailing \n" */
+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_ERROR(err, SVN_ERR_FS_PATH_SYNTAX);
+ } 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_ERROR(err, SVN_ERR_FS_PATH_SYNTAX);
+ } 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_ERROR(err, SVN_ERR_FS_PATH_SYNTAX);
+ } while (p);
+
+ SVN_ERR(editor->abort_edit(edit_baton, subpool));
+
+ return SVN_NO_ERROR;
+}
/* The test table. */
@@ -3208,5 +3303,7 @@ struct svn_test_descriptor_t test_funcs[
"test issue 4060"),
SVN_TEST_OPTS_PASS(test_delete_repos,
"test svn_repos_delete"),
+ SVN_TEST_OPTS_PASS(filename_with_control_chars,
+ "test filenames with control characters"),
SVN_TEST_NULL
};