Page MenuHomePhabricator

D10249.id24663.diff
No OneTemporary

D10249.id24663.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -353,6 +353,7 @@
'assert_stringlike' => 'utils/utils.php',
'coalesce' => 'utils/utils.php',
'csprintf' => 'xsprintf/csprintf.php',
+ 'escapepowershell' => 'xsprintf/csprintf.php',
'exec_manual' => 'future/exec/execx.php',
'execx' => 'future/exec/execx.php',
'head' => 'utils/utils.php',
diff --git a/src/xsprintf/PhutilCommandString.php b/src/xsprintf/PhutilCommandString.php
--- a/src/xsprintf/PhutilCommandString.php
+++ b/src/xsprintf/PhutilCommandString.php
@@ -3,6 +3,7 @@
final class PhutilCommandString extends Phobject {
private $argv;
+ private $powershell = false;
public function __construct(array $argv) {
$this->argv = $argv;
@@ -24,11 +25,17 @@
return $this->renderString(false);
}
+ public function setPowershell($powershell) {
+ $this->powershell = $powershell;
+ return $this;
+ }
+
private function renderString($unmasked) {
return xsprintf(
'xsprintf_command',
array(
'unmasked' => $unmasked,
+ 'powershell' => $this->powershell
),
$this->argv);
}
diff --git a/src/xsprintf/__tests__/PhutilCsprintfTestCase.php b/src/xsprintf/__tests__/PhutilCsprintfTestCase.php
--- a/src/xsprintf/__tests__/PhutilCsprintfTestCase.php
+++ b/src/xsprintf/__tests__/PhutilCsprintfTestCase.php
@@ -11,6 +11,26 @@
// context, %R should apply standard escaping.
$this->assertFalse('a b' === (string)csprintf('%R', 'a b'));
}
+
+ public function testPowershell() {
+ $cmd = csprintf('%s', "\n");
+ $cmd->setPowershell(true);
+
+ $this->assertEqual(
+ '"`n"',
+ (string)$cmd);
+ }
+
+ public function testNoPowershell() {
+ if (!phutil_is_windows()) {
+ $cmd = csprintf('%s', "#");
+ $cmd->setPowershell(false);
+
+ $this->assertEqual(
+ '\'#\'',
+ (string)$cmd);
+ }
+ }
public function testPasswords() {
// Normal "%s" doesn't do anything special.
diff --git a/src/xsprintf/csprintf.php b/src/xsprintf/csprintf.php
--- a/src/xsprintf/csprintf.php
+++ b/src/xsprintf/csprintf.php
@@ -56,6 +56,7 @@
$next = (strlen($pattern) > $pos + 1) ? $pattern[$pos + 1] : null;
$is_unmasked = !empty($userdata['unmasked']);
+ $is_powershell = !empty($userdata['powershell']);
if ($value instanceof PhutilCommandString) {
if ($is_unmasked) {
@@ -102,12 +103,20 @@
case 'R':
if (!preg_match('(^[a-zA-Z0-9:/@._-]+$)', $value)) {
- $value = escapeshellarg($value);
+ if ($is_powershell) {
+ $value = escapepowershell($value);
+ } else {
+ $value = escapeshellarg($value);
+ }
}
$type = 's';
break;
case 's':
- $value = escapeshellarg($value);
+ if ($is_powershell) {
+ $value = escapepowershell($value);
+ } else {
+ $value = escapeshellarg($value);
+ }
$type = 's';
break;
case 'P':
@@ -120,7 +129,11 @@
} else {
$value = 'xxxxx';
}
- $value = escapeshellarg($value);
+ if ($is_powershell) {
+ $value = escapepowershell($value);
+ } else {
+ $value = escapeshellarg($value);
+ }
$type = 's';
break;
case 'C':
@@ -130,3 +143,30 @@
$pattern[$pos] = $type;
}
+
+function escapepowershell($value) {
+
+ // These escape sequences are from http://ss64.com/ps/syntax-esc.html
+
+ // Replace backticks first.
+ $value = str_replace('`', '``', $value);
+
+ // Now replace other required notations.
+ $value = str_replace("\0", '`0', $value);
+ $value = str_replace('\a', '`a', $value);
+ $value = str_replace('\b', '`b', $value);
+ $value = str_replace("\f", '`f', $value);
+ $value = str_replace("\n", '`n', $value);
+ $value = str_replace("\r", '`r', $value);
+ $value = str_replace("\t", '`t', $value);
+ $value = str_replace("\v", '`v', $value);
+ $value = str_replace('#', '`#', $value);
+ $value = str_replace("'", '`\'', $value);
+ $value = str_replace('"', '`"', $value);
+
+ // The rule on dollar signs is mentioned further down the page, and
+ // they only need to be escaped when using double quotes (which we are).
+ $value = str_replace('$', '`$', $value);
+
+ return '"'.$value.'"';
+}

File Metadata

Mime Type
text/plain
Expires
Oct 28 2025, 2:05 PM (8 w, 1 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
12854071
Default Alt Text
D10249.id24663.diff (4 KB)

Event Timeline