diff --git a/src/parser/PhutilGitURI.php b/src/parser/PhutilGitURI.php --- a/src/parser/PhutilGitURI.php +++ b/src/parser/PhutilGitURI.php @@ -30,6 +30,12 @@ } private static function parseURI($uri) { + // See T4913. Fail the parse if there is leading whitespace; stricter + // systems will not accept these URIs. + if (ltrim($uri) !== $uri) { + return null; + } + $user = '(?:([^@]+)@)?'; $domain = '([^:]+)'; $path = ':(.*)'; diff --git a/src/parser/PhutilURI.php b/src/parser/PhutilURI.php --- a/src/parser/PhutilURI.php +++ b/src/parser/PhutilURI.php @@ -17,6 +17,15 @@ public function __construct($uri) { $parts = parse_url($uri); + // The parse_url() call will accept URIs with leading whitespace, but many + // other tools (like git) will not. See T4913 for a specific example. If + // the input string has leading whitespace, fail the parse. + if ($parts) { + if (ltrim($uri) != $uri) { + $parts = false; + } + } + // NOTE: `parse_url()` is very liberal about host names; fail the parse if // the host looks like garbage. if ($parts) { diff --git a/src/parser/__tests__/PhutilGitURITestCase.php b/src/parser/__tests__/PhutilGitURITestCase.php --- a/src/parser/__tests__/PhutilGitURITestCase.php +++ b/src/parser/__tests__/PhutilGitURITestCase.php @@ -19,5 +19,10 @@ $this->assertEqual('host.com:path/to/something', (string)$uri); } + public function testStrictGitURIParsingOfLeadingWhitespace() { + $uri = new PhutilURI(' user@example.com'); + $this->assertEqual('', $uri->getDomain()); + } + } diff --git a/src/parser/__tests__/PhutilURITestCase.php b/src/parser/__tests__/PhutilURITestCase.php --- a/src/parser/__tests__/PhutilURITestCase.php +++ b/src/parser/__tests__/PhutilURITestCase.php @@ -76,4 +76,9 @@ $this->assertEqual('', $uri->getDomain()); } + public function testStrictURIParsingOfLeadingWhitespace() { + $uri = new PhutilURI(' http://example.com/'); + $this->assertEqual('', $uri->getDomain()); + } + }