URLs are encoded in UTF-8, then decoded as if they are Latin1
authorbenjamin@webkit.org <benjamin@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 1 Dec 2011 22:51:13 +0000 (22:51 +0000)
committerbenjamin@webkit.org <benjamin@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 1 Dec 2011 22:51:13 +0000 (22:51 +0000)
https://bugs.webkit.org/show_bug.cgi?id=71758

Reviewed by Darin Adler.

Source/JavaScriptCore:

Add the operator == between a String and a Vector of char. The implementation
is the same as the comparison of String and char* but adds the length as a
parameter for comparing the strings.

* JavaScriptCore.exp:
* wtf/text/StringImpl.h:
(WTF::equal):
* wtf/text/WTFString.h:
(WTF::operator==):
(WTF::operator!=):

Source/WebCore:

Previously, invalid URLs could have a string emanating from a
partial parsing of the input. The creation of the string was done
through the Latin1 codec regardless of the encoding of the char* url.

This caused two types of issues, URLs were evaluated as half-parsed,
and the coding and decoding of the string was not consistent.

This patch changes KURL::parse() to fallback on the original string
whenever the parsing of the URL fails.

Test: fast/url/invalid-urls-utf8.html

* platform/KURL.cpp:
(WebCore::KURL::KURL):
(WebCore::KURL::init):
(WebCore::KURL::parse):
Previously, originalString was only used as an optimization to avoid
the allocation of a string. Since this optimization depends on the
comparison of the incoming string and the encoded buffer.
This patches generalizes originalString to always be the original string
being parsed by KURL. The optimization is kept by comparing that string
and the final parsed result.
* platform/KURL.h:
(WebCore::KURL::parse):
* platform/cf/KURLCFNet.cpp:
(WebCore::KURL::KURL):
* platform/mac/KURLMac.mm:
(WebCore::KURL::KURL):

LayoutTests:

* fast/url/invalid-urls-utf8-expected.txt: Added.
* fast/url/invalid-urls-utf8.html: Added.
New test for invalid URL where the Unicode characters were mangled
by the parsing.

* fast/url/file-expected.txt:
* fast/url/file-http-base-expected.txt:
Two urls where expended by their base URL before found invalid. The partial
parsed result was saved as the new URL.

* fast/url/host-expected.txt:
The host of two urls were invalid, and partially modified by the parsing.

* fast/url/idna2003-expected.txt:
The first 'http://www.lookout.net⩴80/' encoded for parsing is http://www.lookout.net::=80/
and fails as invalid. The new result does not modify the original string.

The whitespace in 'http://www .lookout.net/' causes the parsing to fail when parsing
the username because a space is not a UserInfoChar.

* fast/url/port-expected.txt:
The unicode characters used as the port number were transformed due to
the encoding UTF-8 -> Unicode through the Latin1 codec.

* platform/chromium/test_expectations.txt: Skip the test on Chromium for now since Google URL
does not implement the extended version of parse().

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@101713 268f45cc-cd09-0410-ab3c-d52691b4dbfc

18 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/url/file-expected.txt
LayoutTests/fast/url/file-http-base-expected.txt
LayoutTests/fast/url/host-expected.txt
LayoutTests/fast/url/idna2003-expected.txt
LayoutTests/fast/url/invalid-urls-utf8-expected.txt [new file with mode: 0644]
LayoutTests/fast/url/invalid-urls-utf8.html [new file with mode: 0644]
LayoutTests/fast/url/port-expected.txt
LayoutTests/platform/chromium/test_expectations.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.exp
Source/JavaScriptCore/wtf/text/StringImpl.h
Source/JavaScriptCore/wtf/text/WTFString.h
Source/WebCore/ChangeLog
Source/WebCore/platform/KURL.cpp
Source/WebCore/platform/KURL.h
Source/WebCore/platform/cf/KURLCFNet.cpp
Source/WebCore/platform/mac/KURLMac.mm

