Skip to content

Commit d3cea65

Browse files
authored
Merge pull request #286 from williamdes/CVE-2023-30536-1.4.x
Fix CVE-2023-30536 - GHSA-q2qj-628g-vhfw (1.4.x)
2 parents 0dca983 + 15192ea commit d3cea65

File tree

2 files changed

+78
-2
lines changed

2 files changed

+78
-2
lines changed

src/Headers.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ protected function validateHeader($name, $value): void
269269
*/
270270
protected function validateHeaderName($name): void
271271
{
272-
if (!is_string($name) || preg_match("@^[!#$%&'*+.^_`|~0-9A-Za-z-]+$@", $name) !== 1) {
272+
if (!is_string($name) || preg_match("@^[!#$%&'*+.^_`|~0-9A-Za-z-]+$@D", $name) !== 1) {
273273
throw new InvalidArgumentException('Header name must be an RFC 7230 compatible string.');
274274
}
275275
}
@@ -289,7 +289,7 @@ protected function validateHeaderValue($value): void
289289
);
290290
}
291291

292-
$pattern = "@^[ \t\x21-\x7E\x80-\xFF]*$@";
292+
$pattern = "@^[ \t\x21-\x7E\x80-\xFF]*$@D";
293293
foreach ($items as $item) {
294294
$hasInvalidType = !is_numeric($item) && !is_string($item);
295295
$rejected = $hasInvalidType || preg_match($pattern, (string) $item) !== 1;

tests/HeadersTest.php

+76
Original file line numberDiff line numberDiff line change
@@ -209,4 +209,80 @@ public function testParseAuthorizationHeader()
209209
$headers = new Headers([], ['PHP_AUTH_DIGEST' => 'digest']);
210210
$this->assertEquals(['digest'], $headers->getHeader('Authorization'));
211211
}
212+
213+
/**
214+
* @dataProvider provideInvalidHeaderNames
215+
*/
216+
public function testWithInvalidHeaderName($headerName): void
217+
{
218+
$headers = new Headers();
219+
220+
$this->expectException(\InvalidArgumentException::class);
221+
222+
$headers->setHeader($headerName, 'foo');
223+
}
224+
225+
public static function provideInvalidHeaderNames(): array
226+
{
227+
return [
228+
[[]],
229+
[false],
230+
[new \stdClass()],
231+
["Content-Type\r\n\r\n"],
232+
["Content-Type\r\n"],
233+
["Content-Type\n"],
234+
["\r\nContent-Type"],
235+
["\nContent-Type"],
236+
["\n"],
237+
["\r\n"],
238+
["\t"],
239+
];
240+
}
241+
242+
/**
243+
* @dataProvider provideInvalidHeaderValues
244+
*/
245+
public function testSetInvalidHeaderValue($headerValue)
246+
{
247+
$headers = new Headers();
248+
249+
$this->expectException(\InvalidArgumentException::class);
250+
251+
$headers->setHeader('Content-Type', $headerValue);
252+
}
253+
254+
public static function provideInvalidHeaderValues(): array
255+
{
256+
// Explicit tests for newlines as the most common exploit vector.
257+
$tests = [
258+
["new\nline"],
259+
["new\r\nline"],
260+
["new\rline"],
261+
["new\r\n line"],
262+
["newline\n"],
263+
["\nnewline"],
264+
["newline\r\n"],
265+
["\n\rnewline"],
266+
];
267+
268+
for ($i = 0; $i <= 0xff; $i++) {
269+
if (\chr($i) == "\t") {
270+
continue;
271+
}
272+
if (\chr($i) == " ") {
273+
continue;
274+
}
275+
if ($i >= 0x21 && $i <= 0x7e) {
276+
continue;
277+
}
278+
if ($i >= 0x80) {
279+
continue;
280+
}
281+
282+
$tests[] = ["foo" . \chr($i) . "bar"];
283+
$tests[] = ["foo" . \chr($i)];
284+
}
285+
286+
return $tests;
287+
}
212288
}

0 commit comments

Comments
 (0)