james...@apache.org wrote on Sat, 15 Feb 2020 16:24 -0000:
> Escape filenames when invoking $SVN_EDITOR
> 
> Per https://subversion.apache.org/faq.html#svn-editor, $SVN_EDITOR is invoked
> through the shell instead of directly executed.  The user is expected to
> properly escape/quote $SVN_EDITOR, but svn was putting the filename directly
> into the command without any escaping.  This therefore breaks attempts to,
> e.g., run the editor from the merge conflict dialog when a path has special
> characters.
> 
> Update locations where we invoke the editor to quote the filename as well as
> escape shell special characters using apr_pescape_shell().  The quotes are
> needed in addition to the escaping, since apr_pescape_shell() does not escape
> whitespace.

> +++ subversion/trunk/subversion/libsvn_subr/cmdline.c Sat Feb 15 16:24:53 2020
> @@ -1330,7 +1331,10 @@ svn_cmdline__edit_file_externally(const
>      return svn_error_wrap_apr
>        (apr_err, _("Can't change working directory to '%s'"), base_dir);
>  
> -  cmd = apr_psprintf(pool, "%s %s", editor, file_name);
> +  /* editor is explicitly documented as being interpreted by the user's 
> shell,
> +     and as such should already be quoted/escaped as needed. */
> +  cmd = apr_psprintf(pool, "%s \"%s\"", editor,
> +                     apr_pescape_shell(pool, file_name));

If FILE_NAME is «;» (i.e., a single semicolon), apr_pescape_shell()
will return «\;» (two bytes) and then the command string will be «vi "\;"»,
so vi would edit the file «\;» (two bytes).

This can happen in the conflict-callbacks.c caller, which
passes LOCAL_ABSPATH of a versioned file:

[[[
#!/bin/sh
rm -rf r wc
svnadmin create r
svnmucc put -U file://`pwd`/r -m 'r1' /dev/null ';'
svn co -q file://`pwd`/r wc
cd wc
echo foo > ';'
svn ci -q -m 'r2'
svn up -q -r1
echo bar > ';'
../subversion/svn/svn up --accept=e --editor-cmd='false'
]]]

[[[
% ./repro.sh
r1 committed by daniel at 2020-02-15T17:23:47.372055Z
Updating '.':
C    ;
Updated to revision 2.
system('false "\;"') returned 256
Merge conflicts in ';' marked as resolved.
Summary of conflicts:
  Text conflicts: 0 remaining (and 1 already resolved)
]]]

That could conceivably happen for other callers as well if
svn_io_open_uniquely_named() returns an abspath which contains
a literal semicolon in the directory part.  Its API contract
doesn't forbid that.

Sorry for not noticing this before; I'm sure I saw a previous version
of this patch at some point…

Daniel

>    sys_err = system(cmd);
>  
>    apr_err = apr_filepath_set(old_cwd, pool);
> @@ -1489,7 +1493,11 @@ svn_cmdline__edit_string_externally(svn_
>    err = svn_utf_cstring_from_utf8(&tmpfile_native, tmpfile_name, pool);
>    if (err)
>      goto cleanup;
> -  cmd = apr_psprintf(pool, "%s %s", editor, tmpfile_native);
> +
> +  /* editor is explicitly documented as being interpreted by the user's 
> shell,
> +     and as such should already be quoted/escaped as needed. */
> +  cmd = apr_psprintf(pool, "%s \"%s\"", editor,
> +                     apr_pescape_shell(pool, tmpfile_native));

Reply via email to