[vlc-commits] url: validate host name and path

Rémi Denis-Courmont git at videolan.org
Wed Mar 9 06:04:37 CET 2016


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Wed Mar  9 07:03:08 2016 +0200| [99d97efbc94b5beca38fcedc07e8f961ed8d1f1f] | committer: Rémi Denis-Courmont

url: validate host name and path

This avoids passing embedding unexpected garbage into network requests,
leading to weird errors, or in the worst cases, injection (e.g. white
spaces in HTTP/1.x requests).

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=99d97efbc94b5beca38fcedc07e8f961ed8d1f1f
---

 src/text/url.c |   54 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 53 insertions(+), 1 deletion(-)

diff --git a/src/text/url.c b/src/text/url.c
index b9ed274..0a48ad1 100644
--- a/src/text/url.c
+++ b/src/text/url.c
@@ -72,7 +72,7 @@ char *vlc_uri_decode (char *str)
     return str;
 }
 
-static inline bool isurisafe (int c)
+static bool isurisafe (int c)
 {
     /* These are the _unreserved_ URI characters (RFC3986 §2.3) */
     return ((unsigned char)(c - 'a') < 26)
@@ -81,6 +81,18 @@ static inline bool isurisafe (int c)
         || (strchr ("-._~", c) != NULL);
 }
 
+static bool isurisubdelim(int c)
+{
+    return strchr("!$&'()*+,;=", c) != NULL;
+}
+
+static bool isurihex(int c)
+{   /* Same as isxdigit() but does not depend on locale and unsignedness */
+    return ((unsigned char)(c - '0') < 10)
+        || ((unsigned char)(c - 'A') < 6)
+        || ((unsigned char)(c - 'a') < 6);
+}
+
 static char *encode_URI_bytes (const char *str, size_t *restrict lenp)
 {
     char *buf = malloc (3 * *lenp + 1);
@@ -309,6 +321,39 @@ out:
 
 static char *vlc_idna_to_ascii (const char *);
 
+static bool vlc_uri_component_validate(const char *str, const char *extras)
+{
+    if (str == NULL)
+        return false;
+
+    for (size_t i = 0; str[i] != '\0'; i++)
+    {
+        int c = str[i];
+
+        if (isurisafe(c) || isurisubdelim(c))
+            continue;
+        if (strchr(extras, c) != NULL)
+            continue;
+        if (c == '%' && isurihex(str[i + 1]) && isurihex(str[i + 2]))
+        {
+            i += 2;
+            continue;
+        }
+        return false;
+    }
+    return true;
+}
+
+static bool vlc_uri_host_validate(const char *str)
+{
+    return vlc_uri_component_validate(str, "");
+}
+
+static bool vlc_uri_path_validate(const char *str)
+{
+    return vlc_uri_component_validate(str, "/@:");
+}
+
 /**
  * Splits an URL into parts.
  * \param url structure of URL parts [OUT]
@@ -412,6 +457,11 @@ void vlc_UrlParse (vlc_url_t *restrict url, const char *str)
 
         url->psz_host = vlc_idna_to_ascii (cur);
     }
+    if (!vlc_uri_host_validate(url->psz_host))
+    {
+        free(url->psz_host);
+        url->psz_host = NULL;
+    }
 
     /* Port number */
     if (next != NULL)
@@ -419,6 +469,8 @@ void vlc_UrlParse (vlc_url_t *restrict url, const char *str)
 
     if (url->psz_path != NULL)
         *url->psz_path = '/'; /* restore leading slash */
+    if (!vlc_uri_path_validate(url->psz_path))
+        url->psz_path = NULL;
 }
 
 /**



More information about the vlc-commits mailing list