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