On Mon, 2009-12-14, I (Julian Foad) wrote:
> Jon Foster wrote:
> > It seems that mod_dav_svn doesn't escape special XML characters like
> > "<" and ">" in the error messages from hook scripts.  This causes
> > corrupt XML to be sent across the wire.  Here's a Wireshark capture
> > of the response to the PROPPATCH:
> [...]

> It looks like the problem has been there for years. I think this patch
> should fix it. Do you feel like writing a regression test?

I wrote one myself. Attached. I confirmed the bug, but I am having
trouble testing my test. It may be to do with the test suite not quite
properly supporting a build in a separate directory.

> [[[
> In mod_dav_svn, make error output from the post-commit hook XML-safe, to fix
> the "invalid XML" error that occurred if a post-commit error message
> contained "&" or "<" characters.
> 
> * subversion/mod_dav_svn/merge.c
>   (dav_svn__merge_response): XML-quote the error string.
> --This line, and those below, will be ignored--
> 
> Index: subversion/mod_dav_svn/merge.c
> ===================================================================
> --- subversion/mod_dav_svn/merge.c      (revision 889737)
> +++ subversion/mod_dav_svn/merge.c      (working copy)
> @@ -252,7 +252,9 @@ dav_svn__merge_response(ap_filter_t *out
>        post_commit_err_elem = apr_psprintf(pool,
>                                            "<S:post-commit-err>%s"
>                                            "</S:post-commit-err>",
> -                                          post_commit_err);
> +                                          apr_xml_quote_string(pool,
> +                                                               
> post_commit_err,
> +                                                               0));
>      }
>    else
>      {
> ]]]

- Julian

Add a regression test for post-revprop error message causing invalid XML if
it contains certain XML characters such as '&' and '<'.

* subversion/tests/cmdline/prop_tests.py
  (post_revprop_hook_message_non_xml): New test.
  (test_list): Add the new test.

* subversion/tests/cmdline/svntest/actions.py
  (disable_revprop_changes): Add an optional argument for specifying extra
    text to be included in the hook's error message.
--This line, and those below, will be ignored--

Index: subversion/tests/cmdline/prop_tests.py
===================================================================
--- subversion/tests/cmdline/prop_tests.py	(revision 891747)
+++ subversion/tests/cmdline/prop_tests.py	(working copy)
@@ -1703,6 +1703,33 @@ def delete_nonexistent_property(sbox):
                                      'propdel', 'yellow',
                                      os.path.join(wc_dir, 'A', 'D', 'G'))
 
+#----------------------------------------------------------------------
+# Test the marshalling of a post-commit error message that contains XML
+# significant characters such as '&' and '<'. This used to fail over RA-dav,
+# resulting in the error 'XML data was not well-formed' on the client.
+#
+def post_revprop_hook_message_non_xml(sbox):
+  "post-revprop-change hook message with XML chars"
+
+  sbox.build()
+
+  wc_dir = sbox.wc_dir
+  repo_dir = sbox.repo_dir
+
+  text = 'Text with <angle brackets> & ampersand'
+
+  svntest.actions.enable_revprop_changes(repo_dir)
+  svntest.actions.create_failing_hook(repo_dir, 'post-revprop-change', text)
+
+  expected_error = svntest.verify.ExpectedOutput([
+    "svn: post-revprop-change hook failed (exit code 1) with output:\n",
+    "post-revprop-change hook failed: " + text + "\n",
+  ], match_all = False)
+
+  svntest.actions.run_and_verify_svn(None, [], expected_error,
+                                     'ps', '--revprop', '-r0', 'p', 'v',
+                                     wc_dir)
+
 
 ########################################################################
 # Run the tests
@@ -1743,6 +1770,7 @@ test_list = [ None,
               same_replacement_props,
               added_moved_file,
               delete_nonexistent_property,
+              post_revprop_hook_message_non_xml,
              ]
 
 if __name__ == '__main__':
Index: subversion/tests/cmdline/svntest/actions.py
===================================================================
--- subversion/tests/cmdline/svntest/actions.py	(revision 891747)
+++ subversion/tests/cmdline/svntest/actions.py	(working copy)
@@ -1590,16 +1590,17 @@ def enable_revprop_changes(repo_dir):
   hook_path = main.get_pre_revprop_change_hook_path(repo_dir)
   main.create_python_hook_script(hook_path, 'import sys; sys.exit(0)')
 
-def disable_revprop_changes(repo_dir):
+def disable_revprop_changes(repo_dir, extra_text=''):
   """Disable revprop changes in the repository at REPO_DIR by creating a
   pre-revprop-change hook script that prints "pre-revprop-change" followed
-  by its arguments, and returns an error."""
+  by its arguments and the optional extra TEXT, and returns an error."""
 
   hook_path = main.get_pre_revprop_change_hook_path(repo_dir)
   main.create_python_hook_script(hook_path,
-                                 'import sys\n'
-                                 'sys.stderr.write("pre-revprop-change %s" % " ".join(sys.argv[1:6]))\n'
-                                 'sys.exit(1)\n')
+    'import sys\n'
+    'sys.stderr.write("pre-revprop-change %s\\n" % " ".join(sys.argv[1:6]))\n'
+    'sys.stderr.write(' + repr(extra_text) + ')\n'
+    'sys.exit(1)\n')
 
 def create_failing_post_commit_hook(repo_dir):
   """Create a post-commit hook script in the repository at REPO_DIR that always

Reply via email to