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')
 


Reply via email to