Skip to content

Commit 42f7fcf

Browse files
committed
Improve RFC3986 parsing validation
1 parent 7ff16e9 commit 42f7fcf

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed

interfaces/UriString.php

+44
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,50 @@ public static function parse(Stringable|string|int $uri): array
583583
]
584584
);
585585

586+
return self::validateComponents($components);
587+
}
588+
589+
/**
590+
* Assert the URI internal state is valid.
591+
*
592+
* @link https://tools.ietf.org/html/rfc3986#section-3
593+
* @link https://tools.ietf.org/html/rfc3986#section-3.3
594+
*
595+
* @param ComponentMap $components
596+
*
597+
* @throws SyntaxError
598+
*
599+
* @return ComponentMap
600+
*/
601+
private static function validateComponents(array $components): array
602+
{
603+
$authority = UriString::buildAuthority($components);
604+
$path = $components['path'];
605+
606+
if (null !== $authority) {
607+
if (null !== $path && '' !== $path && '/' !== $path[0]) {
608+
throw new SyntaxError('If an authority is present the path must be empty or start with a `/`.');
609+
}
610+
611+
return $components;
612+
}
613+
614+
if (null === $path || '' === $path) {
615+
return $components;
616+
}
617+
618+
if (str_starts_with($path, '//')) {
619+
throw new SyntaxError('If there is no authority the path `'.$path.'` cannot start with a `//`.');
620+
}
621+
622+
if (null !== $components['scheme'] || false === ($pos = strpos($path, ':'))) {
623+
return $components;
624+
}
625+
626+
if (!str_contains(substr($path, 0, $pos), '/')) {
627+
throw new SyntaxError('In absence of a scheme and an authority the first path segment cannot contain a colon (":") character.');
628+
}
629+
586630
return $components;
587631
}
588632

uri/Uri.php

+2
Original file line numberDiff line numberDiff line change
@@ -1195,6 +1195,8 @@ public function toString(): string
11951195
public function toDisplayString(): string
11961196
{
11971197
$components = $this->toComponents();
1198+
1199+
11981200
unset($components['port']);
11991201
if (null !== $components['host']) {
12001202
$components['host'] = IdnaConverter::toUnicode($components['host'])->domain();

0 commit comments

Comments
 (0)