index 0ce0617bc4d95bf2b1a218ab78efcc531838bea0..b9df91cdb013140f4301f739a72be5e463ae96cf 100644 (file)
@@ -1,3 +1,37 @@
+2011-12-01  Benjamin Poulain  <benjamin@webkit.org>
+
+        URLs are encoded in UTF-8, then decoded as if they are Latin1
+        https://bugs.webkit.org/show_bug.cgi?id=71758
+
+        Reviewed by Darin Adler.
+
+        * fast/url/invalid-urls-utf8-expected.txt: Added.
+        * fast/url/invalid-urls-utf8.html: Added.
+        New test for invalid URL where the Unicode characters were mangled
+        by the parsing.
+
+        * fast/url/file-expected.txt:
+        * fast/url/file-http-base-expected.txt:
+        Two urls where expended by their base URL before found invalid. The partial
+        parsed result was saved as the new URL.
+
+        * fast/url/host-expected.txt:
+        The host of two urls were invalid, and partially modified by the parsing.
+
+        * fast/url/idna2003-expected.txt:
+        The first 'http://www.lookout.net⩴80/' encoded for parsing is http://www.lookout.net::=80/
+        and fails as invalid. The new result does not modify the original string.
+
+        The whitespace in 'http://www .lookout.net/' causes the parsing to fail when parsing
+        the username because a space is not a UserInfoChar.
+
+        * fast/url/port-expected.txt:
+        The unicode characters used as the port number were transformed due to
+        the encoding UTF-8 -> Unicode through the Latin1 codec.
+
+        * platform/chromium/test_expectations.txt: Skip the test on Chromium for now since Google URL
+        does not implement the extended version of parse().
+
 2011-12-01  Sheriff Bot  <webkit.review.bot@gmail.com>
 
         Unreviewed, rolling out r101691.
index d2746733d6544f8957e8b0c43f8e631b6d452091..ab3f7f8c5c321fd17a3218bcba0c4274bb12f7b2 100644 (file)
@@ -10,7 +10,7 @@ FAIL canonicalize('file:UNChost/path') should be file://unchost/path. Was file:/
 FAIL canonicalize('c:\\foo\\bar') should be file:///C:/foo/bar. Was c:/foo/bar.
 FAIL canonicalize('C|/foo/bar') should be file:///C:/foo/bar. Was file:///tmp/mock/C|/foo/bar.
 FAIL canonicalize('/C|\\foo\\bar') should be file:///C:/foo/bar. Was file:///C|/foo/bar.
-FAIL canonicalize('//C|/foo/bar') should be file:///C:/foo/bar. Was file://C|/foo/bar.
+FAIL canonicalize('//C|/foo/bar') should be file:///C:/foo/bar. Was //C|/foo/bar.
 PASS canonicalize('//server/file') is 'file://server/file'
 PASS canonicalize('\\\\server\\file') is 'file://server/file'
 PASS canonicalize('/\\server/file') is 'file://server/file'
index f9169cd5088eb101574ab4bdfed863d062c7632b..ce2cb0811e5a62eb2c339632d0267e6bf1c43c69 100644 (file)
@@ -10,7 +10,7 @@ FAIL canonicalize('file:UNChost/path') should be file://unchost/path. Was file:/
 FAIL canonicalize('c:\\foo\\bar') should be file:///C:/foo/bar. Was c:/foo/bar.
 FAIL canonicalize('C|/foo/bar') should be file:///C:/foo/bar. Was http://example.com/mock/C|/foo/bar.
 FAIL canonicalize('/C|\\foo\\bar') should be file:///C:/foo/bar. Was http://example.com/C|/foo/bar.
-FAIL canonicalize('//C|/foo/bar') should be file:///C:/foo/bar. Was http://C|/foo/bar.
+FAIL canonicalize('//C|/foo/bar') should be file:///C:/foo/bar. Was //C|/foo/bar.
 FAIL canonicalize('//server/file') should be file://server/file. Was http://server/file.
 FAIL canonicalize('\\\\server\\file') should be file://server/file. Was http://server/file.
 FAIL canonicalize('/\\server/file') should be file://server/file. Was http://server/file.
index 43e38ebf1f1d2874b001e77b83419349278e2de7..bd18c47255cc464b3a03b4fd899e2d3a3df78706 100644 (file)
@@ -5,7 +5,7 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 
 FAIL canonicalize('http://GoOgLe.CoM/') should be http://google.com/. Was http://GoOgLe.CoM/.
 FAIL canonicalize('http://Goo%20 goo%7C|.com/') should be http://goo%20%20goo%7C%7C.com/. Was http://Goo%20 goo%7C|.com/.
