Author: jpeck
Date: Wed Jul 8 20:32:27 2026
New Revision: 1936012
Log:
Canonicalize SVNMasterURI at config-parse time, avoid re-encoding it
The SVNMasterURI directive value was stored verbatim, so a trailing slash
leaked "//" into every proxied filename and rewritten Destination header.
mirror.c URI-encoded the raw value before use, double-escaping any
'%' in a master path that itself needs encoding.
Store the value canonicalized (no trailing slash, normalized escapes)
and establish the invariant that consumers use it as-is: the Destination
rewrite and the Location response-header match take it verbatim, and the
proxy filename now encodes only the (decoded) URI segment appended to
it.
This is a user-visible config improvement: SVNMasterURI values with a
trailing slash now work. The mirror test harness deliberately
configures one to keep this canonicalized.
* subversion/mod_dav_svn/mod_dav_svn.c
(SVNMasterURI_cmd): Canonicalize the value before storing it.
* subversion/mod_dav_svn/mirror.c
(proxy_request_fixup): Build r->filename from the raw master URI plus
the encoded segment.
(proxy_request_fixup_destination): Don't re-encode the master URI in
the rewritten Destination header.
(dav_svn__location_header_filter): Match the stored master URI
against the Location header without re-encoding it.
Modified:
subversion/branches/proxy-move-copy-fix/subversion/mod_dav_svn/mirror.c
subversion/branches/proxy-move-copy-fix/subversion/mod_dav_svn/mod_dav_svn.c
Modified:
subversion/branches/proxy-move-copy-fix/subversion/mod_dav_svn/mirror.c
==============================================================================
--- subversion/branches/proxy-move-copy-fix/subversion/mod_dav_svn/mirror.c
Wed Jul 8 20:23:32 2026 (r1936011)
+++ subversion/branches/proxy-move-copy-fix/subversion/mod_dav_svn/mirror.c
Wed Jul 8 20:32:27 2026 (r1936012)
@@ -76,8 +76,7 @@ proxy_request_fixup_destination(request_
}
apr_table_set(r->headers_in, "Destination",
- apr_pstrcat(r->pool, svn_path_uri_encode(master_uri,
r->pool),
- "/", rel, SVN_VA_NULL));
+ apr_pstrcat(r->pool, master_uri, "/", rel, SVN_VA_NULL));
}
@@ -86,7 +85,8 @@ proxy_request_fixup_destination(request_
specified in the SVNMasterURI Apache configuration value.
URI_SEGMENT is the URI bits relative to the repository root (but if
non-empty, *does* have a leading slash delimiter).
- MASTER_URI and URI_SEGMENT are not URI-encoded. */
+ MASTER_URI is canonical and URI-encoded (stored by SVNMasterURI_cmd);
+ URI_SEGMENT is not URI-encoded. */
static int proxy_request_fixup(request_rec *r,
const char *master_uri,
const char *uri_segment)
@@ -101,11 +101,10 @@ static int proxy_request_fixup(request_r
r->proxyreq = PROXYREQ_REVERSE;
r->uri = r->unparsed_uri;
- r->filename = (char *) svn_path_uri_encode(apr_pstrcat(r->pool, "proxy:",
- master_uri,
- uri_segment,
- SVN_VA_NULL),
- r->pool);
+ r->filename = (char *) apr_pstrcat(r->pool, "proxy:", master_uri,
+ svn_path_uri_encode(uri_segment,
+ r->pool),
+ SVN_VA_NULL);
r->handler = "proxy-server";
proxy_request_fixup_destination(r, master_uri);
@@ -300,7 +299,6 @@ apr_status_t dav_svn__location_header_fi
/* Don't filter if we're in a subrequest or we aren't setup to
proxy anything. */
master_uri = dav_svn__get_master_uri(r);
- master_uri = svn_path_uri_encode(master_uri, r->pool);
if (r->main || !master_uri) {
ap_remove_output_filter(f);
return ap_pass_brigade(f->next, bb);
Modified:
subversion/branches/proxy-move-copy-fix/subversion/mod_dav_svn/mod_dav_svn.c
==============================================================================
---
subversion/branches/proxy-move-copy-fix/subversion/mod_dav_svn/mod_dav_svn.c
Wed Jul 8 20:23:32 2026 (r1936011)
+++
subversion/branches/proxy-move-copy-fix/subversion/mod_dav_svn/mod_dav_svn.c
Wed Jul 8 20:32:27 2026 (r1936012)
@@ -339,7 +339,10 @@ SVNMasterURI_cmd(cmd_parms *cmd, void *c
if (! *uri_base_name)
return "SVNMasterURI value must not be a server root";
- conf->master_uri = apr_pstrdup(cmd->pool, arg1);
+ /* Store the URI canonicalized: no trailing slash, normalized hex
+ encoding. mirror.c concatenates "/<relpath>" onto this value and
+ must never see a trailing "/" or a non-normalized escape. */
+ conf->master_uri = svn_urlpath__canonicalize(arg1, cmd->pool);
return NULL;
}