|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2020-06-16 02:30 UTC] svnpenn at gmail dot com
Description:
------------
proc_open failure with Windows
If I run this Python script:
import subprocess
a = [
r'C:\Windows\System32\msiexec.exe',
r'TargetDir=C:\TargetDir',
'/qb',
'/a',
'a.msi'
]
subprocess.run(a)
Everything is fine, but if I run this PHP script:
<?php
declare(strict_types = 1);
$a1 = [
'C:\\Windows\\System32\\msiexec.exe',
'TargetDir=C:\\TargetDir',
'/qb',
'/a',
'a.msi'
];
$a2 = [];
$a3 = [];
proc_open($a1, $a2, $a3);
I just get the usage page for Windows Installer. The documentation and tests
show that you can use an array:
- https://github.com/php/php-src/blob/master/ext/standard/tests/general_functions/proc_open_array.phpt
- https://www.php.net/manual/en/function.proc-open.php
but it seems PHP is doing something funny with the parsing.
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sun Nov 02 22:00:01 2025 UTC |
> proc_open() with the $cmd as an array will quote all the arguments. With a POSIX shell, this is fine. As with non special characters, a quoted string is the same as a non quoted string. So with a POSIX shell, these would be the same: /a '/a' but the Windows shell is not POSIX. And quoting should only be used when it is needed. A command like this will succeed: msiexec.exe TargetDir=C:\TargetDir /qb /a a.msi but add quotes and it fails: msiexec.exe TargetDir=C:\TargetDir /qb "/a" a.msi So it seems strange that "proc_open" assumes this is the correct thing to do for all platforms. As detailed in the original post, other languages dont do that. To make it worse, "escapeshellarg" is broken on Windows as well: > On Windows, escapeshellarg() instead replaces percent signs, exclamation marks > (delayed variable substitution) and double quotes with spaces and adds double > quotes around the string. https://php.net/function.escapeshellarg From a security standpoint that might be fine, but makes it impossible to run some valid external commands from PHP on Windows platform. As a workaround, I wrote this function: function f_escape_sh($s_in) { $s_out = preg_replace('/"/', '""', $s_in); if ($s_out != $s_in) { return '"' . $s_out . '"'; } $n_mat = preg_match('/[ &>^-]/', $s_in); if ($n_mat == 1) { return '"' . $s_out . '"'; } return $s_out; }