-FAIL canonicalize('http://GOO  goo.com/') should be http://goo%20%20goo.com/. Was http://goo  goo.com/.
+FAIL canonicalize('http://GOO  goo.com/') should be http://goo%20%20goo.com/. Was http://GOO  goo.com/.
 PASS canonicalize('http://GOO​⁠goo.com/') is 'http://googoo.com/'
 PASS canonicalize('http://www.foo。bar.com/') is 'http://www.foo.bar.com/'
 FAIL canonicalize('http://﷐zyx.com/') should be http://%EF%BF%BDzyx.com/. Was http:/.
@@ -27,7 +27,7 @@ FAIL canonicalize('http://192.168.0.1 hello/') should be http://192.168.0.1%20he
 FAIL canonicalize('http://0Xc0.0250.01/') should be http://192.168.0.1/. Was http://0xc0.0250.01/.
 PASS canonicalize('http://192.168.0.257/') is 'http://192.168.0.257/'
 PASS canonicalize('http://[google.com]/') is 'http://[google.com]/'
-FAIL canonicalize('http://т(/') should be http://xn--%28-7ed/. Was http://xn--(-8tb/.
+FAIL canonicalize('http://т(/') should be http://xn--%28-7ed/. Was http://т(/.
 PASS canonicalize('http://go\\@ogle.com/') is 'http://go/@ogle.com/'
 PASS canonicalize('http://go/@ogle.com/') is 'http://go/@ogle.com/'
 FAIL canonicalize('http://www.lookout.net::==80::==443::/') should be http://www.lookout.net::%3D%3D80::%3D%3D443:/. Was http://www.lookout.net::==80::==443::/.
index fd1dc3e97fbc0f3791697e664dc7ce468f3d4d5a..790ba2ced6d57a7d79c6a0232d590757c9aa67f8 100644 (file)
@@ -15,8 +15,8 @@ FAIL canonicalize('http://www.lookout.net:80/') should be http://www.lookout.n
 PASS canonicalize('http://www‥lookout.net/') is 'http://www..lookout.net/'
 PASS canonicalize('http://www.lookout‧net/') is 'http://www.xn--lookoutnet-406e/'
 PASS canonicalize('http://www.looĸout.net/') is 'http://www.xn--looout-5bb.net/'
-FAIL canonicalize('http://www.lookout.net⩴80/') should be http://www.lookout.net::%3D80/. Was http://www.lookout.net::=80/.
-FAIL canonicalize('http://www .lookout.net/') should be http://www%20.lookout.net/. Was http://www .lookout.net/.
+FAIL canonicalize('http://www.lookout.net⩴80/') should be http://www.lookout.net::%3D80/. Was http://www.lookout.net80/.
+FAIL canonicalize('http://www .lookout.net/') should be http://www%20.lookout.net/. Was http://www .lookout.net/.
 FAIL canonicalize('http:// lookout.net/') should be http://%E1%9A%80lookout.net/. Was http:/.
 FAIL canonicalize('http://\1flookout.net/') should be http://%1Flookout.net/. Was http://\1flookout.net/.
 FAIL canonicalize('http://look۝out.net/') should be http://look%DB%9Dout.net/. Was http:/.
