Sophie

Sophie

distrib > Mageia > 5 > x86_64 > media > core-updates-src > by-pkgid > f3481c115b42490069a02f2faa8f70d6 > files > 5

libupnp-1.6.19-4.1.mga5.src.rpm

http://sourceforge.net/p/pupnp/code/ci/ef6a6df0b0d215f7659390e7b67f8759c5c6a49f/

Fix resolve_rel_url()

This reworks commit 0edaf3361db01425cae0daee7dc3f6039f381a17, which
broke resolving relative url, where the relative URL is shorter than the
absolute URL:
"http://127.0.0.1:6544/getDeviceDesc" + "CDS_Event"
Wrong: "http://127.0.0.1:6544/CDS_EventDesc"
Right: "http://127.0.0.1:6544/CDS_Event"

While reviewing that commit, improve code by:
1. Move the simple cases to the beginning of the function.
2. Keep track of the remaining target buffer size.
3. Fix URI concatenation with queries.
4. Fix URI concatenation with fragments.

Signed-off-by: Marcelo Roberto Jimenez <mroberto@users.sourceforge.net>
(cherry picked from commit 0508fb0d6e55a9066f3722843aa782632d302276)

--- a/upnp/src/genlib/net/uri/uri.c
+++ b/upnp/src/genlib/net/uri/uri.c
@@ -581,115 +581,113 @@
 {
     uri_type base;
     uri_type rel;
-
-    size_t i = (size_t)0;
-    char *finger = NULL;
-
-    char *last_slash = NULL;
-
-    char *out = NULL;
-
-    if( base_url && rel_url ) {
-        out =
-            ( char * )malloc( strlen( base_url ) + strlen( rel_url ) + (size_t)2 );
+    int rv;
+
+    if (!base_url) {
+        if (!rel_url)
+            return NULL;
+        return strdup(rel_url);
+    }
+
+    size_t len_rel = strlen(rel_url);
+    if (parse_uri(rel_url, len_rel, &rel) != HTTP_SUCCESS)
+        return NULL;
+    if (rel.type == (enum uriType)ABSOLUTE)
+        return strdup(rel_url);
+
+    size_t len_base = strlen(base_url);
+    if ((parse_uri(base_url, len_base, &base) != HTTP_SUCCESS)
+            || (base.type != (enum uriType)ABSOLUTE))
+        return NULL;
+    if (len_rel == (size_t)0)
+        return strdup(base_url);
+
+    size_t len = len_base + len_rel + (size_t)2;
+    char *out = (char *)malloc(len);
+    if (out == NULL)
+        return NULL;
+    memset(out, 0, len);
+    char *out_finger = out;
+
+    /* scheme */
+    rv = snprintf(out_finger, len, "%.*s:", (int)base.scheme.size, base.scheme.buff);
+    if (rv < 0 || rv >= len)
+        goto error;
+    out_finger += rv;
+    len -= rv;
+
+    /* authority */
+    if (rel.hostport.text.size > (size_t)0) {
+        rv = snprintf(out_finger, len, "%s", rel_url);
+        if (rv < 0 || rv >= len)
+            goto error;
+        return out;
+    }
+    if (base.hostport.text.size > (size_t)0) {
+	rv = snprintf(out_finger, len, "//%.*s", (int)base.hostport.text.size, base.hostport.text.buff);
+	if (rv < 0 || rv >= len)
+	    goto error;
+	out_finger += rv;
+	len -= rv;
+    }
+
+    /* path */
+    char *path = out_finger;
+    if (rel.path_type == (enum pathType)ABS_PATH) {
+	rv = snprintf(out_finger, len, "%s", rel_url);
+    } else if (base.pathquery.size == (size_t)0) {
+	rv = snprintf(out_finger, len, "/%s", rel_url);
     } else {
-        if( rel_url )
-            return strdup( rel_url );
-        else
-            return NULL;
-    }
-
-    if( out == NULL ) {
-        return NULL;
-    }
-    memset( out, 0, strlen( base_url ) + strlen( rel_url ) + (size_t)2 );
-
-    if( ( parse_uri( rel_url, strlen( rel_url ), &rel ) ) == HTTP_SUCCESS ) {
-
-        if( rel.type == ( enum uriType) ABSOLUTE ) {
-
-            strncpy( out, rel_url, strlen ( rel_url ) );
-        } else {
-
-            if( ( parse_uri( base_url, strlen( base_url ), &base ) ==
-                  HTTP_SUCCESS )
-                && ( base.type == ( enum uriType ) ABSOLUTE ) ) {
-
-                if( strlen( rel_url ) == (size_t)0 ) {
-                    strncpy( out, base_url, strlen ( base_url ) );
-                } else {
-                    char *out_finger = out;
-                    assert( base.scheme.size + (size_t)1 /* ':' */ <= strlen ( base_url ) );
-                    memcpy( out, base.scheme.buff, base.scheme.size );
-                    out_finger += base.scheme.size;
-                    ( *out_finger ) = ':';
-                    out_finger++;
-
-                    if( rel.hostport.text.size > (size_t)0 ) {
-                        snprintf( out_finger, strlen( rel_url ) + (size_t)1,
-                                  "%s", rel_url );
-                    } else {
-                        if( base.hostport.text.size > (size_t)0 ) {
-                            assert( base.scheme.size + (size_t)1
-                                + base.hostport.text.size + (size_t)2 /* "//" */ <= strlen ( base_url ) );
-                            memcpy( out_finger, "//", (size_t)2 );
-                            out_finger += 2;
-                            memcpy( out_finger, base.hostport.text.buff,
-                                    base.hostport.text.size );
-                            out_finger += base.hostport.text.size;
-                        }
-
-                        if( rel.path_type == ( enum pathType ) ABS_PATH ) {
-                            strncpy( out_finger, rel_url, strlen ( rel_url ) );
-
-                        } else {
-                            char temp_path = '/';
-
-                            if( base.pathquery.size == (size_t)0 ) {
-                                base.pathquery.size = (size_t)1;
-                                base.pathquery.buff = &temp_path;
-                            }
-
-                            assert( base.scheme.size + (size_t)1 + base.hostport.text.size + (size_t)2
-                                + base.pathquery.size <= strlen ( base_url ) + (size_t)1 /* temp_path */);
-                            finger = out_finger;
-                            last_slash = finger;
-                            i = (size_t)0;
-                            while( ( i < base.pathquery.size ) &&
-                                   ( base.pathquery.buff[i] != '?' ) ) {
-                                ( *finger ) = base.pathquery.buff[i];
-                                if( base.pathquery.buff[i] == '/' )
-                                    last_slash = finger + 1;
-                                i++;
-                                finger++;
-
-                            }
-                            strncpy( last_slash, rel_url, strlen ( rel_url ) );
-                            if( remove_dots( out_finger,
-                                             strlen( out_finger ) ) !=
-                                UPNP_E_SUCCESS ) {
-                                free(out);
-                                /* free(rel_url); */
-                                return NULL;
-                            }
-                        }
-
-                    }
-                }
-            } else {
-                free(out);
-                /* free(rel_url); */
-                return NULL;
-            }
-        }
-    } else {
-        free(out);
-        /* free(rel_url); */          
-        return NULL;
-    }
-
-    /* free(rel_url); */
+	if (rel.pathquery.size == (size_t)0) {
+	    rv = snprintf(out_finger, len, "%.*s", (int)base.pathquery.size, base.pathquery.buff);
+	} else {
+	    if (len < base.pathquery.size)
+		goto error;
+	    size_t i = (size_t)0, prefix = (size_t)1;
+	    while (i < base.pathquery.size) {
+		out_finger[i] = base.pathquery.buff[i];
+		switch (base.pathquery.buff[i++]) {
+		    case '/':
+			prefix = i;
+			/* fall-through */
+		    default:
+			continue;
+		    case '?': /* query */
+			if (rel.pathquery.buff[0] == '?')
+			    prefix = --i;
+		}
+		break;
+	    }
+	    out_finger += prefix;
+	    len -= prefix;
+	    rv = snprintf(out_finger, len, "%.*s", (int)rel.pathquery.size, rel.pathquery.buff);
+	}
+	if (rv < 0 || rv >= len)
+	    goto error;
+	out_finger += rv;
+	len -= rv;
+
+	/* fragment */
+	if (rel.fragment.size > (size_t)0)
+	    rv = snprintf(out_finger, len, "#%.*s", (int)rel.fragment.size, rel.fragment.buff);
+	else if (base.fragment.size > (size_t)0)
+	    rv = snprintf(out_finger, len, "#%.*s", (int)base.fragment.size, base.fragment.buff);
+	else
+	    rv = 0;
+    }
+    if (rv < 0 || rv >= len)
+	goto error;
+    out_finger += rv;
+    len -= rv;
+
+    if (remove_dots(path, out_finger - path) != UPNP_E_SUCCESS)
+	goto error;
+
     return out;
+
+error:
+    free(out);
+    return NULL;
 }