Author: svn-role
Date: Fri Dec 7 04:02:33 2012
New Revision: 1418182
URL: http://svn.apache.org/viewvc?rev=1418182&view=rev
Log:
Merge the r1403588 group from trunk:
* r1403588, r1403691
Expand the scope of mod_dav_svn's validation of client-reported
and client-requested revisions during update operations.
Justifications:
mod_dav_svn should gracefully complain about revisions > HEAD
in the update report all the time, not only when doing an
update operation that doesn't explicitly request a target
revision.
Votes:
+1: cmpilato, rhuijben, brane
Modified:
subversion/branches/1.7.x/ (props changed)
subversion/branches/1.7.x/STATUS
subversion/branches/1.7.x/subversion/mod_dav_svn/reports/update.c
subversion/branches/1.7.x/subversion/tests/cmdline/update_tests.py
Propchange: subversion/branches/1.7.x/
------------------------------------------------------------------------------
Merged /subversion/trunk:r1403588,1403691
Modified: subversion/branches/1.7.x/STATUS
URL:
http://svn.apache.org/viewvc/subversion/branches/1.7.x/STATUS?rev=1418182&r1=1418181&r2=1418182&view=diff
==============================================================================
--- subversion/branches/1.7.x/STATUS (original)
+++ subversion/branches/1.7.x/STATUS Fri Dec 7 04:02:33 2012
@@ -91,14 +91,3 @@ Veto-blocked changes:
Approved changes:
=================
-
- * r1403588, r1403691
- Expand the scope of mod_dav_svn's validation of client-reported
- and client-requested revisions during update operations.
- Justifications:
- mod_dav_svn should gracefully complain about revisions > HEAD
- in the update report all the time, not only when doing an
- update operation that doesn't explicitly request a target
- revision.
- Votes:
- +1: cmpilato, rhuijben, brane
Modified: subversion/branches/1.7.x/subversion/mod_dav_svn/reports/update.c
URL:
http://svn.apache.org/viewvc/subversion/branches/1.7.x/subversion/mod_dav_svn/reports/update.c?rev=1418182&r1=1418181&r2=1418182&view=diff
==============================================================================
--- subversion/branches/1.7.x/subversion/mod_dav_svn/reports/update.c (original)
+++ subversion/branches/1.7.x/subversion/mod_dav_svn/reports/update.c Fri Dec
7 04:02:33 2012
@@ -845,6 +845,49 @@ malformed_element_error(const char *tagn
}
+/* Validate that REVISION is a valid revision number for repository in
+ which YOUNGEST is the latest revision. Use RESOURCE as a
+ convenient way to access the request record and a pool for error
+ messaging. (It's okay if REVISION is SVN_INVALID_REVNUM, as in
+ the related contexts that just means "the youngest revision".)
+
+ REVTYPE is just a string describing the type/purpose of REVISION,
+ used in the generated error string. */
+static dav_error *
+validate_input_revision(svn_revnum_t revision,
+ svn_revnum_t youngest,
+ const char *revtype,
+ const dav_resource *resource)
+{
+ if (! SVN_IS_VALID_REVNUM(revision))
+ return SVN_NO_ERROR;
+
+ if (revision > youngest)
+ {
+ svn_error_t *serr;
+
+ if (dav_svn__get_master_uri(resource->info->r))
+ {
+ serr = svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, 0,
+ "No such %s '%ld' found in the repository.
"
+ "Perhaps the repository is out of date with
"
+ "respect to the master repository?",
+ revtype, revision);
+ }
+ else
+ {
+ serr = svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, 0,
+ "No such %s '%ld' found in the repository.",
+ revtype, revision);
+ }
+ return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
+ "Invalid revision found in update report "
+ "request.", resource->pool);
+ }
+ return SVN_NO_ERROR;
+}
+
+
dav_error *
dav_svn__update_report(const dav_resource *resource,
const apr_xml_doc *doc,
@@ -854,8 +897,7 @@ dav_svn__update_report(const dav_resourc
apr_xml_elem *child;
void *rbaton = NULL;
update_ctx_t uc = { 0 };
- svn_revnum_t revnum = SVN_INVALID_REVNUM;
- svn_boolean_t revnum_is_head = FALSE;
+ svn_revnum_t youngest, revnum = SVN_INVALID_REVNUM;
svn_revnum_t from_revnum = SVN_INVALID_REVNUM;
int ns;
/* entry_counter and entry_is_empty are for operational logging. */
@@ -920,6 +962,14 @@ dav_svn__update_report(const dav_resourc
}
}
+ /* Ask the repository about its youngest revision (which we'll need
+ for some input validation later). */
+ if ((serr = svn_fs_youngest_rev(&youngest, repos->fs, resource->pool)))
+ return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
+ "Could not determine the youngest "
+ "revision for the update process.",
+ resource->pool);
+
for (child = doc->root->first_child; child != NULL; child = child->next)
{
/* Note that child->name might not match any of the cases below.
@@ -1039,6 +1089,23 @@ dav_svn__update_report(const dav_resourc
}
}
+ /* If a target revision wasn't requested, or the requested target
+ revision was invalid, just update to HEAD as of the moment we
+ queried the youngest revision. Otherwise, at least make sure the
+ request makes sense in light of that youngest revision
+ number. */
+ if (! SVN_IS_VALID_REVNUM(revnum))
+ {
+ revnum = youngest;
+ }
+ else
+ {
+ derr = validate_input_revision(revnum, youngest, "target revision",
+ resource);
+ if (derr)
+ return derr;
+ }
+
if (!saw_depth && !saw_recursive && (requested_depth == svn_depth_unknown))
requested_depth = svn_depth_infinity;
@@ -1054,18 +1121,6 @@ dav_svn__update_report(const dav_resourc
SVN_DAV_ERROR_TAG);
}
- /* If a revision for this operation was not dictated to us, this
- means "update to whatever the current HEAD is now". */
- if (revnum == SVN_INVALID_REVNUM)
- {
- if ((serr = svn_fs_youngest_rev(&revnum, repos->fs, resource->pool)))
- return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
- "Could not determine the youngest "
- "revision for the update process.",
- resource->pool);
- revnum_is_head = TRUE;
- }
-
uc.svndiff_version = resource->info->svndiff_version;
uc.resource = resource;
uc.output = output;
@@ -1179,27 +1234,10 @@ dav_svn__update_report(const dav_resourc
{
rev = SVN_STR_TO_REV(this_attr->value);
saw_rev = TRUE;
- if (revnum_is_head && rev > revnum)
- {
- if (dav_svn__get_master_uri(resource->info->r))
- return dav_svn__new_error_tag(
- resource->pool,
- HTTP_INTERNAL_SERVER_ERROR, 0,
- "A reported revision is higher than the "
- "current repository HEAD revision. "
- "Perhaps the repository is out of date "
- "with respect to the master repository?",
- SVN_DAV_ERROR_NAMESPACE,
- SVN_DAV_ERROR_TAG);
- else
- return dav_svn__new_error_tag(
- resource->pool,
- HTTP_INTERNAL_SERVER_ERROR, 0,
- "A reported revision is higher than the "
- "current repository HEAD revision.",
- SVN_DAV_ERROR_NAMESPACE,
- SVN_DAV_ERROR_TAG);
- }
+ if ((derr = validate_input_revision(rev, youngest,
+ "reported revision",
+ resource)))
+ return derr;
}
else if (strcmp(this_attr->name, "depth") == 0)
depth = svn_depth_from_word(this_attr->value);
Modified: subversion/branches/1.7.x/subversion/tests/cmdline/update_tests.py
URL:
http://svn.apache.org/viewvc/subversion/branches/1.7.x/subversion/tests/cmdline/update_tests.py?rev=1418182&r1=1418181&r2=1418182&view=diff
==============================================================================
--- subversion/branches/1.7.x/subversion/tests/cmdline/update_tests.py
(original)
+++ subversion/branches/1.7.x/subversion/tests/cmdline/update_tests.py Fri Dec
7 04:02:33 2012
@@ -5397,9 +5397,12 @@ def update_to_HEAD_plus_1(sbox):
sbox.build(read_only = True)
wc_dir = sbox.wc_dir
+ # Attempt the update, expecting an error. (Sometimes the error
+ # strings says "No such revision", sometimes "No such target
+ # revision".)
svntest.actions.run_and_verify_update(wc_dir,
None, None, None,
- ".*No such revision",
+ "E160006.*No such.*revision",
None, None,
None, None, None, wc_dir, '-r', '2')