diff --git a/LayoutTests/fast/url/invalid-urls-utf8-expected.txt b/LayoutTests/fast/url/invalid-urls-utf8-expected.txt
new file mode 100644 (file)
index 0000000..43a2758
--- /dev/null
@@ -0,0 +1,25 @@
+This ensure we do not mess up the bytes when an URL is partially parsed and is invalid.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS src is expected
+PASS src is expected
+PASS src is expected
+PASS src is expected
+PASS src is expected
+PASS src is expected
+PASS src is expected
+PASS src is expected
+PASS src is expected
+PASS src is expected
+PASS src is expected
+PASS src is expected
+PASS src is expected
+PASS src is expected
+PASS src is expected
+PASS src is expected
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/url/invalid-urls-utf8.html b/LayoutTests/fast/url/invalid-urls-utf8.html
new file mode 100644 (file)
index 0000000..e99244d
--- /dev/null
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../js/resources/js-test-pre.js"></script>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<script src="resources/utilities.js"></script>
+<!-- Set the base so that the current URL does not affect the tests. -->
+<base href="">
+</head>
+<body>
+
+<script>
+description("This ensure we do not mess up the bytes when an URL is partially parsed and is invalid.")
+
+// Those are all invalid URLs. They should not be partially modified by the parser.
+var testSet = [
+    'foo://tête à tête@host/',
+    'foo://user:tête à tête@host/',
+    '    foo://<>@host/    ',
+    '    foo://user:<>@host/    ',
+    'foo://user:password@[xxxxx]/tête à tête/',
+    // The '?' is a path separator and make sure the hostname is not encoded in punicode. The hostname is an invalid IPV6 hostname.
+    'foo://user:password@[?tête à tête/',
+    'foo://user:password@[?tête à tête]/',
+    'foo://user:password@host:tête à tête/',
+    'foo://user:password@host:80tête à tête',
+    'foo://user:password@host:tête à tête/',
+    'foo://user:password@host:80tête à tête',
+    // The schemes "ws:", "ftp:", "http:", "https:", "gother:" take a shortcut during parsing so we test them separately.
+    'ws:/tête',
+    'ftp:/tête',
+    'http:/tête',
+    'https:/tête',
+    'gopher:/tête',
+];
+
+for (var i = 0; i < testSet.length; ++i) {
+    src = canonicalize(testSet[i]);
+       expected = testSet[i].trim();
+       shouldBe('src', 'expected');
+}
+
+successfullyParsed = true;
+</script>
+<script src="../js/resources/js-test-post.js"></script>
+</body>
+</html>
index 9a16ee3c3522c7ce974aa1b9c9a422ddff3e6ce6..d08dd8f77b59070075606bf03432dbfdc8cba5e9 100644 (file)
@@ -8,8 +8,8 @@ PASS canonicalize('http://www.example.com:-2/') is 'http://www.example.com:-2/'
 PASS canonicalize('http://www.example.com:80/') is 'http://www.example.com/'
 PASS canonicalize('http://www.example.com:8080/') is 'http://www.example.com:8080/'
 PASS canonicalize('http://www.example.com:/') is 'http://www.example.com/'
-FAIL canonicalize('http://www.example.com:፩/') should be http://www.example.com:%E1%8D%A9/. Was http://www.example.com:áÂ\8d©/.
-FAIL canonicalize('http://www.example.com:𝟖/') should be http://www.example.com:%F0%9D%9F%96/. Was http://www.example.com:ðÂ\9dÂ\9fÂ\96/.
+FAIL canonicalize('http://www.example.com:፩/') should be http://www.example.com:%E1%8D%A9/. Was http://www.example.com:á\8d©/.
+FAIL canonicalize('http://www.example.com:𝟖/') should be http://www.example.com:%F0%9D%9F%96/. Was http://www.example.com:ð\9d\9f\96/.
 PASS canonicalize('foobar://www.example.com:80/') is 'foobar://www.example.com:80/'
 PASS successfullyParsed is true
 
index 975e4a2e79fb42b4e5c896ed97b371082fd1f47e..02d72a709388ef696e763bd3b5d6ca7cb97c93b3 100644 (file)
@@ -1930,6 +1930,13 @@ BUGCR41206 : fast/history/multiple-classes-visited.html = TIMEOUT TEXT
 BUGCR41292 : fast/url/ipv4.html = TEXT
 BUGCR41292 : fast/url/anchor.html = TEXT
 
+BUGWK71758 : fast/url/invalid-urls-utf8.html = TEXT
+BUGWK71758 : fast/url/file.html = TEXT PASS
+BUGWK71758 : fast/url/file-http-base.html = TEXT PASS
+BUGWK71758 : fast/url/host.html = TEXT PASS
+BUGWK71758 : fast/url/idna2003.html = TEXT PASS
+BUGWK71758 : fast/url/port.html = TEXT PASS
+
 BUGWK33812 SKIP : fast/dom/icon-url-property.html = FAIL
 
 BUGCR42044 WIN : http/tests/security/xss-DENIED-mime-type-execute-as-html.html = PASS TIMEOUT
