r63214 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r63213‎ | r63214 | r63215 >
Date:18:22, 3 March 2010
Author:platonides
Status:reverted (Comments)
Tags:
Comment:
Follow-up r63213. Move it to wfEscapeShellArg, which is the proper place.
Modified paths:
  • /trunk/phase3/includes/GlobalFunctions.php (modified) (history)
  • /trunk/phase3/includes/Math.php (modified) (history)

Diff [purge]

Index: trunk/phase3/includes/GlobalFunctions.php
@@ -1460,13 +1460,17 @@
14611461 }
14621462 $delim = !$delim;
14631463 }
 1464+
14641465 // Double the backslashes before the end of the string, because
14651466 // we will soon add a quote
14661467 $m = array();
14671468 if ( preg_match( '/^(.*?)(\\\\+)$/', $arg, $m ) ) {
14681469 $arg = $m[1] . str_replace( '\\', '\\\\', $m[2] );
14691470 }
1470 -
 1471+
 1472+ // The caret is also an special character
 1473+ $arg = str_replace( "^", "^^", $arg );
 1474+
14711475 // Add surrounding quotes
14721476 $retVal .= '"' . $arg . '"';
14731477 } else {
Index: trunk/phase3/includes/Math.php
@@ -67,7 +67,7 @@
6868
6969 if ( wfIsWindows() ) {
7070 # Invoke it within cygwin sh, because texvc expects sh features in its default shell
71 - $cmd = 'sh -c ' . wfEscapeShellArg( str_replace( "^", "^^", $cmd ) );
 71+ $cmd = 'sh -c ' . wfEscapeShellArg( $cmd );
7272 }
7373
7474 wfDebug( "TeX: $cmd\n" );

Follow-up revisions

RevisionCommit summaryAuthorDate
r69201Revert r63213, r63214 per CR comment on r63214, doesn't match documented cmd....tstarling06:54, 9 July 2010
r69732Follow up r63214, and its revert r69201. The rules were more complex than a ...platonides16:04, 22 July 2010

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r63213Escape the caret under Windows, since that's a special character for cmd shell....platonides18:18, 3 March 2010

Comments

#Comment by Tim Starling (talk | contribs)   06:26, 9 July 2010

The reference quoted in comment 11 on the bug report (http://technet.microsoft.com/en-us/library/cc723564.aspx) states that special characters such as ^ must either be escaped with a ^, or enclosed in double quotes. The reference, and experimentation, suggests that doing both (as this code does) is incorrect:

C:\>echo ^^
^

C:\>echo "^^"
"^^"

C:\>echo "^"
"^"

I'm reverting. If you still think you're right, then you should respond on the bug report and document your testing procedure fully.

#Comment by Platonides (talk | contribs)   21:40, 12 July 2010

Do not use echo to test the Windows shell. It seems to be a builtin sometimes using different rules (eg. the quotes are printed as literals).

I tested it by compiling a program that iterated argv printing it. The results are in bug 13518#c9.

Math.php calls several times escapeshellarg() which, under Win32 will be surrounding with double quotes.

Thus we end up doing a call like wfEscapeShellArg('foo "bar" "baz"'); which outputs "foo \"bar\" \"baz\"". The \" escape the quotes but oddly the carets are treated as "not inside quotes", regardless of the closing quote being escaped with a backslash.

So relying only on the external double quotes is wrong and always doubling the carets isn't right either.

#Comment by Tim Starling (talk | contribs)   00:01, 13 July 2010

Please give the source code and compiler details of the program you used to test it.

You're probably aware that unlike UNIX, Windows passes command line parameters to applications as a single string, which the called program is then required to parse. Typically this is done by the Visual C++ run-time library, which splits the string provided and populates the argv and argc variables. The question then is: at what stage are double-carets converted to single-carets, and what is the relevant algorithm?

If the algorithm is something different to the documented behaviour for CMD.EXE, then we probably need to do a disassembly of the relevant VC++ code.

#Comment by Platonides (talk | contribs)   16:06, 22 July 2010

Yes, I know. I have been looking into it with more detail. The caret is handled by cmd.exe, while the quote escaping is at the program level. The problem is that in "Foo\"Bar", the content enclosed in double quotes is Foo\.

Program to output arguments:

#include <string.h>
#include <windows.h>

int main(int argc, char** argv) {
	int i;
	LPWSTR* argv2;
	
	puts( "GetCommandLine:" );
	puts( GetCommandLineA() );
	
	puts( "\n__getmainargs:" );
	do {
		printf( "<%s> ", *argv );
	} while( *++argv );

	puts( "\n\nCommandLineToArgvW:" );
	argv2 = CommandLineToArgvW( GetCommandLineW(), &argc );
	for ( i = 0; i < argc; i++) {
		wprintf( L"<%ls> ", argv2[i] );
	}

	return 0;
}


Testcase showing the problem:

<?php
define( 'MEDIAWIKI', true );

require "mediawiki/includes/GlobalFunctions.php";

echo 'Expected <AAA^BBB"CCC^DDD"EEE^FFF> <GGG>' . "\n";
echo wfShellExec("myecho " . wfEscapeShellArg('AAA^BBB"CCC^DDD"EEE^FFF', 'GGG'));
echo "\n\n\n\n";
echo 'Expected <AAA\\"BB>' . "\n";
echo wfShellExec("myecho " . wfEscapeShellArg('AAA\\"BB'));

I think it is fixed by r69732.

Status & tagging log