Skip to content

Commit 1afa115

Browse files
kayw-geeksebastianbergmann
authored andcommitted
Quote PHP -d INI values so regex characters like " and ; survive
1 parent d54e2d8 commit 1afa115

2 files changed

Lines changed: 37 additions & 1 deletion

File tree

src/Util/PHP/JobRunner.php

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,11 @@
2626
use function is_resource;
2727
use function proc_close;
2828
use function proc_open;
29+
use function str_replace;
2930
use function str_starts_with;
3031
use function stream_get_contents;
32+
use function strpos;
33+
use function substr;
3134
use function sys_get_temp_dir;
3235
use function tempnam;
3336
use function trim;
@@ -325,9 +328,28 @@ private function settingsToParameters(array $settings): array
325328

326329
foreach ($settings as $setting) {
327330
$buffer[] = '-d';
328-
$buffer[] = $setting;
331+
$buffer[] = $this->quoteSettingValue($setting);
329332
}
330333

331334
return $buffer;
332335
}
336+
337+
/**
338+
* Wraps the value portion of a "name=value" INI setting in double quotes
339+
* so PHP's INI parser treats characters such as `;` (comment) and `"`
340+
* (string delimiter) as literal data instead of metacharacters.
341+
*/
342+
private function quoteSettingValue(string $setting): string
343+
{
344+
$position = strpos($setting, '=');
345+
346+
if ($position === false) {
347+
return $setting;
348+
}
349+
350+
$name = substr($setting, 0, $position);
351+
$value = substr($setting, $position + 1);
352+
353+
return $name . '="' . str_replace('"', '\\"', $value) . '"';
354+
}
333355
}

tests/unit/Util/PHP/JobRunnerTest.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,20 @@ public static function provider(): Generator
110110
input: 'test',
111111
),
112112
];
113+
114+
$obfuscationRegex = '(?i)(?:(?:"|%22)?)(?:(?:old[-_]?|new[-_]?)?p(?:ass)?w(?:or)?d(?:1|2)?|pass(?:[-_]?phrase)?|secret|(?:api_?|private_?|public_?|access_?|secret_?)key(?:_?id)?|token|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)(?:(?:\s|%20)*(?:=|%3D)[^&]+|(?:"|%22)(?:\s|%20)*(?::|%3A)(?:\s|%20)*(?:"|%22)(?:%2[^2]|%[^2]|[^"%])+(?:"|%22))|bearer(?:\s|%20)+[a-z0-9\._\-]+|token(?::|%3A)[a-z0-9]{13}|gh[opsu]_[0-9a-zA-Z]{36}|ey[I-L](?:[\w=-]|%3D)+\.ey[I-L](?:[\w=-]|%3D)+(?:\.(?:[\w.+\/=-]|%3D|%2F|%2B)+)?|-{5}BEGIN(?:[a-z\s]|%20)+PRIVATE(?:\s|%20)KEY-{5}[^\-]+-{5}END(?:[a-z\s]|%20)+PRIVATE(?:\s|%20)KEY(?:-{5})?(?:\n|%0A)?';
115+
116+
yield 'php setting value containing INI metacharacters' => [
117+
new Result($obfuscationRegex, ''),
118+
new Job(
119+
<<<'EOT'
120+
<?php declare(strict_types=1);
121+
print ini_get('highlight.string');
122+
123+
EOT,
124+
phpSettings: ['highlight.string=' . $obfuscationRegex],
125+
),
126+
];
113127
}
114128

115129
#[DataProvider('provider')]

0 commit comments

Comments
 (0)