Skip to content

Commit fbd6d18

Browse files
committed
Follow Windows argument quoting rules
Fixes #142
1 parent 945d570 commit fbd6d18

File tree

4 files changed

+38
-9
lines changed

4 files changed

+38
-9
lines changed

Makefile.PL

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ if ( $^O ne 'MSWin32' ) {
1616
}
1717
}
1818
else {
19-
$PREREQ_PM{'Win32::Process'} = '0.14';
20-
$PREREQ_PM{'Win32API::File'} = '0.0901';
19+
$PREREQ_PM{'Win32::Process'} = '0.14';
20+
$PREREQ_PM{'Win32::ShellQuote'} = 0;
21+
$PREREQ_PM{'Win32API::File'} = '0.0901';
2122
if ( $] >= 5.021006 ) {
2223
$PREREQ_PM{'Win32API::File'} = '0.1203';
2324
}

lib/IPC/Run/Win32Helper.pm

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ require POSIX;
4040

4141
use Text::ParseWords;
4242
use Win32::Process;
43+
use Win32::ShellQuote ();
4344
use IPC::Run::Debug;
4445
use Win32API::File qw(
4546
FdGetOsFHandle
@@ -323,6 +324,11 @@ trying to be a little cross-platform here. The only difference is
323324
that "\" is *not* treated as an escape except when it precedes
324325
punctuation, since it's used all over the place in DOS path specs.
325326
327+
TODO: strip caret escapes?
328+
329+
TODO: use
330+
https://docs.microsoft.com/en-us/cpp/cpp/main-function-command-line-args#parsing-c-command-line-arguments
331+
326332
TODO: globbing? probably not (it's unDOSish).
327333
328334
TODO: shebang emulation? Probably, but perhaps that should be part
@@ -442,11 +448,7 @@ sub win32_spawn {
442448
}
443449

444450
my $process;
445-
my $cmd_line = join " ", map {
446-
( my $s = $_ ) =~ s/"/"""/g;
447-
$s = qq{"$s"} if /[\"\s]|^$/;
448-
$s;
449-
} @$cmd;
451+
my $cmd_line = Win32::ShellQuote::quote_native(@$cmd);
450452

451453
_debug "cmd line: ", $cmd_line
452454
if _debugging;

t/run.t

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ sub get_warnings {
3838
select STDERR;
3939
select STDOUT;
4040

41-
use Test::More tests => 268;
41+
use Test::More tests => 272;
4242
use IPC::Run::Debug qw( _map_fds );
4343
use IPC::Run qw( :filters :filter_imp start );
4444

@@ -210,6 +210,31 @@ is $? >> 8, 42;
210210
is( _map_fds, $fd_map );
211211
$fd_map = _map_fds;
212212

213+
##
214+
## Arguments bearing most bytes, excluding NUL (unsupported) and BEL (noisy and
215+
## not otherwise special). Arguments bearing special sequences of bytes.
216+
##
217+
{
218+
local $ENV{PERL_UNICODE};
219+
delete $ENV{PERL_UNICODE};
220+
221+
my @bytes = map { $_ == 7 ? () : pack( 'C', $_ ); } 1 .. 0xFF;
222+
$r = run(
223+
[ $perl, '-e', 'binmode STDOUT; print join "\0", @ARGV', @bytes ],
224+
'>', \$out
225+
);
226+
eok( $out, join "\0", @bytes );
227+
228+
my $sequences = qq{\\"\\az\\\\"\\\\\\};
229+
foreach my $payload ( join( '', @bytes ), $sequences, "$sequences\n" ) {
230+
$r = run(
231+
[ $perl, '-e', 'binmode STDOUT; print @ARGV', $payload ],
232+
'>', \$out
233+
);
234+
eok( $out, $payload );
235+
}
236+
}
237+
213238
##
214239
## A function
215240
##

t/win32_compile.t

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ BEGIN {
3535
plan( skip_all => "android does not support getprotobyname()" );
3636
}
3737

38-
$INC{$_} = 1 for qw( Win32/Process.pm Win32API/File.pm );
38+
$INC{$_} = 1 for qw(
39+
Win32/Process.pm Win32/ShellQuote.pm Win32API/File.pm );
3940

4041
package Win32API::File;
4142

0 commit comments

Comments
 (0)