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 2022/01/14 14:01:51 UTC
svn commit: r1897034 [21/37] - in /subversion/branches/multi-wc-format: ./ build/ build/ac-macros/ build/generator/ build/generator/swig/ build/generator/templates/ contrib/client-side/ contrib/client-side/svn_load_dirs/ contrib/hook-scripts/ contrib/s...
Modified: subversion/branches/multi-wc-format/subversion/libsvn_repos/authz_parse.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_repos/authz_parse.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_repos/authz_parse.c (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_repos/authz_parse.c Fri Jan 14 14:01:45 2022
@@ -83,7 +83,7 @@ typedef struct ctor_baton_t
same immutable string multiple times, we reduce the size of the
authz representation in the result pool.
- N.B.: Whilst the strings are allocated from teh result pool, the
+ N.B.: Whilst the strings are allocated from the result pool, the
hash table itself is not. */
apr_hash_t *strings;
@@ -127,6 +127,10 @@ typedef struct ctor_baton_t
svn_membuf_t rule_path_buffer;
svn_stringbuf_t *rule_string_buffer;
+ /* The warning callback and its baton. */
+ svn_repos_authz_warning_func_t warning_func;
+ void *warning_baton;
+
/* The parser's scratch pool. This may not be the same pool as
passed to the constructor callbacks, that is supposed to be an
iteration pool maintained by the generic parser.
@@ -154,6 +158,8 @@ static const char anon_access_token[] =
/* The authenticated access token. */
static const char authn_access_token[] = "$authenticated";
+/* Fake token for inverted rights. */
+static const char neg_access_token[] = "~~$inverted";
/* Initialize a rights structure.
The minimum rights start with all available access and are later
@@ -191,15 +197,19 @@ insert_default_acl(ctor_baton_t *cb)
acl->acl.has_anon_access = TRUE;
acl->acl.authn_access = authz_access_none;
acl->acl.has_authn_access = TRUE;
+ acl->acl.neg_access = authz_access_none;
+ acl->acl.has_neg_access = TRUE;
acl->acl.user_access = NULL;
acl->aces = svn_hash__make(cb->parser_pool);
acl->alias_aces = svn_hash__make(cb->parser_pool);
}
-/* Initialize a constuctor baton. */
+/* Initialize a constructor baton. */
static ctor_baton_t *
-create_ctor_baton(apr_pool_t *result_pool,
+create_ctor_baton(svn_repos_authz_warning_func_t warning_func,
+ void *warning_baton,
+ apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
apr_pool_t *const parser_pool = svn_pool_create(scratch_pool);
@@ -208,6 +218,7 @@ create_ctor_baton(apr_pool_t *result_poo
authz_full_t *const authz = apr_pcalloc(result_pool, sizeof(*authz));
init_global_rights(&authz->anon_rights, anon_access_token, result_pool);
init_global_rights(&authz->authn_rights, authn_access_token, result_pool);
+ init_global_rights(&authz->neg_rights, neg_access_token, result_pool);
authz->user_rights = svn_hash__make(result_pool);
authz->pool = result_pool;
@@ -229,6 +240,9 @@ create_ctor_baton(apr_pool_t *result_poo
svn_membuf__create(&cb->rule_path_buffer, 0, parser_pool);
cb->rule_string_buffer = svn_stringbuf_create_empty(parser_pool);
+ cb->warning_func = warning_func;
+ cb->warning_baton = warning_baton;
+
cb->parser_pool = parser_pool;
insert_default_acl(cb);
@@ -237,6 +251,25 @@ create_ctor_baton(apr_pool_t *result_poo
}
+/* Emit a warning. Clears ERROR */
+static void
+emit_parser_warning(const ctor_baton_t *cb,
+ svn_error_t *error,
+ apr_pool_t *scratch_pool)
+{
+ if (cb->warning_func)
+ cb->warning_func(cb->warning_baton, error, scratch_pool);
+ svn_error_clear(error);
+}
+
+/* Avoid creating an error struct if there is no warning function. */
+#define SVN_AUTHZ_PARSE_WARN(cb, err, pool) \
+ do { \
+ if ((cb) && (cb)->warning_func) \
+ emit_parser_warning((cb), (err), (pool)); \
+ } while(0)
+
+
/* Create and store per-user global rights.
The USER string must be interned or statically initialized. */
static void
@@ -536,7 +569,7 @@ parse_rule_path(authz_rule_t *rule,
|| (pattern->len == 2 && pattern->data[1] == '*'))
{
/* Process * and **, applying normalization as per
- https://wiki.apache.org/subversion/AuthzImprovements. */
+ https://cwiki.apache.org/confluence/display/SVN/Authz+Improvements. */
authz_rule_segment_t *const prev =
(nseg > 1 ? segment - 1 : NULL);
@@ -758,6 +791,8 @@ rules_open_section(void *baton, svn_stri
acl.acl.has_anon_access = FALSE;
acl.acl.authn_access = authz_access_none;
acl.acl.has_authn_access = FALSE;
+ acl.acl.neg_access = authz_access_none;
+ acl.acl.has_neg_access = FALSE;
acl.acl.user_access = NULL;
acl.aces = svn_hash__make(cb->parser_pool);
@@ -930,7 +965,7 @@ add_access_entry(ctor_baton_t *cb, svn_s
{
/* The inversion tag must be part of the key in the hash
table, otherwise we can't tell regular and inverted
- entries appart. */
+ entries apart. */
const char *key = (inverted ? name - 1 : name);
const apr_size_t key_len = (inverted ? name_len + 1 : name_len);
const svn_boolean_t aliased = (*name == '&');
@@ -958,6 +993,14 @@ add_access_entry(ctor_baton_t *cb, svn_s
if (!aliased && *ace->name != '@')
prepare_global_rights(cb, ace->name);
}
+
+ /* Propagate rights for inverted selectors to the global rights, otherwise
+ an access check can bail out early. See: SVN-4793 */
+ if (inverted)
+ {
+ acl->acl.has_neg_access = TRUE;
+ acl->acl.neg_access |= access;
+ }
}
return SVN_NO_ERROR;
@@ -996,7 +1039,8 @@ close_section(void *baton, svn_stringbuf
/* Add a user to GROUP.
- GROUP is never internalized, but USER always is. */
+ GROUP is never internalized, but USER always is.
+ Adding a NULL user will create an empty group, if it doesn't exist. */
static void
add_to_group(ctor_baton_t *cb, const char *group, const char *user)
{
@@ -1007,7 +1051,8 @@ add_to_group(ctor_baton_t *cb, const cha
members = svn_hash__make(cb->authz->pool);
svn_hash_sets(cb->expanded_groups, group, members);
}
- svn_hash_sets(members, user, interned_empty_string);
+ if (user)
+ svn_hash_sets(members, user, interned_empty_string);
}
@@ -1023,8 +1068,15 @@ expand_group_callback(void *baton,
ctor_baton_t *const cb = baton;
const char *const group = key;
apr_array_header_t *members = value;
-
int i;
+
+ if (0 == members->nelts)
+ {
+ /* Create the group with no members. */
+ add_to_group(cb, group, NULL);
+ return SVN_NO_ERROR;
+ }
+
for (i = 0; i < members->nelts; ++i)
{
const char *member = APR_ARRAY_IDX(members, i, const char*);
@@ -1154,10 +1206,24 @@ array_insert_ace(void *baton,
SVN_ERR_ASSERT(ace->members == NULL);
ace->members = svn_hash_gets(iab->cb->expanded_groups, ace->name);
if (!ace->members)
- return svn_error_createf(
- SVN_ERR_AUTHZ_INVALID_CONFIG, NULL,
- _("Access entry refers to undefined group '%s'"),
- ace->name);
+ {
+ return svn_error_createf(
+ SVN_ERR_AUTHZ_INVALID_CONFIG, NULL,
+ _("Access entry refers to undefined group '%s'"),
+ ace->name);
+ }
+ else if (0 == apr_hash_count(ace->members))
+ {
+ /* An ACE for an empty group has no effect, so ignore it. */
+ SVN_AUTHZ_PARSE_WARN(
+ iab->cb,
+ svn_error_createf(
+ SVN_ERR_AUTHZ_INVALID_CONFIG, NULL,
+ _("Ignoring access entry for empty group '%s'"),
+ ace->name),
+ scratch_pool);
+ return SVN_NO_ERROR;
+ }
}
APR_ARRAY_PUSH(iab->ace_array, authz_ace_t) = *ace;
@@ -1271,6 +1337,12 @@ expand_acl_callback(void *baton,
update_global_rights(&cb->authz->authn_rights,
acl->rule.repos, acl->authn_access);
}
+ if (acl->has_neg_access)
+ {
+ cb->authz->has_neg_rights = TRUE;
+ update_global_rights(&cb->authz->neg_rights,
+ acl->rule.repos, acl->neg_access);
+ }
SVN_ERR(svn_iter_apr_hash(NULL, cb->authz->user_rights,
update_user_rights, acl, scratch_pool));
return SVN_NO_ERROR;
@@ -1297,10 +1369,13 @@ svn_error_t *
svn_authz__parse(authz_full_t **authz,
svn_stream_t *rules,
svn_stream_t *groups,
+ svn_repos_authz_warning_func_t warning_func,
+ void *warning_baton,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- ctor_baton_t *const cb = create_ctor_baton(result_pool, scratch_pool);
+ ctor_baton_t *const cb = create_ctor_baton(warning_func, warning_baton,
+ result_pool, scratch_pool);
/*
* Pass 1: Parse the authz file.
Modified: subversion/branches/multi-wc-format/subversion/libsvn_repos/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_repos/commit.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_repos/commit.c (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_repos/commit.c Fri Jan 14 14:01:45 2022
@@ -124,7 +124,7 @@ struct dir_baton
svn_revnum_t base_rev; /* the revision I'm based on */
svn_boolean_t was_copied; /* was this directory added with history? */
apr_pool_t *pool; /* my personal pool, in which I am allocated. */
- svn_boolean_t checked_write; /* TRUE after successfull write check */
+ svn_boolean_t checked_write; /* TRUE after successful write check */
};
@@ -132,7 +132,7 @@ struct file_baton
{
struct edit_baton *edit_baton;
const char *path; /* the -absolute- path to this file in the fs */
- svn_boolean_t checked_write; /* TRUE after successfull write check */
+ svn_boolean_t checked_write; /* TRUE after successful write check */
};
@@ -189,7 +189,7 @@ check_out_of_date(struct edit_baton *eb,
else if (base_rev > created_rev)
{
if (base_rev > svn_fs_txn_base_revision(eb->txn))
- return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL,
+ return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL,
_("No such revision %ld"),
base_rev);
}
@@ -306,13 +306,14 @@ add_file_or_directory(const char *path,
struct edit_baton *eb = pb->edit_baton;
apr_pool_t *subpool = svn_pool_create(pool);
svn_boolean_t was_copied = FALSE;
- const char *full_path;
+ const char *full_path, *canonicalized_path;
/* Reject paths which contain control characters (related to issue #4340). */
SVN_ERR(svn_path_check_valid(path, pool));
- full_path = svn_fspath__join(eb->base_path,
- svn_relpath_canonicalize(path, pool), pool);
+ SVN_ERR(svn_relpath_canonicalize_safe(&canonicalized_path, NULL, path,
+ pool, pool));
+ full_path = svn_fspath__join(eb->base_path, canonicalized_path, pool);
/* Sanity check. */
if (copy_path && (! SVN_IS_VALID_REVNUM(copy_revision)))
@@ -477,10 +478,11 @@ delete_entry(const char *path,
struct edit_baton *eb = parent->edit_baton;
svn_node_kind_t kind;
svn_repos_authz_access_t required = svn_authz_write;
- const char *full_path;
+ const char *full_path, *canonicalized_path;
- full_path = svn_fspath__join(eb->base_path,
- svn_relpath_canonicalize(path, pool), pool);
+ SVN_ERR(svn_relpath_canonicalize_safe(&canonicalized_path, NULL, path,
+ pool, pool));
+ full_path = svn_fspath__join(eb->base_path, canonicalized_path, pool);
/* Check PATH in our transaction. */
SVN_ERR(svn_fs_check_path(&kind, eb->txn_root, full_path, pool));
@@ -538,10 +540,11 @@ open_directory(const char *path,
struct dir_baton *pb = parent_baton;
struct edit_baton *eb = pb->edit_baton;
svn_node_kind_t kind;
- const char *full_path;
+ const char *full_path, *canonicalized_path;
- full_path = svn_fspath__join(eb->base_path,
- svn_relpath_canonicalize(path, pool), pool);
+ SVN_ERR(svn_relpath_canonicalize_safe(&canonicalized_path, NULL, path,
+ pool, pool));
+ full_path = svn_fspath__join(eb->base_path, canonicalized_path, pool);
/* Check PATH in our transaction. If it does not exist,
return a 'Path not present' error. */
@@ -611,10 +614,11 @@ open_file(const char *path,
struct edit_baton *eb = pb->edit_baton;
svn_revnum_t cr_rev;
apr_pool_t *subpool = svn_pool_create(pool);
- const char *full_path;
+ const char *full_path, *canonicalized_path;
- full_path = svn_fspath__join(eb->base_path,
- svn_relpath_canonicalize(path, pool), pool);
+ SVN_ERR(svn_relpath_canonicalize_safe(&canonicalized_path, NULL, path,
+ pool, pool));
+ full_path = svn_fspath__join(eb->base_path, canonicalized_path, pool);
/* Check for read authorization. */
SVN_ERR(check_authz(eb, full_path, eb->txn_root,
@@ -637,7 +641,7 @@ open_file(const char *path,
*file_baton = new_fb;
- /* Destory the work subpool. */
+ /* Destroy the work subpool. */
svn_pool_destroy(subpool);
return SVN_NO_ERROR;
Modified: subversion/branches/multi-wc-format/subversion/libsvn_repos/compat.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_repos/compat.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_repos/compat.c (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_repos/compat.c Fri Jan 14 14:01:45 2022
@@ -98,7 +98,7 @@ log4_path_change_receiver(void *baton,
: svn_tristate_false;
/* Auto-create the CHANGES container (happens for each first change
- * in any revison. */
+ * in any revision. */
if (b->changes == NULL)
b->changes = svn_hash__make(b->changes_pool);
Modified: subversion/branches/multi-wc-format/subversion/libsvn_repos/config_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_repos/config_file.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_repos/config_file.c (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_repos/config_file.c Fri Jan 14 14:01:45 2022
@@ -237,6 +237,10 @@ get_repos_config(svn_stream_t **stream,
{
/* Search for a repository in the full path. */
repos_root_dirent = svn_repos_find_root_path(dirent, scratch_pool);
+ if (repos_root_dirent == NULL)
+ return svn_error_trace(handle_missing_file(stream, checksum, access,
+ url, must_exist,
+ svn_node_none));
/* Attempt to open a repository at repos_root_dirent. */
SVN_ERR(svn_repos_open3(&access->repos, repos_root_dirent, NULL,
@@ -342,7 +346,7 @@ svn_repos__create_config_access(svn_repo
return result;
}
-void
+void
svn_repos__destroy_config_access(config_access_t *access)
{
svn_pool_destroy(access->pool);
Modified: subversion/branches/multi-wc-format/subversion/libsvn_repos/config_file.h
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_repos/config_file.h?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_repos/config_file.h (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_repos/config_file.h Fri Jan 14 14:01:45 2022
@@ -48,7 +48,7 @@ svn_repos__create_config_access(svn_repo
apr_pool_t *result_pool);
/* Release all resources allocated while using ACCESS. */
-void
+void
svn_repos__destroy_config_access(config_access_t *access);
/* Using ACCESS as a helper object, access the textual configuration at PATH,
Modified: subversion/branches/multi-wc-format/subversion/libsvn_repos/delta.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_repos/delta.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_repos/delta.c (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_repos/delta.c Fri Jan 14 14:01:45 2022
@@ -215,7 +215,7 @@ svn_repos_dir_delta2(svn_fs_root_t *src_
{
void *root_baton = NULL;
struct context c;
- const char *src_fullpath;
+ const char *src_fullpath, *canonicalized_path;
svn_node_kind_t src_kind, tgt_kind;
svn_revnum_t rootrev;
svn_fs_node_relation_t relation;
@@ -223,14 +223,22 @@ svn_repos_dir_delta2(svn_fs_root_t *src_
/* SRC_PARENT_DIR must be valid. */
if (src_parent_dir)
- src_parent_dir = svn_relpath_canonicalize(src_parent_dir, pool);
+ {
+ SVN_ERR(svn_relpath_canonicalize_safe(&canonicalized_path, NULL,
+ src_parent_dir, pool, pool));
+ src_parent_dir = canonicalized_path;
+ }
else
return svn_error_create(SVN_ERR_FS_NOT_DIRECTORY, 0,
"Invalid source parent directory '(null)'");
/* TGT_FULLPATH must be valid. */
if (tgt_fullpath)
- tgt_fullpath = svn_relpath_canonicalize(tgt_fullpath, pool);
+ {
+ SVN_ERR(svn_relpath_canonicalize_safe(&canonicalized_path, NULL,
+ tgt_fullpath, pool, pool));
+ tgt_fullpath = canonicalized_path;
+ }
else
return svn_error_create(SVN_ERR_FS_PATH_SYNTAX, 0,
_("Invalid target path"));
Modified: subversion/branches/multi-wc-format/subversion/libsvn_repos/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_repos/deprecated.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_repos/deprecated.c (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_repos/deprecated.c Fri Jan 14 14:01:45 2022
@@ -1273,6 +1273,21 @@ svn_repos_fs_begin_txn_for_update(svn_fs
/*** From authz.c ***/
svn_error_t *
+svn_repos_authz_read3(svn_authz_t **authz_p,
+ const char *path,
+ const char *groups_path,
+ svn_boolean_t must_exist,
+ svn_repos_t *repos_hint,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ return svn_error_trace(svn_repos_authz_read4(authz_p, path, groups_path,
+ must_exist, repos_hint,
+ NULL, NULL, result_pool,
+ scratch_pool));
+}
+
+svn_error_t *
svn_repos_authz_read2(svn_authz_t **authz_p,
const char *path,
const char *groups_path,
@@ -1300,3 +1315,17 @@ svn_repos_authz_read(svn_authz_t **authz
return svn_error_trace(svn_repos_authz_read2(authz_p, file, NULL,
must_exist, pool));
}
+
+svn_error_t *
+svn_repos_authz_parse(svn_authz_t **authz_p,
+ svn_stream_t *stream,
+ svn_stream_t *groups_stream,
+ apr_pool_t *pool)
+{
+ apr_pool_t *scratch_pool = svn_pool_create(pool);
+ svn_error_t *err = svn_repos_authz_parse2(authz_p, stream, groups_stream,
+ NULL, NULL, pool, scratch_pool);
+ svn_pool_destroy(scratch_pool);
+
+ return svn_error_trace(err);
+}
Modified: subversion/branches/multi-wc-format/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_repos/dump.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_repos/dump.c Fri Jan 14 14:01:45 2022
@@ -44,6 +44,7 @@
#include "private/svn_sorts_private.h"
#include "private/svn_utf_private.h"
#include "private/svn_cache.h"
+#include "private/svn_fspath.h"
#define ARE_VALID_COPY_ARGS(p,r) ((p) && SVN_IS_VALID_REVNUM(r))
@@ -737,8 +738,9 @@ struct dir_baton
or NULL if this is the top-level directory of the edit.
Perform all allocations in POOL. */
-static struct dir_baton *
-make_dir_baton(const char *path,
+static struct svn_error_t *
+make_dir_baton(struct dir_baton **dbp,
+ const char *path,
const char *cmp_path,
svn_revnum_t cmp_rev,
void *edit_baton,
@@ -747,10 +749,10 @@ make_dir_baton(const char *path,
{
struct edit_baton *eb = edit_baton;
struct dir_baton *new_db = apr_pcalloc(pool, sizeof(*new_db));
- const char *full_path;
+ const char *full_path, *canonicalized_path;
/* A path relative to nothing? I don't think so. */
- SVN_ERR_ASSERT_NO_RETURN(!path || pb);
+ SVN_ERR_ASSERT(!path || pb);
/* Construct the full path of this node. */
if (pb)
@@ -760,7 +762,11 @@ make_dir_baton(const char *path,
/* Remove leading slashes from copyfrom paths. */
if (cmp_path)
- cmp_path = svn_relpath_canonicalize(cmp_path, pool);
+ {
+ SVN_ERR(svn_relpath_canonicalize_safe(&canonicalized_path, NULL,
+ cmp_path, pool, pool));
+ cmp_path = canonicalized_path;
+ }
new_db->edit_baton = eb;
new_db->path = full_path;
@@ -771,7 +777,8 @@ make_dir_baton(const char *path,
new_db->check_name_collision = FALSE;
new_db->pool = pool;
- return new_db;
+ *dbp = new_db;
+ return SVN_NO_ERROR;
}
static svn_error_t *
@@ -1167,7 +1174,12 @@ dump_node(struct edit_baton *eb,
/* Remove leading slashes from copyfrom paths. */
if (cmp_path)
- cmp_path = svn_relpath_canonicalize(cmp_path, pool);
+ {
+ const char *canonicalized_path;
+ SVN_ERR(svn_relpath_canonicalize_safe(&canonicalized_path, NULL,
+ cmp_path, pool, pool));
+ cmp_path = canonicalized_path;
+ }
/* Validate the comparison path/rev. */
if (ARE_VALID_COPY_ARGS(cmp_path, cmp_rev))
@@ -1537,9 +1549,9 @@ open_root(void *edit_baton,
apr_pool_t *pool,
void **root_baton)
{
- *root_baton = make_dir_baton(NULL, NULL, SVN_INVALID_REVNUM,
- edit_baton, NULL, pool);
- return SVN_NO_ERROR;
+ return svn_error_trace(make_dir_baton((struct dir_baton **)root_baton,
+ NULL, NULL, SVN_INVALID_REVNUM,
+ edit_baton, NULL, pool));
}
@@ -1571,8 +1583,10 @@ add_directory(const char *path,
struct edit_baton *eb = pb->edit_baton;
void *was_deleted;
svn_boolean_t is_copy = FALSE;
- struct dir_baton *new_db
- = make_dir_baton(path, copyfrom_path, copyfrom_rev, eb, pb, pool);
+ struct dir_baton *new_db;
+
+ SVN_ERR(make_dir_baton(&new_db, path, copyfrom_path, copyfrom_rev, eb,
+ pb, pool));
/* This might be a replacement -- is the path already deleted? */
was_deleted = svn_hash_gets(pb->deleted_entries, path);
@@ -1629,7 +1643,7 @@ open_directory(const char *path,
cmp_rev = pb->cmp_rev;
}
- new_db = make_dir_baton(path, cmp_path, cmp_rev, eb, pb, pool);
+ SVN_ERR(make_dir_baton(&new_db, path, cmp_path, cmp_rev, eb, pb, pool));
*child_baton = new_db;
return SVN_NO_ERROR;
}
@@ -1996,6 +2010,11 @@ dump_filter_authz_func(svn_boolean_t *al
{
dump_filter_baton_t *b = baton;
+ /* For some nodes (e.g. files under copied directory) PATH may be
+ * non-canonical (missing leading '/'). Canonicalize PATH before
+ * passing it to FILTER_FUNC. */
+ path = svn_fspath__canonicalize(path, pool);
+
return svn_error_trace(b->filter_func(allowed, root, path, b->filter_baton,
pool));
}
Modified: subversion/branches/multi-wc-format/subversion/libsvn_repos/dump_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_repos/dump_editor.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_repos/dump_editor.c (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_repos/dump_editor.c Fri Jan 14 14:01:45 2022
@@ -61,8 +61,8 @@ normalize_props(apr_hash_t **normal_prop
svn_pool_clear(iterpool);
SVN_ERR(svn_repos__normalize_prop(&value, NULL, key, value,
- result_pool, iterpool));
- svn_hash_sets(*normal_props, key, value);
+ iterpool, iterpool));
+ svn_hash_sets(*normal_props, key, svn_string_dup(value, result_pool));
}
svn_pool_destroy(iterpool);
@@ -178,8 +178,9 @@ struct dump_edit_baton {
* this is the top-level directory of the edit.
*
* Perform all allocations in POOL. */
-static struct dir_baton *
-make_dir_baton(const char *path,
+static struct svn_error_t *
+make_dir_baton(struct dir_baton **dbp,
+ const char *path,
const char *copyfrom_path,
svn_revnum_t copyfrom_rev,
void *edit_baton,
@@ -192,7 +193,8 @@ make_dir_baton(const char *path,
/* Construct the full path of this node. */
if (pb)
- repos_relpath = svn_relpath_canonicalize(path, pool);
+ SVN_ERR(svn_relpath_canonicalize_safe(&repos_relpath, NULL, path,
+ pool, pool));
else
repos_relpath = "";
@@ -213,7 +215,8 @@ make_dir_baton(const char *path,
new_db->deleted_props = apr_hash_make(pool);
new_db->deleted_entries = apr_hash_make(pool);
- return new_db;
+ *dbp = new_db;
+ return SVN_NO_ERROR;
}
/* Make a file baton to represent the directory at PATH (relative to
@@ -577,8 +580,8 @@ open_root(void *edit_baton,
{
/* ... but for the source directory itself, we'll defer
to letting the typical plumbing handle this task. */
- new_db = make_dir_baton(NULL, NULL, SVN_INVALID_REVNUM,
- edit_baton, NULL, pool);
+ SVN_ERR(make_dir_baton(&new_db, NULL, NULL, SVN_INVALID_REVNUM,
+ edit_baton, NULL, pool));
SVN_ERR(dump_node(&new_db->headers,
eb, new_db->repos_relpath, new_db,
NULL, svn_node_action_add, FALSE,
@@ -594,8 +597,8 @@ open_root(void *edit_baton,
if (! new_db)
{
- new_db = make_dir_baton(NULL, NULL, SVN_INVALID_REVNUM,
- edit_baton, NULL, pool);
+ SVN_ERR(make_dir_baton(&new_db, NULL, NULL, SVN_INVALID_REVNUM,
+ edit_baton, NULL, pool));
}
*root_baton = new_db;
@@ -636,8 +639,8 @@ add_directory(const char *path,
SVN_ERR(dump_pending_dir(pb->eb, pool));
- new_db = make_dir_baton(path, copyfrom_path, copyfrom_rev, pb->eb,
- pb, pb->pool);
+ SVN_ERR(make_dir_baton(&new_db, path, copyfrom_path, copyfrom_rev, pb->eb,
+ pb, pb->pool));
/* This might be a replacement -- is the path already deleted? */
was_deleted = svn_hash_gets(pb->deleted_entries, path);
@@ -690,8 +693,8 @@ open_directory(const char *path,
copyfrom_rev = pb->copyfrom_rev;
}
- new_db = make_dir_baton(path, copyfrom_path, copyfrom_rev, pb->eb, pb,
- pb->pool);
+ SVN_ERR(make_dir_baton(&new_db, path, copyfrom_path, copyfrom_rev,
+ pb->eb, pb, pb->pool));
*child_baton = new_db;
return SVN_NO_ERROR;
Modified: subversion/branches/multi-wc-format/subversion/libsvn_repos/fs-wrap.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_repos/fs-wrap.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_repos/fs-wrap.c (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_repos/fs-wrap.c Fri Jan 14 14:01:45 2022
@@ -282,7 +282,7 @@ svn_repos__normalize_prop(const svn_stri
}
else
{
- *result_p = svn_string_dup(value, result_pool);
+ *result_p = value;
if (normalized_p)
*normalized_p = FALSE;
}
@@ -1106,7 +1106,7 @@ svn_repos_fs_get_inherited_props(apr_arr
apr_pstrdup(result_pool, parent_path + 1);
i_props->prop_hash = parent_properties;
/* Build the output array in depth-first order. */
- svn_sort__array_insert(inherited_props, &i_props, 0);
+ SVN_ERR(svn_sort__array_insert2(inherited_props, &i_props, 0));
}
}
}
Modified: subversion/branches/multi-wc-format/subversion/libsvn_repos/hooks.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_repos/hooks.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_repos/hooks.c (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_repos/hooks.c Fri Jan 14 14:01:45 2022
@@ -668,7 +668,7 @@ svn_repos__hooks_pre_revprop_change(svn_
{
/* If the pre- hook doesn't exist at all, then default to
MASSIVE PARANOIA. Changing revision properties is a lossy
- operation; so unless the repository admininstrator has
+ operation; so unless the repository administrator has
*deliberately* created the pre-hook, disallow all changes. */
return
svn_error_create
Modified: subversion/branches/multi-wc-format/subversion/libsvn_repos/load-fs-vtable.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_repos/load-fs-vtable.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_repos/load-fs-vtable.c (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_repos/load-fs-vtable.c Fri Jan 14 14:01:45 2022
@@ -155,9 +155,11 @@ get_revision_mapping(apr_hash_t *rev_map
}
-/* Change revision property NAME to VALUE for REVISION in REPOS. If
- VALIDATE_PROPS is set, use functions which perform validation of
- the property value. Otherwise, bypass those checks. */
+/* Change revision property NAME to VALUE for REVISION in REPOS.
+ If NORMALIZE_PROPS is set, attempt to normalize properties before
+ changing them, if that is needed. If VALIDATE_PROPS is set, use
+ functions which perform validation of the property value.
+ Otherwise, bypass those checks. */
static svn_error_t *
change_rev_prop(svn_repos_t *repos,
svn_revnum_t revision,
@@ -179,17 +181,23 @@ change_rev_prop(svn_repos_t *repos,
NULL, value, pool);
}
-/* Change property NAME to VALUE for PATH in TXN_ROOT. If
- VALIDATE_PROPS is set, use functions which perform validation of
- the property value. Otherwise, bypass those checks. */
+/* Change property NAME to VALUE for PATH in TXN_ROOT.
+ If NORMALIZE_PROPS is set, attempt to normalize properties before
+ changing them, if that is needed. If VALIDATE_PROPS is set, use
+ functions which perform validation of the property value.
+ Otherwise, bypass those checks. */
static svn_error_t *
change_node_prop(svn_fs_root_t *txn_root,
const char *path,
const char *name,
const svn_string_t *value,
svn_boolean_t validate_props,
+ svn_boolean_t normalize_props,
apr_pool_t *pool)
{
+ if (normalize_props)
+ SVN_ERR(svn_repos__normalize_prop(&value, NULL, name, value, pool, pool));
+
if (validate_props)
return svn_repos_fs_change_node_prop(txn_root, path, name, value, pool);
else
@@ -213,9 +221,11 @@ prefix_mergeinfo_paths(svn_string_t **me
{
const char *merge_source = apr_hash_this_key(hi);
svn_rangelist_t *rangelist = apr_hash_this_val(hi);
- const char *path;
+ const char *path, *canonicalized_path;
- merge_source = svn_relpath_canonicalize(merge_source, pool);
+ SVN_ERR(svn_relpath_canonicalize_safe(&canonicalized_path, NULL,
+ merge_source, pool, pool));
+ merge_source = canonicalized_path;
/* The svn:mergeinfo property syntax demands a repos abspath */
path = svn_fspath__canonicalize(svn_relpath_join(parent_dir,
@@ -377,7 +387,10 @@ make_node_baton(struct node_baton **node
/* Then add info from the headers. */
if ((val = svn_hash_gets(headers, SVN_REPOS_DUMPFILE_NODE_PATH)))
{
- val = svn_relpath_canonicalize(val, pool);
+ const char *canonicalized_path;
+ SVN_ERR(svn_relpath_canonicalize_safe(&canonicalized_path, NULL,
+ val, pool, pool));
+ val = canonicalized_path;
if (rb->pb->parent_dir)
nb->path = svn_relpath_join(rb->pb->parent_dir, val, pool);
else
@@ -869,7 +882,8 @@ set_node_property(void *baton,
}
return change_node_prop(rb->txn_root, nb->path, name, value,
- pb->validate_props, nb->pool);
+ pb->validate_props, rb->pb->normalize_props,
+ nb->pool);
}
@@ -885,7 +899,8 @@ delete_node_property(void *baton,
return SVN_NO_ERROR;
return change_node_prop(rb->txn_root, nb->path, name, NULL,
- rb->pb->validate_props, nb->pool);
+ rb->pb->validate_props, rb->pb->normalize_props,
+ nb->pool);
}
@@ -909,7 +924,8 @@ remove_node_props(void *baton)
const char *key = apr_hash_this_key(hi);
SVN_ERR(change_node_prop(rb->txn_root, nb->path, key, NULL,
- rb->pb->validate_props, nb->pool));
+ rb->pb->validate_props, rb->pb->normalize_props,
+ nb->pool));
}
return SVN_NO_ERROR;
@@ -1202,7 +1218,12 @@ svn_repos_get_fs_build_parser6(const svn
struct parse_baton *pb = apr_pcalloc(pool, sizeof(*pb));
if (parent_dir)
- parent_dir = svn_relpath_canonicalize(parent_dir, pool);
+ {
+ const char *canonicalized_path;
+ SVN_ERR(svn_relpath_canonicalize_safe(&canonicalized_path, NULL,
+ parent_dir, pool, pool));
+ parent_dir = canonicalized_path;
+ }
SVN_ERR_ASSERT((SVN_IS_VALID_REVNUM(start_rev) &&
SVN_IS_VALID_REVNUM(end_rev))
@@ -1400,7 +1421,7 @@ revprops_close_revision(void *baton)
* both of these values are #SVN_INVALID_REVNUM (in which case no
* revision-based filtering occurs at all), or both are valid revisions
* (where START_REV is older than or equivalent to END_REV).
- *
+ *
* START_REV and END_REV act as filters, the lower and upper (inclusive)
* range values of revisions which will
* be loaded. Either both of these values are #SVN_INVALID_REVNUM (in
Modified: subversion/branches/multi-wc-format/subversion/libsvn_repos/load.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_repos/load.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_repos/load.c (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_repos/load.c Fri Jan 14 14:01:45 2022
@@ -355,24 +355,62 @@ parse_text_block(svn_stream_t *stream,
-/* Parse VERSIONSTRING and verify that we support the dumpfile format
- version number, setting *VERSION appropriately. */
+/* Parse VERSIONSTRING from STREAM and verify that we support the dumpfile
+ format version number, setting *VERSION appropriately. */
static svn_error_t *
parse_format_version(int *version,
- const char *versionstring)
+ svn_stream_t *stream,
+ apr_pool_t *scratch_pool)
{
static const int magic_len = sizeof(SVN_REPOS_DUMPFILE_MAGIC_HEADER) - 1;
- const char *p = strchr(versionstring, ':');
+ svn_stringbuf_t *linebuf;
+ const char *p;
int value;
+ /* No svn_stream_readline() here, because malformed streams may not have
+ the EOL at all, and currently svn_stream_readline() keeps loading the
+ whole thing into memory until it encounters an EOL or the stream ends.
+ This is particularly troublesome, because users may incorrectly attempt
+ to load arbitrary large files instead of proper dump files.
+
+ As a workaround, parse the first line with a length limit. While this
+ is not a complete solution, doing so handles the common case described
+ above. For a complete solution, svn_stream_readline() may need to grow
+ a `limit` argument that would allow us to safely use it everywhere within
+ this parser.
+ */
+ linebuf = svn_stringbuf_create_empty(scratch_pool);
+ while (1)
+ {
+ apr_size_t len;
+ char c;
+
+ len = 1;
+ SVN_ERR(svn_stream_read_full(stream, &c, &len));
+ if (len != 1)
+ return stream_ran_dry();
+
+ if (c == '\n')
+ break;
+
+ if (linebuf->len + 1 > 80)
+ return svn_error_createf(SVN_ERR_STREAM_MALFORMED_DATA, NULL,
+ _("Malformed dumpfile header '%s'"),
+ linebuf->data);
+
+ svn_stringbuf_appendbyte(linebuf, c);
+ }
+
+ p = strchr(linebuf->data, ':');
+
if (p == NULL
- || p != (versionstring + magic_len)
- || strncmp(versionstring,
+ || p != (linebuf->data + magic_len)
+ || strncmp(linebuf->data,
SVN_REPOS_DUMPFILE_MAGIC_HEADER,
magic_len))
return svn_error_createf(SVN_ERR_STREAM_MALFORMED_DATA, NULL,
_("Malformed dumpfile header '%s'"),
- versionstring);
+ linebuf->data);
SVN_ERR(svn_cstring_atoi(&value, p + 1));
@@ -542,14 +580,10 @@ svn_repos_parse_dumpstream3(svn_stream_t
parse_fns = complete_vtable(parse_fns, pool);
/* Start parsing process. */
- SVN_ERR(svn_stream_readline(stream, &linebuf, "\n", &eof, linepool));
- if (eof)
- return stream_ran_dry();
-
/* The first two lines of the stream are the dumpfile-format version
number, and a blank line. To preserve backward compatibility,
don't assume the existence of newer parser-vtable functions. */
- SVN_ERR(parse_format_version(&version, linebuf->data));
+ SVN_ERR(parse_format_version(&version, stream, linepool));
if (parse_fns->magic_header_record != NULL)
SVN_ERR(parse_fns->magic_header_record(version, parse_baton, pool));
Modified: subversion/branches/multi-wc-format/subversion/libsvn_repos/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_repos/log.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_repos/log.c (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_repos/log.c Fri Jan 14 14:01:45 2022
@@ -655,7 +655,7 @@ fs_mergeinfo_changed(svn_mergeinfo_catal
because that greatly influences the costs for log processing.
So, it is faster to iterate over the changes twice - in the worst
case b/c most times there is no m/i at all and we exit out early
- without any overhead.
+ without any overhead.
*/
while (change && (!any_mergeinfo || !any_copy))
{
@@ -999,7 +999,7 @@ get_combined_mergeinfo_changes(svn_merge
/* Issue #4022 'svn log -g interprets change in inherited mergeinfo due
to move as a merge': A copy where the source and destination inherit
mergeinfo from the same parent means the inherited mergeinfo of the
- source and destination will differ, but this diffrence is not
+ source and destination will differ, but this difference is not
indicative of a merge unless the mergeinfo on the inherited parent
has actually changed.
@@ -1053,7 +1053,7 @@ get_combined_mergeinfo_changes(svn_merge
continue;
}
- /* Compare, constrast, and combine the results. */
+ /* Compare, contrast, and combine the results. */
SVN_ERR(svn_mergeinfo_diff2(&deleted, &added, prev_mergeinfo,
mergeinfo, FALSE, result_pool, iterpool));
SVN_ERR(svn_mergeinfo_merge2(*deleted_mergeinfo, deleted,
@@ -1227,7 +1227,7 @@ typedef struct interesting_merge_baton_t
void *inner_baton;
} interesting_merge_baton_t;
-/* Implements svn_repos_path_change_receiver_t.
+/* Implements svn_repos_path_change_receiver_t.
* *BATON is a interesting_merge_baton_t.
*
* If BATON->REV a merged revision that is not already part of
@@ -1909,7 +1909,7 @@ store_search(svn_mergeinfo_t processed,
apr_pool_t *scratch_pool)
{
/* We add 1 to end so that we can use the mergeinfo API to handle
- singe revisions where HIST_START is equal to HIST_END. */
+ single revisions where HIST_START is equal to HIST_END. */
svn_revnum_t start = hist_start <= hist_end ? hist_start : hist_end;
svn_revnum_t end = hist_start <= hist_end ? hist_end + 1 : hist_start + 1;
svn_mergeinfo_t mergeinfo = svn_hash__make(scratch_pool);
Modified: subversion/branches/multi-wc-format/subversion/libsvn_repos/notify.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_repos/notify.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_repos/notify.c (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_repos/notify.c Fri Jan 14 14:01:45 2022
@@ -1,4 +1,4 @@
-/* notify.c --- notifcation system
+/* notify.c --- notification system
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
Modified: subversion/branches/multi-wc-format/subversion/libsvn_repos/replay.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_repos/replay.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_repos/replay.c (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_repos/replay.c Fri Jan 14 14:01:45 2022
@@ -126,9 +126,6 @@ struct copy_info
struct path_driver_cb_baton
{
- const svn_delta_editor_t *editor;
- void *edit_baton;
-
/* The root of the revision we're replaying. */
svn_fs_root_t *root;
@@ -454,14 +451,14 @@ fill_copyfrom(svn_fs_root_t **copyfrom_r
static svn_error_t *
path_driver_cb_func(void **dir_baton,
+ const svn_delta_editor_t *editor,
+ void *edit_baton,
void *parent_baton,
void *callback_baton,
const char *edit_path,
apr_pool_t *pool)
{
struct path_driver_cb_baton *cb = callback_baton;
- const svn_delta_editor_t *editor = cb->editor;
- void *edit_baton = cb->edit_baton;
svn_fs_root_t *root = cb->root;
svn_fs_path_change3_t *change;
svn_boolean_t do_add = FALSE, do_delete = FALSE;
@@ -894,7 +891,7 @@ get_relevant_changes(apr_hash_t **change
}
/* If the base_path doesn't match the top directory of this path
- we don't want anything to do with it...
+ we don't want anything to do with it...
...unless this was a change to one of the parent directories of
base_path. */
if ( svn_relpath_skip_ancestor(base_relpath, path)
@@ -957,8 +954,6 @@ svn_repos_replay2(svn_fs_root_t *root,
low_water_mark = 0;
/* Initialize our callback baton. */
- cb_baton.editor = editor;
- cb_baton.edit_baton = edit_baton;
cb_baton.root = root;
cb_baton.changed_paths = changed_paths;
cb_baton.authz_read_func = authz_read_func;
@@ -989,7 +984,7 @@ svn_repos_replay2(svn_fs_root_t *root,
}
/* Call the path-based editor driver. */
- return svn_delta_path_driver2(editor, edit_baton,
+ return svn_delta_path_driver3(editor, edit_baton,
paths, TRUE,
path_driver_cb_func, &cb_baton, pool);
#else
Modified: subversion/branches/multi-wc-format/subversion/libsvn_repos/reporter.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_repos/reporter.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_repos/reporter.c (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_repos/reporter.c Fri Jan 14 14:01:45 2022
@@ -47,7 +47,7 @@
the delta between the source and target revs.
Spill-buffer content format: we use a simple ad-hoc format to store the
- report operations. Each report operation is the concatention of
+ report operations. Each report operation is the concatenation of
the following ("+/-" indicates the single character '+' or '-';
<length> and <revnum> are written out as decimal strings):
Modified: subversion/branches/multi-wc-format/subversion/libsvn_repos/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_repos/repos.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_repos/repos.c (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_repos/repos.c Fri Jan 14 14:01:45 2022
@@ -1183,7 +1183,7 @@ svn_repos_create(svn_repos_t **repos_p,
if ((err = svn_fs_create2(&repos->fs, repos->db_path, fs_config,
result_pool, scratch_pool)))
{
- /* If there was an error making the filesytem, e.g. unknown/supported
+ /* If there was an error making the filesystem, e.g. unknown/supported
* filesystem type. Clean up after ourselves. Yes this is safe because
* create_repos_structure will fail if the path existed before we started
* so we can't accidentally remove a directory that previously existed.
@@ -1452,7 +1452,7 @@ svn_repos_upgrade2(const char *path,
if (notify_func)
{
/* We notify *twice* here, because there are two different logistical
- actions occuring. */
+ actions occurring. */
svn_repos_notify_t *notify = svn_repos_notify_create(
svn_repos_notify_mutex_acquired, subpool);
notify_func(notify_baton, notify, subpool);
@@ -1702,7 +1702,7 @@ svn_repos_recover4(const char *path,
if (notify_func)
{
/* We notify *twice* here, because there are two different logistical
- actions occuring. */
+ actions occurring. */
svn_repos_notify_t *notify = svn_repos_notify_create(
svn_repos_notify_mutex_acquired, subpool);
notify_func(notify_baton, notify, subpool);
Modified: subversion/branches/multi-wc-format/subversion/libsvn_repos/repos.h
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_repos/repos.h?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_repos/repos.h (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_repos/repos.h Fri Jan 14 14:01:45 2022
@@ -128,7 +128,7 @@ struct svn_repos_t
/* The format number of this repository. */
int format;
- /* The path to the repository's hooks enviroment file. If NULL, hooks run
+ /* The path to the repository's hooks environment file. If NULL, hooks run
* in an empty environment. */
const char *hooks_env_path;
Modified: subversion/branches/multi-wc-format/subversion/libsvn_subr/cache-memcache.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_subr/cache-memcache.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_subr/cache-memcache.c (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_subr/cache-memcache.c Fri Jan 14 14:01:45 2022
@@ -234,7 +234,7 @@ memcache_has_key(svn_boolean_t *found,
return SVN_NO_ERROR;
}
-/* Core functionality of our setter functions: store LENGH bytes of DATA
+/* Core functionality of our setter functions: store LENGTH bytes of DATA
* to be identified by KEY in the memcached given by CACHE_VOID. Use POOL
* for temporary allocations.
*/
Modified: subversion/branches/multi-wc-format/subversion/libsvn_subr/cmdline.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_subr/cmdline.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_subr/cmdline.c (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_subr/cmdline.c Fri Jan 14 14:01:45 2022
@@ -39,8 +39,15 @@
#include <apr.h> /* for STDIN_FILENO */
#include <apr_errno.h> /* for apr_strerror */
+#include <apr_version.h>
+#if APR_VERSION_AT_LEAST(1,5,0)
+#include <apr_escape.h>
+#else
+#include "private/svn_dep_compat.h"
+#endif
#include <apr_general.h> /* for apr_initialize/apr_terminate */
#include <apr_strings.h> /* for apr_snprintf */
+#include <apr_env.h> /* for apr_env_get */
#include <apr_pools.h>
#include <apr_signal.h>
@@ -73,7 +80,7 @@
#if defined(WIN32) && defined(_MSC_VER) && (_MSC_VER < 1400)
/* Before Visual Studio 2005, the C runtime didn't handle encodings for the
- for the stdio output handling. */
+ stdio output handling. */
#define CMDLINE_USE_CUSTOM_ENCODING
/* The stdin encoding. If null, it's the same as the native encoding. */
@@ -1233,39 +1240,85 @@ svn_cmdline__be_interactive(svn_boolean_
}
-/* Helper for the next two functions. Set *EDITOR to some path to an
- editor binary. Sources to search include: the EDITOR_CMD argument
- (if not NULL), $SVN_EDITOR, the runtime CONFIG variable (if CONFIG
+/* Helper for the edit_externally functions. Set *EDITOR to some path to an
+ editor binary, in native C string on Unix/Linux platforms and in UTF-8
+ string on Windows platform. Sources to search include: the EDITOR_CMD
+ argument (if not NULL), $SVN_EDITOR, the runtime CONFIG variable (if CONFIG
is not NULL), $VISUAL, $EDITOR. Return
SVN_ERR_CL_NO_EXTERNAL_EDITOR if no binary can be found. */
static svn_error_t *
find_editor_binary(const char **editor,
const char *editor_cmd,
- apr_hash_t *config)
+ apr_hash_t *config,
+ apr_pool_t *pool)
{
const char *e;
+ const char *e_cfg;
struct svn_config_t *cfg;
+ apr_status_t status;
/* Use the editor specified on the command line via --editor-cmd, if any. */
+#ifdef WIN32
+ /* On Windows, editor_cmd is transcoded to the system active code page
+ because we use main() as a entry point without APR's (or our own) wrapper
+ in command line tools. */
+ if (editor_cmd)
+ {
+ SVN_ERR(svn_utf_cstring_to_utf8(&e, editor_cmd, pool));
+ }
+ else
+ {
+ e = NULL;
+ }
+#else
e = editor_cmd;
+#endif
/* Otherwise look for the Subversion-specific environment variable. */
if (! e)
- e = getenv("SVN_EDITOR");
+ {
+ status = apr_env_get((char **)&e, "SVN_EDITOR", pool);
+ if (status || ! *e)
+ {
+ e = NULL;
+ }
+ }
/* If not found then fall back on the config file. */
if (! e)
{
cfg = config ? svn_hash_gets(config, SVN_CONFIG_CATEGORY_CONFIG) : NULL;
- svn_config_get(cfg, &e, SVN_CONFIG_SECTION_HELPERS,
+ svn_config_get(cfg, &e_cfg, SVN_CONFIG_SECTION_HELPERS,
SVN_CONFIG_OPTION_EDITOR_CMD, NULL);
+#ifdef WIN32
+ if (e_cfg)
+ {
+ /* On Windows, we assume that config values are set in system active
+ code page, so we need transcode it here. */
+ SVN_ERR(svn_utf_cstring_to_utf8(&e, e_cfg, pool));
+ }
+#else
+ e = e_cfg;
+#endif
}
/* If not found yet then try general purpose environment variables. */
if (! e)
- e = getenv("VISUAL");
+ {
+ status = apr_env_get((char**)&e, "VISUAL", pool);
+ if (status || ! *e)
+ {
+ e = NULL;
+ }
+ }
if (! e)
- e = getenv("EDITOR");
+ {
+ status = apr_env_get((char**)&e, "EDITOR", pool);
+ if (status || ! *e)
+ {
+ e = NULL;
+ }
+ }
#ifdef SVN_CLIENT_EDITOR
/* If still not found then fall back on the hard-coded default. */
@@ -1299,6 +1352,98 @@ find_editor_binary(const char **editor,
return SVN_NO_ERROR;
}
+/* Wrapper around apr_pescape_shell() which also escapes whitespace. */
+static const char *
+escape_path(apr_pool_t *pool, const char *orig_path)
+{
+ apr_size_t len, esc_len;
+ apr_status_t status;
+
+ len = strlen(orig_path);
+ esc_len = 0;
+
+ status = apr_escape_shell(NULL, orig_path, len, &esc_len);
+
+ if (status == APR_NOTFOUND)
+ {
+ /* No special characters found by APR, so just surround it in double
+ quotes in case there is whitespace, which APR (as of 1.6.5) doesn't
+ consider special. */
+ return apr_psprintf(pool, "\"%s\"", orig_path);
+ }
+ else
+ {
+#ifdef WIN32
+ const char *p;
+ /* Following the advice from
+ https://docs.microsoft.com/en-us/archive/blogs/twistylittlepassagesallalike/everyone-quotes-command-line-arguments-the-wrong-way
+ 1. Surround argument with double-quotes
+ 2. Escape backslashes, if they're followed by a double-quote, and double-quotes
+ 3. Escape any metacharacter, including double-quotes, with ^ */
+
+ /* Use APR's buffer size as an approximation for how large the escaped
+ string should be, plus 4 bytes for the leading/trailing ^" */
+ svn_stringbuf_t *buf = svn_stringbuf_create_ensure(esc_len + 4, pool);
+ svn_stringbuf_appendcstr(buf, "^\"");
+ for (p = orig_path; *p; p++)
+ {
+ int nr_backslash = 0;
+ while (*p && *p == '\\')
+ {
+ nr_backslash++;
+ p++;
+ }
+
+ if (!*p)
+ /* We've reached the end of the argument, so we need 2n backslash
+ characters. That will be interpreted as n backslashes and the
+ final double-quote character will be interpreted as the final
+ string delimiter. */
+ svn_stringbuf_appendfill(buf, '\\', nr_backslash * 2);
+ else if (*p == '"')
+ {
+ /* Double-quote as part of the argument means we need to double
+ any preceding backslashes and then add one to escape the
+ double-quote. */
+ svn_stringbuf_appendfill(buf, '\\', nr_backslash * 2 + 1);
+ svn_stringbuf_appendbyte(buf, '^');
+ svn_stringbuf_appendbyte(buf, *p);
+ }
+ else
+ {
+ /* Since there's no double-quote, we just insert any backslashes
+ literally. No escaping needed. */
+ svn_stringbuf_appendfill(buf, '\\', nr_backslash);
+ if (strchr("()%!^<>&|", *p))
+ svn_stringbuf_appendbyte(buf, '^');
+ svn_stringbuf_appendbyte(buf, *p);
+ }
+ }
+ svn_stringbuf_appendcstr(buf, "^\"");
+ return buf->data;
+#else
+ char *path, *p, *esc_path;
+
+ /* Account for whitespace, since APR doesn't */
+ for (p = (char *)orig_path; *p; p++)
+ if (strchr(" \t\n\r", *p))
+ esc_len++;
+
+ path = apr_pcalloc(pool, esc_len);
+ apr_escape_shell(path, orig_path, len, NULL);
+
+ p = esc_path = apr_pcalloc(pool, len + esc_len + 1);
+ while (*path)
+ {
+ if (strchr(" \t\n\r", *path))
+ *p++ = '\\';
+ *p++ = *path++;
+ }
+
+ return esc_path;
+#endif
+ }
+}
svn_error_t *
svn_cmdline__edit_file_externally(const char *path,
@@ -1307,13 +1452,17 @@ svn_cmdline__edit_file_externally(const
apr_pool_t *pool)
{
const char *editor, *cmd, *base_dir, *file_name, *base_dir_apr;
+ const char *file_name_local;
+#ifdef WIN32
+ const WCHAR *wcmd;
+#endif
char *old_cwd;
int sys_err;
apr_status_t apr_err;
svn_dirent_split(&base_dir, &file_name, path, pool);
- SVN_ERR(find_editor_binary(&editor, editor_cmd, config));
+ SVN_ERR(find_editor_binary(&editor, editor_cmd, config, pool));
apr_err = apr_filepath_get(&old_cwd, APR_FILEPATH_NATIVE, pool);
if (apr_err)
@@ -1330,8 +1479,18 @@ svn_cmdline__edit_file_externally(const
return svn_error_wrap_apr
(apr_err, _("Can't change working directory to '%s'"), base_dir);
- cmd = apr_psprintf(pool, "%s %s", editor, file_name);
+ SVN_ERR(svn_path_cstring_from_utf8(&file_name_local,
+ escape_path(pool, file_name), pool));
+ /* editor is explicitly documented as being interpreted by the user's shell,
+ and as such should already be quoted/escaped as needed. */
+#ifndef WIN32
+ cmd = apr_psprintf(pool, "%s %s", editor, file_name_local);
sys_err = system(cmd);
+#else
+ cmd = apr_psprintf(pool, "\"%s %s\"", editor, file_name_local);
+ SVN_ERR(svn_utf__win32_utf8_to_utf16(&wcmd, cmd, NULL, pool));
+ sys_err = _wsystem(wcmd);
+#endif
apr_err = apr_filepath_set(old_cwd, pool);
if (apr_err)
@@ -1340,10 +1499,16 @@ svn_cmdline__edit_file_externally(const
stderr, TRUE /* fatal */, "svn: ");
if (sys_err)
- /* Extracting any meaning from sys_err is platform specific, so just
- use the raw value. */
- return svn_error_createf(SVN_ERR_EXTERNAL_PROGRAM, NULL,
- _("system('%s') returned %d"), cmd, sys_err);
+ {
+ const char *cmd_utf8;
+
+ /* Extracting any meaning from sys_err is platform specific, so just
+ use the raw value. */
+ SVN_ERR(svn_path_cstring_to_utf8(&cmd_utf8, cmd, pool));
+ return svn_error_createf(SVN_ERR_EXTERNAL_PROGRAM, NULL,
+ _("system('%s') returned %d"),
+ cmd_utf8, sys_err);
+ }
return SVN_NO_ERROR;
}
@@ -1363,6 +1528,9 @@ svn_cmdline__edit_string_externally(svn_
{
const char *editor;
const char *cmd;
+#ifdef WIN32
+ const WCHAR *wcmd;
+#endif
apr_file_t *tmp_file;
const char *tmpfile_name;
const char *tmpfile_native;
@@ -1376,7 +1544,7 @@ svn_cmdline__edit_string_externally(svn_
int sys_err;
svn_boolean_t remove_file = TRUE;
- SVN_ERR(find_editor_binary(&editor, editor_cmd, config));
+ SVN_ERR(find_editor_binary(&editor, editor_cmd, config, pool));
/* Convert file contents from UTF-8/LF if desired. */
if (as_text)
@@ -1486,10 +1654,18 @@ svn_cmdline__edit_string_externally(svn_
goto cleanup;
/* Prepare the editor command line. */
- err = svn_utf_cstring_from_utf8(&tmpfile_native, tmpfile_name, pool);
+ err = svn_path_cstring_from_utf8(&tmpfile_native,
+ escape_path(pool, tmpfile_name), pool);
if (err)
goto cleanup;
+
+ /* editor is explicitly documented as being interpreted by the user's shell,
+ and as such should already be quoted/escaped as needed. */
+#ifndef WIN32
cmd = apr_psprintf(pool, "%s %s", editor, tmpfile_native);
+#else
+ cmd = apr_psprintf(pool, "\"%s %s\"", editor, tmpfile_native);
+#endif
/* If the caller wants us to leave the file around, return the path
of the file we'll use, and make a note not to destroy it. */
@@ -1500,13 +1676,22 @@ svn_cmdline__edit_string_externally(svn_
}
/* Now, run the editor command line. */
+#ifndef WIN32
sys_err = system(cmd);
+#else
+ SVN_ERR(svn_utf__win32_utf8_to_utf16(&wcmd, cmd, NULL, pool));
+ sys_err = _wsystem(wcmd);
+#endif
if (sys_err != 0)
{
+ const char *cmd_utf8;
+
/* Extracting any meaning from sys_err is platform specific, so just
use the raw value. */
+ SVN_ERR(svn_path_cstring_to_utf8(&cmd_utf8, cmd, pool));
err = svn_error_createf(SVN_ERR_EXTERNAL_PROGRAM, NULL,
- _("system('%s') returned %d"), cmd, sys_err);
+ _("system('%s') returned %d"),
+ cmd_utf8, sys_err);
goto cleanup;
}
Modified: subversion/branches/multi-wc-format/subversion/libsvn_subr/config_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_subr/config_file.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_subr/config_file.c (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_subr/config_file.c Fri Jan 14 14:01:45 2022
@@ -550,7 +550,7 @@ parse_option(int *pch, parse_context_t *
}
-/* Read chars until enounter ']', then skip everything to the end of
+/* Read chars until encounter ']', then skip everything to the end of
* the line. Set *PCH to the character that ended the line (either
* newline or EOF), and set CTX->section to the string of characters
* seen before ']'.
@@ -1045,7 +1045,7 @@ svn_config_ensure(const char *config_dir
"The syntax of the configuration files is a subset of the one used by" NL
"Python's ConfigParser module; see" NL
"" NL
- " http://www.python.org/doc/current/lib/module-ConfigParser.html" NL
+ " https://docs.python.org/3/library/configparser.html" NL
"" NL
"Configuration data in the Windows registry" NL
"==========================================" NL
@@ -1192,16 +1192,13 @@ svn_config_ensure(const char *config_dir
"### may be cached to disk." NL
"### username Specifies the default username." NL
"###" NL
- "### Set store-passwords to 'no' to avoid storing passwords on disk" NL
- "### in any way, including in password stores. It defaults to" NL
+ "### Set store-passwords to 'no' to avoid storing new passwords on" NL
+ "### disk in any way, including in password stores. It defaults to" NL
"### 'yes', but Subversion will never save your password to disk in" NL
"### plaintext unless explicitly configured to do so." NL
- "### Note that this option only prevents saving of *new* passwords;" NL
- "### it doesn't invalidate existing passwords. (To do that, remove" NL
- "### the cache files by hand as described in the Subversion book.)" NL
"###" NL
#ifndef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE
- "### Set store-plaintext-passwords to 'no' to avoid storing" NL
+ "### Set store-plaintext-passwords to 'no' to avoid storing new" NL
"### passwords in unencrypted form in the auth/ area of your config" NL
"### directory. Set it to 'yes' to allow Subversion to store" NL
"### unencrypted passwords in the auth/ area. The default is" NL
@@ -1211,22 +1208,15 @@ svn_config_ensure(const char *config_dir
"### 'store-auth-creds' is set to 'no'." NL
"###" NL
#endif
- "### Set store-ssl-client-cert-pp to 'no' to avoid storing ssl" NL
+ "### Set store-ssl-client-cert-pp to 'no' to avoid storing new ssl" NL
"### client certificate passphrases in the auth/ area of your" NL
"### config directory. It defaults to 'yes', but Subversion will" NL
"### never save your passphrase to disk in plaintext unless" NL
"### explicitly configured to do so." NL
"###" NL
- "### Note store-ssl-client-cert-pp only prevents the saving of *new*"NL
- "### passphrases; it doesn't invalidate existing passphrases. To do"NL
- "### that, remove the cache files by hand as described in the" NL
- "### Subversion book at http://svnbook.red-bean.com/nightly/en/\\" NL
- "### svn.serverconfig.netmodel.html\\" NL
- "### #svn.serverconfig.netmodel.credcache" NL
- "###" NL
#ifndef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE
"### Set store-ssl-client-cert-pp-plaintext to 'no' to avoid storing"NL
- "### passphrases in unencrypted form in the auth/ area of your" NL
+ "### new passphrases in unencrypted form in the auth/ area of your" NL
"### config directory. Set it to 'yes' to allow Subversion to" NL
"### store unencrypted passphrases in the auth/ area. The default" NL
"### is 'ask', which means that Subversion will prompt before" NL
@@ -1235,12 +1225,19 @@ svn_config_ensure(const char *config_dir
"### 'store-ssl-client-cert-pp' is set to 'no'." NL
"###" NL
#endif
- "### Set store-auth-creds to 'no' to avoid storing any Subversion" NL
+ "### Set store-auth-creds to 'no' to avoid storing any new Subversion"
+ NL
"### credentials in the auth/ area of your config directory." NL
"### Note that this includes SSL server certificates." NL
- "### It defaults to 'yes'. Note that this option only prevents" NL
- "### saving of *new* credentials; it doesn't invalidate existing" NL
- "### caches. (To do that, remove the cache files by hand.)" NL
+ "### It defaults to 'yes'." NL
+ "###" NL
+ "### Note that setting a 'store-*' option to 'no' only prevents" NL
+ "### saving of *new* passwords, passphrases or other credentials." NL
+ "### It does not remove or invalidate existing stored credentials." NL
+ "### To do that, see the 'svn auth --remove' command, or remove the" NL
+ "### cache files by hand as described in the Subversion book at" NL
+ "### http://svnbook.red-bean.com/nightly/en/svn.serverconfig.netmodel.html#svn.tour.initial.authn-cache-purge"
+ NL
"###" NL
"### HTTP timeouts, if given, are specified in seconds. A timeout" NL
"### of 0, i.e. zero, causes a builtin default to be used." NL
@@ -1445,11 +1442,12 @@ svn_config_ensure(const char *config_dir
"### is defined. The command (or environment variable) may contain" NL
"### arguments, using standard shell quoting for arguments with" NL
"### spaces. The command will be invoked as:" NL
- "### <command> <hostname> svnserve -t" NL
- "### (If the URL includes a username, then the hostname will be" NL
- "### passed to the tunnel agent as <user>@<hostname>.) If the" NL
- "### built-in ssh scheme were not predefined, it could be defined" NL
- "### as:" NL
+ "### <command> <hostinfo> svnserve -t" NL
+ "### where <hostinfo> is the hostname part of the URL. If the URL" NL
+ "### specified a username and/or a port, those are included in the" NL
+ "### <hostinfo> argument in the usual way: <user>@<hostname>:<port>."NL
+ "### If the built-in ssh scheme were not predefined, it could be" NL
+ "### defined as:" NL
"# ssh = $SVN_SSH ssh -q --" NL
"### If you wanted to define a new 'rsh' scheme, to be used with" NL
"### 'svn+rsh:' URLs, you could do so as follows:" NL
Modified: subversion/branches/multi-wc-format/subversion/libsvn_subr/date.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_subr/date.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_subr/date.c (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_subr/date.c Fri Jan 14 14:01:45 2022
@@ -37,7 +37,7 @@ enum rule_action {
if the next template character matches the current
value character, continue processing as normal.
Otherwise, attempt to complete matching starting
- immediately after the first subsequent occurrance of
+ immediately after the first subsequent occurrence of
']' in the template. */
SKIP, /* Ignore this template character */
ACCEPT /* Accept the value */
Modified: subversion/branches/multi-wc-format/subversion/libsvn_subr/dirent_uri.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_subr/dirent_uri.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_subr/dirent_uri.c (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_subr/dirent_uri.c Fri Jan 14 14:01:45 2022
@@ -37,6 +37,7 @@
#include "svn_ctype.h"
#include "dirent_uri.h"
+#include "private/svn_dirent_uri_private.h"
#include "private/svn_fspath.h"
#include "private/svn_cert.h"
@@ -292,8 +293,9 @@ uri_previous_segment(const char *uri,
/* Return the canonicalized version of PATH, of type TYPE, allocated in
* POOL.
*/
-static const char *
-canonicalize(path_type_t type, const char *path, apr_pool_t *pool)
+static svn_error_t *
+canonicalize(const char **canonical_path,
+ path_type_t type, const char *path, apr_pool_t *pool)
{
char *canon, *dst;
const char *src;
@@ -307,8 +309,12 @@ canonicalize(path_type_t type, const cha
depends on path not being zero-length. */
if (SVN_PATH_IS_EMPTY(path))
{
- assert(type != type_uri);
- return "";
+ *canonical_path = "";
+ if (type == type_uri)
+ return svn_error_create(SVN_ERR_CANONICALIZATION_FAILED, NULL,
+ _("An empty URI can not be canonicalized"));
+ else
+ return SVN_NO_ERROR;
}
dst = canon = apr_pcalloc(pool, strlen(path) + 1);
@@ -319,7 +325,12 @@ canonicalize(path_type_t type, const cha
src = path;
if (type == type_uri)
{
- assert(*src != '/');
+ if (*src == '/')
+ {
+ *canonical_path = src;
+ return svn_error_create(SVN_ERR_CANONICALIZATION_FAILED, NULL,
+ _("A URI can not start with '/'"));
+ }
while (*src && (*src != '/') && (*src != ':'))
src++;
@@ -546,7 +557,10 @@ canonicalize(path_type_t type, const cha
if ((type == type_dirent) && canon[0] == '/' && canon[1] == '/')
{
if (canon_segments < 2)
- return canon + 1;
+ {
+ *canonical_path = canon + 1;
+ return SVN_NO_ERROR;
+ }
else
{
/* Now we're sure this is a valid UNC path, convert the server name
@@ -654,7 +668,8 @@ canonicalize(path_type_t type, const cha
*dst = '\0';
}
- return canon;
+ *canonical_path = canon;
+ return SVN_NO_ERROR;
}
/* Return the string length of the longest common ancestor of PATH1 and PATH2.
@@ -883,6 +898,20 @@ svn_dirent_internal_style(const char *di
return svn_dirent_canonicalize(internal_style(dirent, pool), pool);
}
+svn_error_t *
+svn_dirent_internal_style_safe(const char **internal_style_dirent,
+ const char **non_canonical_result,
+ const char *dirent,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ return svn_error_trace(
+ svn_dirent_canonicalize_safe(internal_style_dirent,
+ non_canonical_result,
+ internal_style(dirent, scratch_pool),
+ result_pool, scratch_pool));
+}
+
const char *
svn_dirent_local_style(const char *dirent, apr_pool_t *pool)
{
@@ -906,14 +935,18 @@ svn_dirent_local_style(const char *diren
return dirent;
}
-const char *
-svn_relpath__internal_style(const char *relpath,
- apr_pool_t *pool)
-{
- return svn_relpath_canonicalize(internal_style(relpath, pool), pool);
+svn_error_t *
+svn_relpath__make_internal(const char **internal_style_relpath,
+ const char *relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ return svn_error_trace(
+ svn_relpath_canonicalize_safe(internal_style_relpath, NULL,
+ internal_style(relpath, scratch_pool),
+ result_pool, scratch_pool));
}
-
/* We decided against using apr_filepath_root here because of the negative
performance impact (creating a pool and converting strings ). */
svn_boolean_t
@@ -1643,19 +1676,84 @@ svn_dirent_get_absolute(const char **pab
const char *
svn_uri_canonicalize(const char *uri, apr_pool_t *pool)
{
- return canonicalize(type_uri, uri, pool);
+ const char *result;
+ svn_error_t *const err = canonicalize(&result, type_uri, uri, pool);
+ if (err)
+ {
+ svn_error_clear(err);
+ SVN_ERR_ASSERT_NO_RETURN(!"URI canonicalization failed");
+ }
+ return result;
+}
+
+svn_error_t *
+svn_uri_canonicalize_safe(const char **canonical_uri,
+ const char **non_canonical_result,
+ const char *uri,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ const char *result = NULL;
+ SVN_ERR(canonicalize(&result, type_uri, uri, result_pool));
+ if (!svn_uri_is_canonical(result, scratch_pool))
+ {
+ if (non_canonical_result)
+ *non_canonical_result = result;
+
+ return svn_error_createf(
+ SVN_ERR_CANONICALIZATION_FAILED, NULL,
+ _("Could not canonicalize URI '%s'"
+ " (the result '%s' is not canonical)"),
+ uri, result);
+ }
+ *canonical_uri = result;
+ return SVN_NO_ERROR;
}
const char *
svn_relpath_canonicalize(const char *relpath, apr_pool_t *pool)
{
- return canonicalize(type_relpath, relpath, pool);
+ const char *result;
+ svn_error_t *const err = canonicalize(&result, type_relpath, relpath, pool);
+ if (err)
+ {
+ svn_error_clear(err);
+ SVN_ERR_ASSERT_NO_RETURN(!"relpath canonicalization failed");
+ }
+ return result;
}
-const char *
-svn_dirent_canonicalize(const char *dirent, apr_pool_t *pool)
+svn_error_t *
+svn_relpath_canonicalize_safe(const char **canonical_relpath,
+ const char **non_canonical_result,
+ const char *relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ const char *result = NULL;
+ SVN_ERR(canonicalize(&result, type_relpath, relpath, result_pool));
+ if (!svn_relpath_is_canonical(result))
+ {
+ if (non_canonical_result)
+ *non_canonical_result = result;
+
+ return svn_error_createf(
+ SVN_ERR_CANONICALIZATION_FAILED, NULL,
+ _("Could not canonicalize relpath '%s'"
+ " (the result '%s' is not canonical)"),
+ relpath, result);
+ }
+
+ SVN_UNUSED(scratch_pool);
+ *canonical_relpath = result;
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+canonicalize_dirent(const char **result, const char *dirent, apr_pool_t *pool)
{
- const char *dst = canonicalize(type_dirent, dirent, pool);
+ const char *dst;
+ SVN_ERR(canonicalize(&dst, type_dirent, dirent, pool));
#ifdef SVN_USE_DOS_PATHS
/* Handle a specific case on Windows where path == "X:/". Here we have to
@@ -1671,11 +1769,50 @@ svn_dirent_canonicalize(const char *dire
dst_slash[2] = '/';
dst_slash[3] = '\0';
- return dst_slash;
+ *result = dst_slash;
+ return SVN_NO_ERROR;
}
#endif /* SVN_USE_DOS_PATHS */
- return dst;
+ *result = dst;
+ return SVN_NO_ERROR;
+}
+
+const char *
+svn_dirent_canonicalize(const char *dirent, apr_pool_t *pool)
+{
+ const char *result;
+ svn_error_t *const err = canonicalize_dirent(&result, dirent, pool);
+ if (err)
+ {
+ svn_error_clear(err);
+ SVN_ERR_ASSERT_NO_RETURN(!"dirent canonicalization failed");
+ }
+ return result;
+}
+
+svn_error_t *
+svn_dirent_canonicalize_safe(const char **canonical_dirent,
+ const char **non_canonical_result,
+ const char *dirent,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ const char *result = NULL;
+ SVN_ERR(canonicalize_dirent(&result, dirent, result_pool));
+ if (!svn_dirent_is_canonical(result, scratch_pool))
+ {
+ if (non_canonical_result)
+ *non_canonical_result = result;
+
+ return svn_error_createf(
+ SVN_ERR_CANONICALIZATION_FAILED, NULL,
+ _("Could not canonicalize dirent '%s'"
+ " (the result '%s' is not canonical)"),
+ dirent, result);
+ }
+ *canonical_dirent = result;
+ return SVN_NO_ERROR;
}
svn_boolean_t
Modified: subversion/branches/multi-wc-format/subversion/libsvn_subr/error.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_subr/error.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_subr/error.c (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_subr/error.c Fri Jan 14 14:01:45 2022
@@ -146,6 +146,7 @@ svn_error__locate(const char *file, long
/* Cleanup function for errors. svn_error_clear () removes this so
errors that are properly handled *don't* hit this code. */
+#ifdef SVN_DEBUG
static apr_status_t err_abort(void *data)
{
svn_error_t *err = data; /* For easy viewing in a debugger */
@@ -155,6 +156,7 @@ static apr_status_t err_abort(void *data
abort();
return APR_SUCCESS;
}
+#endif
static svn_error_t *
Modified: subversion/branches/multi-wc-format/subversion/libsvn_subr/gpg_agent.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_subr/gpg_agent.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/libsvn_subr/gpg_agent.c (original)
+++ subversion/branches/multi-wc-format/subversion/libsvn_subr/gpg_agent.c Fri Jan 14 14:01:45 2022
@@ -108,7 +108,7 @@ escape_blanks(char *str)
#define is_hex(c) (((c) >= '0' && (c) <= '9') || ((c) >= 'A' && (c) <= 'F'))
#define hex_to_int(c) ((c) < '9' ? (c) - '0' : (c) - 'A' + 10)
-
+
/* Modify STR in-place. '%', CR and LF are always percent escaped,
other characters may be percent escaped, always using uppercase
hex, see https://www.gnupg.org/documentation/manuals/assuan.pdf */
@@ -680,9 +680,9 @@ simple_gpg_agent_next_creds(void **crede
/* TODO: This attempt limit hard codes it at 3 attempts (or 2 retries)
* which matches svn command line client's retry_limit as set in
* svn_cmdline_create_auth_baton(). It would be nice to have that
- * limit reflected here but that violates the boundry between the
+ * limit reflected here but that violates the boundary between the
* prompt provider and the cache provider. gpg-agent is acting as
- * both here due to the peculiarties of their design so we'll have to
+ * both here due to the peculiarities of their design so we'll have to
* live with this for now. Note that when these failures get exceeded
* it'll eventually fall back on the retry limits of whatever prompt
* provider is in effect, so this effectively doubles the limit. */