index e9319d4f564e5fdf1b5983ca4cd910939b77a05c..4e2fda69feaf5dc1c2128240b1fc2f14e1ea0e2f 100644 (file)
@@ -1,3 +1,21 @@
+2011-12-01  Benjamin Poulain  <benjamin@webkit.org>
+
+        URLs are encoded in UTF-8, then decoded as if they are Latin1
+        https://bugs.webkit.org/show_bug.cgi?id=71758
+
+        Reviewed by Darin Adler.
+
+        Add the operator == between a String and a Vector of char. The implementation
+        is the same as the comparison of String and char* but adds the length as a
+        parameter for comparing the strings.
+
+        * JavaScriptCore.exp:
+        * wtf/text/StringImpl.h:
+        (WTF::equal):
+        * wtf/text/WTFString.h:
+        (WTF::operator==):
+        (WTF::operator!=):
+
 2011-12-01  Martin Robinson  <mrobinson@igalia.com>
 
         [GTK] Read fonts from the jhbuild root
index 3715ab11ab766542f6a34d834b9ac1d783b9f5cc..5fa4fab92ffb6a0464571a7a7c96bf7e2e9f53db 100644 (file)
@@ -488,6 +488,7 @@ __ZN3WTF5Mutex7tryLockEv
 __ZN3WTF5MutexC1Ev
 __ZN3WTF5MutexD1Ev
 __ZN3WTF5equalEPKNS_10StringImplEPKh
+__ZN3WTF5equalEPKNS_10StringImplEPKhj
 __ZN3WTF5equalEPKNS_10StringImplEPKtj
 __ZN3WTF5equalEPKNS_10StringImplES2_
 __ZN3WTF5yieldEv
index 4fc69dbbe81d212ca9abd4a8bd1557d613075861..8e7c45543ba8c7d1f9cead749a23083fb540fa9a 100644 (file)
@@ -557,6 +557,7 @@ bool equal(const StringImpl*, const StringImpl*);
 bool equal(const StringImpl*, const LChar*);
 inline bool equal(const StringImpl* a, const char* b) { return equal(a, reinterpret_cast<const LChar*>(b)); }
 bool equal(const StringImpl*, const LChar*, unsigned);
+inline bool equal(const StringImpl* a, const char* b, unsigned length) { return equal(a, reinterpret_cast<const LChar*>(b), length); }
 inline bool equal(const LChar* a, StringImpl* b) { return equal(b, a); }
 inline bool equal(const char* a, StringImpl* b) { return equal(b, reinterpret_cast<const LChar*>(a)); }
 bool equal(const StringImpl*, const UChar*, unsigned);
