8000 bug #45088 [Console] fix parsing escaped chars in StringInput (nicola… · symfony/symfony@6e67c62 · GitHub
[go: up one dir, main page]

Skip to content

Commit 6e67c62

Browse files
committed
bug #45088 [Console] fix parsing escaped chars in StringInput (nicolas-grekas)
This PR was merged into the 4.4 branch. Discussion ---------- [Console] fix parsing escaped chars in StringInput | Q | A | ------------- | --- | Branch? | 4.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | Fix #32182 | License | MIT | Doc PR | - Commits ------- f0a89ec [Console] fix parsing escaped chars in StringInput
2 parents 8a0ed01 + f0a89ec commit 6e67c62

File tree

2 files changed

+20
-4
lines changed

2 files changed

+20
-4
lines changed

src/Symfony/Component/Console/Input/StringInput.php

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
*/
2525
class StringInput extends ArgvInput
2626
{
27-
public const REGEX_STRING = '([^\s]+?)(?:\s|(?<!\\\\)"|(?<!\\\\)\'|$)';
27+
public const REGEX_STRING = '([^\s\\\\]+?)';
2828
public const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')';
2929

3030
/**
@@ -47,14 +47,25 @@ private function tokenize(string $input): array
4747
$tokens = [];
4848
$length = \strlen($input);
4949
$cursor = 0;
50+
$token = null;
5051
while ($cursor < $length) {
52+
if ('\\' === $input[$cursor]) {
53+
$token .= $input[++$cursor] ?? '';
54+
++$cursor;
55+
continue;
56+
}
57+
5158
if (preg_match('/\s+/A', $input, $match, 0, $cursor)) {
59+
if (null !== $token) {
60+
$tokens[] = $token;
61+
$token = null;
62+
}
5263
} elseif (preg_match('/([^="\'\s]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, 0, $cursor)) {
53-
$tokens[] = $match[1].$match[2].stripcslashes(str_replace(['"\'', '\'"', '\'\'', '""'], '', substr($match[3], 1, -1)));
64+
$token .= $match[1].$match[2].stripcslashes(str_replace(['"\'', '\'"', '\'\'', '""'], '', substr($match[3], 1, -1)));
5465
} elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, 0, $cursor)) {
55-
$tokens[] = stripcslashes(substr($match[0], 1, -1));
66+
$token .= stripcslashes(substr($match[0], 1, -1));
5667
} elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, 0, $cursor)) {
57-
$tokens[] = stripcslashes($match[1]);
68+
$token .= $match[1];
5869
} else {
5970
// should never happen
6071
throw new InvalidArgumentException(sprintf('Unable to parse input near "... %s ...".', substr($input, $cursor, 10)));
@@ -63,6 +74,10 @@ private function tokenize(string $input): array
6374
$cursor += \strlen($match[0]);
6475
}
6576

77+
if (null !== $token) {
78+
$tokens[] = $token;
79+
}
80+
6681
return $tokens;
6782
}
6883
}

src/Symfony/Component/Console/Tests/Input/StringInputTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ public function getTokenizeData()
7171
["--long-option='foo bar''another'", ['--long-option=foo baranother'], '->tokenize() parses long options with a value'],
7272
["--long-option='foo bar'\"another\"", ['--long-option=foo baranother'], '->tokenize() parses long options with a value'],
7373
['foo -a -ffoo --long bar', ['foo', '-a', '-ffoo', '--long', 'bar'], '->tokenize() parses when several arguments and options'],
74+
["--arg=\\\"'Jenny'\''s'\\\"", ["--arg=\"Jenny's\""], '->tokenize() parses quoted quotes'],
7475
];
7576
}
7677

0 commit comments

Comments
 (0)
0