Thomas Mullaly : urlmon: Implemented validation of the host name component of a IUriBuilder.

Alexandre Julliard julliard at winehq.org
Tue Sep 28 11:13:31 CDT 2010


Module: wine
Branch: master
Commit: 63723845c4529b12b4c161450937212c92cb33cb
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=63723845c4529b12b4c161450937212c92cb33cb

Author: Thomas Mullaly <thomas.mullaly at gmail.com>
Date:   Mon Sep 20 22:45:57 2010 -0400

urlmon: Implemented validation of the host name component of a IUriBuilder.

---

 dlls/urlmon/tests/uri.c |   61 +++++++++++++++++++++++++++++++-
 dlls/urlmon/uri.c       |   89 ++++++++++++++++++++++++++++++++++++-----------
 2 files changed, 128 insertions(+), 22 deletions(-)

diff --git a/dlls/urlmon/tests/uri.c b/dlls/urlmon/tests/uri.c
index b2e265e..a32f889 100644
--- a/dlls/urlmon/tests/uri.c
+++ b/dlls/urlmon/tests/uri.c
@@ -4823,7 +4823,6 @@ static const uri_builder_test uri_builder_tests[] = {
         {
             {FALSE},
         },
-
         {TRUE,TRUE,999999,S_OK,FALSE},
         0,S_OK,TRUE,
         0,S_OK,TRUE,
@@ -5236,6 +5235,66 @@ static const uri_builder_test uri_builder_tests[] = {
         0,INET_E_INVALID_URL,FALSE,
         0,INET_E_INVALID_URL,FALSE,
         0,0,0,INET_E_INVALID_URL,FALSE
+    },
+    {   "http://google.com/",0,S_OK,FALSE,
+        {
+            {TRUE,"winehq.org/test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
+        },
+        {FALSE},
+        0,INET_E_INVALID_URL,FALSE,
+        0,INET_E_INVALID_URL,FALSE,
+        0,0,0,INET_E_INVALID_URL,FALSE
+    },
+    {   "http://google.com/",0,S_OK,FALSE,
+        {
+            {TRUE,"winehq.org?test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
+        },
+        {FALSE},
+        0,INET_E_INVALID_URL,FALSE,
+        0,INET_E_INVALID_URL,FALSE,
+        0,0,0,INET_E_INVALID_URL,FALSE
+    },
+    {   "http://google.com/",0,S_OK,FALSE,
+        {
+            {TRUE,"winehq.org#test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
+        },
+        {FALSE},
+        0,INET_E_INVALID_URL,FALSE,
+        0,INET_E_INVALID_URL,FALSE,
+        0,0,0,INET_E_INVALID_URL,FALSE
+    },
+    /* Hostname is allowed to contain a ':' (even for known scheme types). */
+    {   "http://google.com/",0,S_OK,FALSE,
+        {
+            {TRUE,"winehq.org:test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE},
+        },
+        {FALSE},
+        0,S_OK,TRUE,
+        0,S_OK,TRUE,
+        0,0,0,S_OK,TRUE,
+        {
+            {"http://winehq.org:test/",S_OK},
+            {"winehq.org:test",S_OK},
+            {"http://winehq.org:test/",S_OK},
+            {"winehq.org:test",S_OK},
+            {"",S_FALSE},
+            {"",S_FALSE},
+            {"winehq.org:test",S_OK},
+            {"",S_FALSE},
+            {"/",S_OK},
+            {"/",S_OK},
+            {"",S_FALSE},
+            {"http://winehq.org:test/",S_OK},
+            {"http",S_OK},
+            {"",S_FALSE},
+            {"",S_FALSE}
+        },
+        {
+            {Uri_HOST_DNS,S_OK},
+            {80,S_OK},
+            {URL_SCHEME_HTTP,S_OK},
+            {URLZONE_INVALID,E_NOTIMPL}
+        }
     }
 };
 
diff --git a/dlls/urlmon/uri.c b/dlls/urlmon/uri.c
index eaf8c83..c6570d6 100644
--- a/dlls/urlmon/uri.c
+++ b/dlls/urlmon/uri.c
@@ -26,9 +26,12 @@
 #define UINT_MAX 0xffffffff
 #define USHORT_MAX 0xffff
 
-#define ALLOW_NULL_TERM_SCHEME      0x1
-#define ALLOW_NULL_TERM_USER_NAME   0x2
-#define ALLOW_NULL_TERM_PASSWORD    0x4
+#define ALLOW_NULL_TERM_SCHEME          0x01
+#define ALLOW_NULL_TERM_USER_NAME       0x02
+#define ALLOW_NULL_TERM_PASSWORD        0x04
+#define ALLOW_BRACKETLESS_IP_LITERAL    0x08
+#define SKIP_IP_FUTURE_CHECK            0x10
+#define IGNORE_PORT_DELIMITER           0x20
 
 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
 
@@ -1516,11 +1519,11 @@ static BOOL parse_ipv4address(const WCHAR **ptr, parse_data *data, DWORD flags)
  *
  *  A reg-name CAN be empty.
  */
-static BOOL parse_reg_name(const WCHAR **ptr, parse_data *data, DWORD flags) {
+static BOOL parse_reg_name(const WCHAR **ptr, parse_data *data, DWORD flags, DWORD extras) {
     const BOOL has_start_bracket = **ptr == '[';
     const BOOL known_scheme = data->scheme_type != URL_SCHEME_UNKNOWN;
     BOOL inside_brackets = has_start_bracket;
-    BOOL ignore_col = FALSE;
+    BOOL ignore_col = extras & IGNORE_PORT_DELIMITER;
 
     /* We have to be careful with file schemes. */
     if(data->scheme_type == URL_SCHEME_FILE) {
@@ -1554,7 +1557,7 @@ static BOOL parse_reg_name(const WCHAR **ptr, parse_data *data, DWORD flags) {
                     if(data->scheme_type != URL_SCHEME_UNKNOWN) {
                         *ptr = data->host;
                         data->host = NULL;
-                        TRACE("(%p %p %x): Expected valid port\n", ptr, data, flags);
+                        TRACE("(%p %p %x %x): Expected valid port\n", ptr, data, flags, extras);
                         return FALSE;
                     } else
                         /* Windows gives up on trying to parse a port when it
@@ -1585,8 +1588,8 @@ static BOOL parse_reg_name(const WCHAR **ptr, parse_data *data, DWORD flags) {
     if(has_start_bracket) {
         /* Make sure the last character of the host wasn't a ']'. */
         if(*(*ptr-1) == ']') {
-            TRACE("(%p %p %x): Expected an IP literal inside of the host\n",
-                ptr, data, flags);
+            TRACE("(%p %p %x %x): Expected an IP literal inside of the host\n",
+                ptr, data, flags, extras);
             *ptr = data->host;
             data->host = NULL;
             return FALSE;
@@ -1603,7 +1606,7 @@ static BOOL parse_reg_name(const WCHAR **ptr, parse_data *data, DWORD flags) {
     else
         data->host_type = Uri_HOST_DNS;
 
-    TRACE("(%p %p %x): Parsed reg-name. host=%s len=%d\n", ptr, data, flags,
+    TRACE("(%p %p %x %x): Parsed reg-name. host=%s len=%d\n", ptr, data, flags, extras,
         debugstr_wn(data->host, data->host_len), data->host_len);
     return TRUE;
 }
@@ -1816,27 +1819,33 @@ static BOOL parse_ipvfuture(const WCHAR **ptr, parse_data *data, DWORD flags) {
 }
 
 /* IP-literal = "[" ( IPv6address / IPvFuture  ) "]" */
-static BOOL parse_ip_literal(const WCHAR **ptr, parse_data *data, DWORD flags) {
+static BOOL parse_ip_literal(const WCHAR **ptr, parse_data *data, DWORD flags, DWORD extras) {
     data->host = *ptr;
 
-    if(**ptr != '[') {
+    if(**ptr != '[' && !(extras & ALLOW_BRACKETLESS_IP_LITERAL)) {
         data->host = NULL;
         return FALSE;
-    }
+    } else if(**ptr == '[')
+        ++(*ptr);
 
-    ++(*ptr);
     if(!parse_ipv6address(ptr, data, flags)) {
-        if(!parse_ipvfuture(ptr, data, flags)) {
+        if(extras & SKIP_IP_FUTURE_CHECK || !parse_ipvfuture(ptr, data, flags)) {
             *ptr = data->host;
             data->host = NULL;
             return FALSE;
         }
     }
 
-    if(**ptr != ']') {
+    if(**ptr != ']' && !(extras & ALLOW_BRACKETLESS_IP_LITERAL)) {
         *ptr = data->host;
         data->host = NULL;
         return FALSE;
+    } else if(!**ptr && extras & ALLOW_BRACKETLESS_IP_LITERAL) {
+        /* The IP literal didn't contain brackets and was followed by
+         * a NULL terminator, so no reason to even check the port.
+         */
+        data->host_len = *ptr - data->host;
+        return TRUE;
     }
 
     ++(*ptr);
@@ -1860,12 +1869,12 @@ static BOOL parse_ip_literal(const WCHAR **ptr, parse_data *data, DWORD flags) {
  *
  * host = IP-literal / IPv4address / reg-name
  */
-static BOOL parse_host(const WCHAR **ptr, parse_data *data, DWORD flags) {
-    if(!parse_ip_literal(ptr, data, flags)) {
+static BOOL parse_host(const WCHAR **ptr, parse_data *data, DWORD flags, DWORD extras) {
+    if(!parse_ip_literal(ptr, data, flags, extras)) {
         if(!parse_ipv4address(ptr, data, flags)) {
-            if(!parse_reg_name(ptr, data, flags)) {
-                TRACE("(%p %p %x): Malformed URI, Unknown host type.\n",
-                    ptr, data, flags);
+            if(!parse_reg_name(ptr, data, flags, extras)) {
+                TRACE("(%p %p %x %x): Malformed URI, Unknown host type.\n",
+                    ptr, data, flags, extras);
                 return FALSE;
             }
         }
@@ -1884,7 +1893,7 @@ static BOOL parse_authority(const WCHAR **ptr, parse_data *data, DWORD flags) {
     /* Parsing the port will happen during one of the host parsing
      * routines (if the URI has a port).
      */
-    if(!parse_host(ptr, data, flags))
+    if(!parse_host(ptr, data, flags, 0))
         return FALSE;
 
     return TRUE;
@@ -3651,6 +3660,37 @@ static HRESULT validate_userinfo(const UriBuilder *builder, parse_data *data, DW
     return S_OK;
 }
 
+static HRESULT validate_host(const UriBuilder *builder, parse_data *data, DWORD flags) {
+    const WCHAR *ptr;
+    const WCHAR **pptr;
+    DWORD expected_len;
+
+    if(builder->host) {
+        ptr = builder->host;
+        expected_len = builder->host_len;
+    } else if(!(builder->modified_props & Uri_HAS_HOST) && builder->uri && builder->uri->host_start > -1) {
+        ptr = builder->uri->canon_uri + builder->uri->host_start;
+        expected_len = builder->uri->host_len;
+    } else
+        ptr = NULL;
+
+    if(ptr) {
+        DWORD extras = ALLOW_BRACKETLESS_IP_LITERAL|IGNORE_PORT_DELIMITER|SKIP_IP_FUTURE_CHECK;
+        pptr = &ptr;
+
+        if(parse_host(pptr, data, flags, extras) && data->host_len == expected_len)
+            TRACE("(%p %p %x): Found valid host name %s len=%d type=%d.\n", builder, data, flags,
+                debugstr_wn(data->host, data->host_len), data->host_len, data->host_type);
+        else {
+            TRACE("(%p %p %x): Invalid host name found %s expected_len=%d.\n", builder, data, flags,
+                debugstr_wn(ptr, expected_len), expected_len);
+            return INET_E_INVALID_URL;
+        }
+    }
+
+    return S_OK;
+}
+
 static HRESULT validate_components(const UriBuilder *builder, parse_data *data, DWORD flags) {
     HRESULT hr;
 
@@ -3676,6 +3716,13 @@ static HRESULT validate_components(const UriBuilder *builder, parse_data *data,
     if(FAILED(hr))
         return hr;
 
+    hr = validate_host(builder, data, flags);
+    if(FAILED(hr))
+        return hr;
+
+    /* The URI is opaque if it doesn't have an authority component. */
+    data->is_opaque = !data->username && !data->password && !data->host;
+
     return E_NOTIMPL;
 }
 




More information about the wine-cvs mailing list