<div dir="ltr"><div>Filip,<br><br></div>I see you are already addressing the atoi() checks. Thus I'll wait to include that in my patch series.<br><div class="gmail_extra">The other issue ipv6-bracket-check has been addressed.<br><br></div><div class="gmail_extra">From 5d0298b9983247cc9f2f2ebca538c466b0fdf718 Mon Sep 17 00:00:00 2001<br>From: Jean-Paul Saman <<a href="mailto:jpsaman@videolan.org">jpsaman@videolan.org</a>><br>Date: Fri, 21 Oct 2016 14:29:49 +0200<br>Subject: [PATCH 1/3] vlc_url: parse '@[bindhost]:[bindport]' in<br> '[serveraddr[:serverport]][@[bindaddr]:[bindport]]'<br><br>---<br> include/vlc_url.h |   2 ++<br> src/text/url.c    | 100 +++++++++++++++++++++++++++++++++++++++---------------<br> 2 files changed, 75 insertions(+), 27 deletions(-)<br><br>diff --git a/include/vlc_url.h b/include/vlc_url.h<br>index 5a20c27..802227e 100644<br>--- a/include/vlc_url.h<br>+++ b/include/vlc_url.h<br>@@ -149,6 +149,8 @@ struct vlc_url_t<br>     char *psz_password;<br>     char *psz_host;<br>     unsigned i_port;<br>+    char *psz_bind_host;<br>+    unsigned i_bind_port;<br>     char *psz_path;<br>     char *psz_option;<br> <br>diff --git a/src/text/url.c b/src/text/url.c<br>index 6116893..3a95bb9 100644<br>--- a/src/text/url.c<br>+++ b/src/text/url.c<br>@@ -400,6 +400,33 @@ static bool vlc_uri_path_validate(const char *str)<br>     return vlc_uri_component_validate(str, "/@:");<br> }<br> <br>+static char *vlc_uri_host_get(char *str, char **saveptr)<br>+{<br>+    char *host = NULL;<br>+    char *next;<br>+<br>+    if (*str == '[' && (next = strchr(str, ']')) != NULL)<br>+    {   /* Try IPv6 numeral within brackets */<br>+        *(next++) = '\0';<br>+        host = strdup(str + 1);<br>+<br>+        if (*next == ':')<br>+            next++;<br>+        else<br>+            next = NULL;<br>+    }<br>+    else<br>+    {<br>+        next = strchr(str, ':');<br>+        if (next != NULL)<br>+            *(next++) = '\0';<br>+<br>+        host = vlc_idna_to_ascii(vlc_uri_decode(str));<br>+    }<br>+    *saveptr = next;<br>+    return host;<br>+}<br>+<br> int vlc_UrlParse(vlc_url_t *restrict url, const char *str)<br> {<br>     url->psz_protocol = NULL;<br>@@ -407,6 +434,8 @@ int vlc_UrlParse(vlc_url_t *restrict url, const char *str)<br>     url->psz_password = NULL;<br>     url->psz_host = NULL;<br>     url->i_port = 0;<br>+    url->psz_bind_host = NULL;<br>+    url->i_bind_port = 0;<br>     url->psz_path = NULL;<br>     url->psz_option = NULL;<br>     url->psz_buffer = NULL;<br>@@ -473,45 +502,61 @@ int vlc_UrlParse(vlc_url_t *restrict url, const char *str)<br>         /*else<br>             url->psz_path = "/";*/<br> <br>-        /* User name */<br>-        next = strrchr(cur, '@');<br>-        if (next != NULL)<br>+        if (url->psz_protocol && (strcmp(url->psz_protocol, "udp") == 0))<br>         {<br>-            *(next++) = '\0';<br>-            url->psz_username = cur;<br>-            cur = next;<br>-<br>-            /* Password (obsolete) */<br>-            next = strchr(url->psz_username, ':');<br>+            /*<br>+             * Parse udp syntax:<br>+             * [serveraddr[:serverport]][@[bindaddr]:[bindport]]<br>+             */<br>+            next = strchr(cur, '@');<br>             if (next != NULL)<br>             {<br>                 *(next++) = '\0';<br>-                url->psz_password = next;<br>-                vlc_uri_decode(url->psz_password);<br>+                char *psz_bindhost = strdup(next);<br>+                url->psz_bind_host = vlc_uri_host_get(psz_bindhost, &next);<br>+<br>+                if (url->psz_bind_host == NULL)<br>+                    ret = -1;<br>+                else<br>+                    if (!vlc_uri_host_validate(url->psz_bind_host))<br>+                    {<br>+                        free(url->psz_bind_host);<br>+                        url->psz_bind_host = NULL;<br>+                        errno = EINVAL;<br>+                        ret = -1;<br>+                    }<br>+                /* Port number */<br>+                if (next != NULL)<br>+                    url->i_bind_port = atoi(next);<br>+<br>+                free(psz_bindhost);<br>             }<br>-            vlc_uri_decode(url->psz_username);<br>-        }<br>-<br>-        /* Host name */<br>-        if (*cur == '[' && (next = strrchr(cur, ']')) != NULL)<br>-        {   /* Try IPv6 numeral within brackets */<br>-            *(next++) = '\0';<br>-            url->psz_host = strdup(cur + 1);<br>-<br>-            if (*next == ':')<br>-                next++;<br>-            else<br>-                next = NULL;<br>         }<br>         else<br>         {<br>-            next = strchr(cur, ':');<br>+            /* User name */<br>+            next = strrchr(cur, '@');<br>             if (next != NULL)<br>+            {<br>                 *(next++) = '\0';<br>-<br>-            url->psz_host = vlc_idna_to_ascii(vlc_uri_decode(cur));<br>+                url->psz_username = cur;<br>+                cur = next;<br>+<br>+                /* Password (obsolete) */<br>+                next = strchr(url->psz_username, ':');<br>+                if (next != NULL)<br>+                {<br>+                    *(next++) = '\0';<br>+                    url->psz_password = next;<br>+                    vlc_uri_decode(url->psz_password);<br>+                }<br>+                vlc_uri_decode(url->psz_username);<br>+            }<br>         }<br> <br>+        /* Host name */<br>+        url->psz_host = vlc_uri_host_get(cur, &next);<br>+<br>         if (url->psz_host == NULL)<br>             ret = -1;<br>         else<br>@@ -547,6 +592,7 @@ int vlc_UrlParse(vlc_url_t *restrict url, const char *str)<br> <br> void vlc_UrlClean (vlc_url_t *restrict url)<br> {<br>+    free (url->psz_bind_host);<br>     free (url->psz_host);<br>     free (url->psz_buffer);<br> }<br>-- <br>2.7.4<br><br></div></div>