index 68079e5aaa6fbac5d39f51a390d82ed37d85234b..58ce1264f033f8bcd36893c51633e26cfa37a099 100644 (file)
@@ -402,12 +402,21 @@ inline bool operator==(const String& a, const LChar* b) { return equal(a.impl(),
 inline bool operator==(const String& a, const char* b) { return equal(a.impl(), reinterpret_cast<const LChar*>(b)); }
 inline bool operator==(const LChar* a, const String& b) { return equal(a, b.impl()); }
 inline bool operator==(const char* a, const String& b) { return equal(reinterpret_cast<const LChar*>(a), b.impl()); }
+template<size_t inlineCapacity>
+inline bool operator==(const Vector<char, inlineCapacity>& a, const String& b) { return equal(b.impl(), a.data(), a.size()); }
+template<size_t inlineCapacity>
+inline bool operator==(const String& a, const Vector<char, inlineCapacity>& b) { return b == a; }
+
 
 inline bool operator!=(const String& a, const String& b) { return !equal(a.impl(), b.impl()); }
 inline bool operator!=(const String& a, const LChar* b) { return !equal(a.impl(), b); }
 inline bool operator!=(const String& a, const char* b) { return !equal(a.impl(), reinterpret_cast<const LChar*>(b)); }
 inline bool operator!=(const LChar* a, const String& b) { return !equal(a, b.impl()); }
 inline bool operator!=(const char* a, const String& b) { return !equal(reinterpret_cast<const LChar*>(a), b.impl()); }
+template<size_t inlineCapacity>
+inline bool operator!=(const Vector<char, inlineCapacity>& a, const String& b) { return !(a == b); }
+template<size_t inlineCapacity>
+inline bool operator!=(const String& a, const Vector<char, inlineCapacity>& b) { return b != a; }
 
 inline bool equalIgnoringCase(const String& a, const String& b) { return equalIgnoringCase(a.impl(), b.impl()); }
 inline bool equalIgnoringCase(const String& a, const LChar* b) { return equalIgnoringCase(a.impl(), b); }
index 8e0bd617b496acb486f12c24e97ce5fdc2104f63..0cdfe76a695c172fb2696afb057056024a6e2724 100644 (file)
@@ -1,3 +1,39 @@
+2011-12-01  Benjamin Poulain  <benjamin@webkit.org>
+
+        URLs are encoded in UTF-8, then decoded as if they are Latin1
+        https://bugs.webkit.org/show_bug.cgi?id=71758
+
+        Reviewed by Darin Adler.
+
+        Previously, invalid URLs could have a string emanating from a
+        partial parsing of the input. The creation of the string was done
+        through the Latin1 codec regardless of the encoding of the char* url.
+
+        This caused two types of issues, URLs were evaluated as half-parsed,
+        and the coding and decoding of the string was not consistent.
+
+        This patch changes KURL::parse() to fallback on the original string
+        whenever the parsing of the URL fails.
+
+        Test: fast/url/invalid-urls-utf8.html
+
+        * platform/KURL.cpp:
+        (WebCore::KURL::KURL):
+        (WebCore::KURL::init):
+        (WebCore::KURL::parse):
+        Previously, originalString was only used as an optimization to avoid
+        the allocation of a string. Since this optimization depends on the
+        comparison of the incoming string and the encoded buffer.
+        This patches generalizes originalString to always be the original string
+        being parsed by KURL. The optimization is kept by comparing that string
+        and the final parsed result.
+        * platform/KURL.h:
+        (WebCore::KURL::parse):
+        * platform/cf/KURLCFNet.cpp:
+        (WebCore::KURL::KURL):
+        * platform/mac/KURLMac.mm:
+        (WebCore::KURL::KURL):
+
 2011-12-01  Martin Robinson  <mrobinson@igalia.com>
 
         [GTK] Add a helper function to find the current executable's path
index e752bb8a46b50aae4b8ca8506ff748092a67d7df..7c8b1dbfbcb9daca511bdb9d675742dedaac2d32 100644 (file)
@@ -322,7 +322,7 @@ void KURL::invalidate()
 
 KURL::KURL(ParsedURLStringTag, const char* url)
 {
-    parse(url, 0);
+    parse(url);
     ASSERT(url == m_string);
 }
 
@@ -376,8 +376,6 @@ void KURL::init(const KURL& base, const String& relative, const TextEncoding& en
     if (rel.contains('\\') && !(protocolIsJavaScript(rel) || protocolIs(rel, "data")))
         rel = substituteBackslashes(rel);
 
-    String* originalString = &rel;
-
     bool allASCII = charactersAreAllASCII(rel.characters(), rel.length());
     CharBuffer strBuffer;
     char* str;
@@ -389,7 +387,6 @@ void KURL::init(const KURL& base, const String& relative, const TextEncoding& en
         strBuffer[len] = 0;
         str = strBuffer.data();
     } else {
-        originalString = 0;
         encodeRelativeString(rel, encoding, strBuffer);
         str = strBuffer.data();
         len = strlen(str);
@@ -397,16 +394,13 @@ void KURL::init(const KURL& base, const String& relative, const TextEncoding& en
 
     // Get rid of leading whitespace and control characters.
     while (len && shouldTrimFromURL(*str)) {
-        originalString = 0;
         str++;
         --len;
     }
 
     // Get rid of trailing whitespace and control characters.
-    while (len && shouldTrimFromURL(str[len - 1])) {
-        originalString = 0;
+    while (len && shouldTrimFromURL(str[len - 1]))
         str[--len] = '\0';
-    }
 
     // According to the RFC, the reference should be interpreted as an
     // absolute URI if possible, using the "leftmost, longest"
@@ -421,10 +415,9 @@ void KURL::init(const KURL& base, const String& relative, const TextEncoding& en
             ++p;
         }
         if (*p == ':') {
-            if (p[1] != '/' && equalIgnoringCase(base.protocol(), String(str, p - str)) && base.isHierarchical()) {
+            if (p[1] != '/' && equalIgnoringCase(base.protocol(), String(str, p - str)) && base.isHierarchical())
                 str = p + 1;
-                originalString = 0;
-            } else
+            else
                 absolute = true;
         }
     }
@@ -432,14 +425,14 @@ void KURL::init(const KURL& base, const String& relative, const TextEncoding& en
     CharBuffer parseBuffer;
 
     if (absolute) {
-        parse(str, originalString);
+        parse(str, relative);
     } else {
         // If the base is empty or opaque (e.g. data: or javascript:), then the URL is invalid
         // unless the relative URL is a single fragment.
         if (!base.isHierarchical()) {
             if (str[0] == '#') {
                 appendASCII(base.m_string.left(base.m_queryEnd), str, len, parseBuffer);
-                parse(parseBuffer.data(), 0);
+                parse(parseBuffer.data(), relative);
             } else {
                 m_string = relative;
                 invalidate();
@@ -456,13 +449,13 @@ void KURL::init(const KURL& base, const String& relative, const TextEncoding& en
         case '#': {
             // must be fragment-only reference
             appendASCII(base.m_string.left(base.m_queryEnd), str, len, parseBuffer);
-            parse(parseBuffer.data(), 0);
+            parse(parseBuffer.data(), relative);
             break;
         }
         case '?': {
             // query-only reference, special case needed for non-URL results
             appendASCII(base.m_string.left(base.m_pathEnd), str, len, parseBuffer);
-            parse(parseBuffer.data(), 0);
+            parse(parseBuffer.data(), relative);
             break;
         }
         case '/':
@@ -470,11 +463,11 @@ void KURL::init(const KURL& base, const String& relative, const TextEncoding& en
             if (str[1] == '/') {
                 // net-path
                 appendASCII(base.m_string.left(base.m_schemeEnd + 1), str, len, parseBuffer);
-                parse(parseBuffer.data(), 0);
+                parse(parseBuffer.data(), relative);
             } else {
                 // abs-path
                 appendASCII(base.m_string.left(base.m_portEnd), str, len, parseBuffer);
-                parse(parseBuffer.data(), 0);
+                parse(parseBuffer.data(), relative);
             }
             break;
         default:
@@ -551,7 +544,7 @@ void KURL::init(const KURL& base, const String& relative, const TextEncoding& en
                 // of the relative reference; this will also add a null terminator
                 strncpy(bufferPos, relStringPos, bufferSize - (bufferPos - bufferStart));
 
-                parse(parseBuffer.data(), 0);
+                parse(parseBuffer.data(), relative);
 
                 ASSERT(strlen(parseBuffer.data()) + 1 <= parseBuffer.size());
                 break;
@@ -1061,7 +1054,7 @@ void KURL::parse(const String& string)
     CharBuffer buffer(string.length() + 1);
     copyASCII(string.characters(), string.length(), buffer.data());
     buffer[string.length()] = '\0';
-    parse(buffer.data(), &string);
+    parse(buffer.data(), string);
 }
 
 static inline bool equal(const char* a, size_t lenA, const char* b, size_t lenB)
@@ -1118,18 +1111,18 @@ static bool isNonFileHierarchicalScheme(const char* scheme, size_t schemeLength)
     return false;
 }
 
-void KURL::parse(const char* url, const String* originalString)
+void KURL::parse(const char* url, const String& originalString)
 {
     if (!url || url[0] == '\0') {
         // valid URL must be non-empty
-        m_string = originalString ? *originalString : url;
+        m_string = !originalString.isNull() ? originalString : url;
         invalidate();
         return;
     }
 
     if (!isSchemeFirstChar(url[0])) {
         // scheme must start with an alphabetic character
-        m_string = originalString ? *originalString : url;
+        m_string = !originalString.isNull() ? originalString : url;
         invalidate();
         return;
     }
@@ -1139,7 +1132,7 @@ void KURL::parse(const char* url, const String* originalString)
         schemeEnd++;
 
     if (url[schemeEnd] != ':') {
-        m_string = originalString ? *originalString : url;
+        m_string = !originalString.isNull() ? originalString : url;
         invalidate();
         return;
     }
@@ -1205,7 +1198,7 @@ void KURL::parse(const char* url, const String* originalString)
             hostStart = userStart;
         } else {
             // invalid character
-            m_string = originalString ? *originalString : url;
+            m_string = !originalString.isNull() ? originalString : url;
             invalidate();
             return;
         }
@@ -1221,7 +1214,7 @@ void KURL::parse(const char* url, const String* originalString)
                 hostEnd++;
             else {
                 // invalid character
-                m_string = originalString ? *originalString : url;
+                m_string = !originalString.isNull() ? originalString : url;
                 invalidate();
                 return;
             }
@@ -1242,7 +1235,7 @@ void KURL::parse(const char* url, const String* originalString)
 
         if (!isPathSegmentEndChar(url[portEnd])) {
             // invalid character
-            m_string = originalString ? *originalString : url;
+            m_string = !originalString.isNull() ? originalString : url;
             invalidate();
             return;
         }
@@ -1417,11 +1410,12 @@ void KURL::parse(const char* url, const String* originalString)
     m_fragmentEnd = p - buffer.data();
 
     ASSERT(p - buffer.data() <= static_cast<int>(buffer.size()));
+    ASSERT(buffer.size() > 0);
 
     // If we didn't end up actually changing the original string and
     // it was already in a String, reuse it to avoid extra allocation.
-    if (originalString && originalString->length() == static_cast<unsigned>(m_fragmentEnd) && strncmp(buffer.data(), url, m_fragmentEnd) == 0)
-        m_string = *originalString;
+    if (originalString == buffer)
+        m_string = originalString;
     else
         m_string = String(buffer.data(), m_fragmentEnd);
 
index f6211804c07aec2b645a7ba656cb19dc85f4e976..8304f069283be38104cc625b3f1dd7e3072067f4 100644 (file)
@@ -236,6 +236,7 @@ private:
     static bool protocolIs(const String&, const char*);
 #if USE(GOOGLEURL)
     friend class KURLGooglePrivate;
+    void parse(const char* url, const String& originalString = String()) { parse(url, &originalString); };
     void parse(const char* url, const String* originalString);  // KURLMac calls this.
     void copyToBuffer(Vector<char, 512>& buffer) const;  // KURLCFNet uses this.
     KURLGooglePrivate m_url;
@@ -247,7 +248,7 @@ private:
     // optimization: When the source is the same as the fixed-up string,
     // it will use the passed-in string instead of allocating a new one.
     void parse(const String&);
-    void parse(const char* url, const String* originalString);
+    void parse(const char* url, const String& originalString = String());
 
     String m_string;
     bool m_isValid : 1;
index 8bf50e091ed1f6b6b6b5bc8f9bbdb67b023ddc34..d7912372044f4069d068b280f53f6e7c75f947e7 100644 (file)
@@ -40,7 +40,7 @@ CFURLRef createCFURLFromBuffer(const CharBuffer&);
 KURL::KURL(CFURLRef url)
 {
     if (!url) {
-        parse(0, 0);
+        parse(0);
         return;
     }
 
@@ -50,7 +50,7 @@ KURL::KURL(CFURLRef url)
     CFURLGetBytes(url, reinterpret_cast<UInt8*>(bytes), bytesLength);
     bytes[bytesLength] = '\0';
     if (bytes[0] != '/') {
-        parse(bytes, 0);
+        parse(bytes);
         return;
     }
 
@@ -60,7 +60,7 @@ KURL::KURL(CFURLRef url)
     buffer[3] = 'e';
     buffer[4] = ':';
 
-    parse(buffer.data(), 0);
+    parse(buffer.data());
 }
 
 CFURLRef createCFURLFromBuffer(const CharBuffer& buffer)
index 1a114bfcf3fffe41d50c6c2a6574d1259752416f..bc20f3828fc6391b8c9ce47633884278e8802f4c 100644 (file)
@@ -37,7 +37,7 @@ extern CFURLRef createCFURLFromBuffer(const CharBuffer& buffer);
 KURL::KURL(NSURL *url)
 {
     if (!url) {
-        parse(0, 0);
+        parse(0);
         return;
     }
 
@@ -47,7 +47,7 @@ KURL::KURL(NSURL *url)
     CFURLGetBytes(reinterpret_cast<CFURLRef>(url), reinterpret_cast<UInt8*>(bytes), bytesLength);
     bytes[bytesLength] = '\0';
     if (bytes[0] != '/') {
-        parse(bytes, 0);
+        parse(bytes);
         return;
     }
 
@@ -57,7 +57,7 @@ KURL::KURL(NSURL *url)
     buffer[3] = 'e';
     buffer[4] = ':';
 
-    parse(buffer.data(), 0);
+    parse(buffer.data());
 }
 
 KURL::operator NSURL *() const