Sophie

Sophie

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

libupnp-1.6.19-4.1.mga5.src.rpm

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

Fix remove_dots()

Rewrite to handle all normal and abnormal examples mentioned in RFC 3986
section 5.4.
The previous implementation failed the following test cases:

'http://www.libupnp.org/path1/path1' | '#frag1' -> 'http://www.libupnp.org/path1/#frag1' != 'http://www.libupnp.org/path1/path1#frag1' (0)
'http://127.0.0.1:6544/getDeviceDesc' | 'CDS_Event' -> 'http://127.0.0.1:6544/CDS_EventDesc' != 'http://127.0.0.1:6544/CDS_Event' (0)
'http://localhost/b/c/d;p?q' | 'g' -> 'http://localhost/b/c/g;p' != 'http://localhost/b/c/g' (0)
'http://localhost/b/c/d;p?q' | 'g/' -> 'http://localhost/b/c/g/p' != 'http://localhost/b/c/g/' (0)
'http://localhost/b/c/d;p?q' | '?y' -> 'http://localhost/b/c/?yp' != 'http://localhost/b/c/d;p?y' (0)
'http://localhost/b/c/d;p?q' | '#s' -> 'http://localhost/b/c/#sp' != 'http://localhost/b/c/d;p?q#s' (0)
'http://localhost/b/c/d;p?q' | ';x' -> 'http://localhost/b/c/;xp' != 'http://localhost/b/c/;x' (0)
'http://localhost/b/c/d;p?q' | '.' -> 'http://localhost/b/c/.;p' != 'http://localhost/b/c/' (0)
'http://localhost/b/c/d;p?q' | './' -> 'http://localhost/b/c/p' != 'http://localhost/b/c/' (0)
'http://localhost/b/c/d;p?q' | '..' -> 'http://localhost/b/c/..p' != 'http://localhost/b/' (0)
'http://localhost/b/c/d;p?q' | '/./g' -> 'http://localhost/./g' != 'http://localhost/g' (0)
'http://localhost/b/c/d;p?q' | '/../g' -> 'http://localhost/../g' != 'http://localhost/g' (0)
'http://localhost/b/c/d;p?q' | 'g.' -> 'http://localhost/b/c/g.p' != 'http://localhost/b/c/g.' (0)
'http://localhost/b/c/d;p?q' | '.g' -> 'http://localhost/b/c/.gp' != 'http://localhost/b/c/.g' (0)

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

--- a/upnp/src/genlib/net/uri/uri.c
+++ b/upnp/src/genlib/net/uri/uri.c
@@ -511,68 +511,81 @@
 }
 
 
-int remove_dots(char *in, size_t size)
-{
-    char *copyTo = in;
-    char *copyFrom = in;
-    char *max = in + size;
-    char **Segments = NULL;
-    int lastSegment = -1;
-
-    Segments = malloc( sizeof( char * ) * size );
-
-    if( Segments == NULL )
-        return UPNP_E_OUTOF_MEMORY;
-
-    Segments[0] = NULL;
-    UpnpPrintf( UPNP_ALL, API, __FILE__, __LINE__,
-        "REMOVE_DOTS: before: %s\n", in );
-    while( ( copyFrom < max ) && ( *copyFrom != '?' )
-           && ( *copyFrom != '#' ) ) {
-
-        if( ( ( *copyFrom ) == '.' )
-            && ( ( copyFrom == in ) || ( *( copyFrom - 1 ) == '/' ) ) ) {
-            if( ( copyFrom + 1 == max )
-                || ( *( copyFrom + 1 ) == '/' ) ) {
-
-                copyFrom += 2;
-                continue;
-            } else if( ( *( copyFrom + 1 ) == '.' )
-                       && ( ( copyFrom + 2 == max )
-                            || ( *( copyFrom + 2 ) == '/' ) ) ) {
-                copyFrom += 3;
-
-                if( lastSegment > 0 ) {
-                    copyTo = Segments[--lastSegment];
-                } else {
-                    free( Segments );
-                    /*TRACE("ERROR RESOLVING URL, ../ at ROOT"); */
-                    return UPNP_E_INVALID_URL;
-                }
-                continue;
+static UPNP_INLINE int is_end_path(char c) {
+    switch (c) {
+	case '?':
+	case '#':
+	case '\0':
+	    return 1;
+    }
+    return 0;
+}
+
+
+/* This function directly implements the "Remove Dot Segments"
+ * algorithm described in RFC 3986 section 5.2.4. */
+int remove_dots(char *buf, size_t size)
+{
+    char *in = buf;
+    char *out = buf;
+    char *max = buf + size;
+
+    while (!is_end_path(in[0])) {
+	assert (buf <= out);
+	assert (out <= in);
+	assert (in < max);
+
+        /* case 2.A: */
+        if (strncmp(in, "./", 2) == 0) {
+            in += 2;
+        } else if (strncmp(in, "../", 3) == 0) {
+            in += 3;
+        /* case 2.B: */
+        } else if (strncmp(in, "/./", 3) == 0) {
+            in += 2;
+        } else if (strncmp(in, "/.", 2) == 0 && is_end_path(in[2])) {
+            in += 1;
+	    in[0] = '/';
+        /* case 2.C: */
+        } else if (strncmp(in, "/../", 4) == 0 || (strncmp(in, "/..", 3) == 0 && is_end_path(in[3]))) {
+            /* Make the next character in the input buffer a '/': */
+            if (is_end_path(in[3])) { /* terminating "/.." case */
+                in += 2;
+                in[0] = '/';
+            } else { /* "/../" prefix case */
+                in += 3;
             }
+            /* Trim the last component from the output buffer, or empty it. */
+            while (buf < out)
+		if (*--out == '/')
+		    break;
+#ifdef DEBUG
+	    if (out < in)
+		out[0] = '\0';
+#endif
+        /* case 2.D: */
+        } else if (strncmp(in, ".", 1) == 0 && is_end_path(in[1])) {
+            in += 1;
+	} else if (strncmp(in, "..", 2) == 0 && is_end_path(in[2])) {
+            in += 2;
+        /* case 2.E */
+        } else {
+            /* move initial '/' character (if any) */
+            if (in[0] == '/')
+		*out++ = *in++;
+	    /* move first segment up to, but not including, the next '/' character */
+	    while (in < max && in[0] != '/' && !is_end_path(in[0]))
+		*out++ = *in++;
+#ifdef DEBUG
+	    if (out < in)
+		out[0] = '\0';
+#endif
         }
-
-        if( ( *copyFrom ) == '/' ) {
-
-            lastSegment++;
-            Segments[lastSegment] = copyTo + 1;
-        }
-        ( *copyTo ) = ( *copyFrom );
-        copyTo++;
-        copyFrom++;
-    }
-    if( copyFrom < max ) {
-        while( copyFrom < max ) {
-            ( *copyTo ) = ( *copyFrom );
-            copyTo++;
-            copyFrom++;
-        }
-    }
-    ( *copyTo ) = 0;
-    free( Segments );
-    UpnpPrintf( UPNP_ALL, API, __FILE__, __LINE__,
-        "REMOVE_DOTS: after: %s\n", in );
+    }
+    while (in < max)
+	*out++ = *in++;
+    if (out < max)
+	out[0] = '\0';
     return UPNP_E_SUCCESS;
 }