[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#731357: opu: package librsvg/2.26.3-2



Control: tag 732144 patch

Attached patch should correctly handle URIs and non-URIs.

I've tested it with a few applications using relative and absolute
paths, and URIs.

Cheers,
-- 
Raphael Geissert - Debian Developer
www.debian.org - get.debian.net
Index: librsvg-2.26.3/rsvg-image.c
===================================================================
--- librsvg-2.26.3.orig/rsvg-image.c	2013-12-19 11:47:57.499003067 +0100
+++ librsvg-2.26.3/rsvg-image.c	2013-12-19 12:20:32.046140515 +0100
@@ -325,22 +325,7 @@ rsvg_acquire_vfs_resource (const char *f
 
     file = g_file_new_for_uri (filename);
 
-    if (!(res = g_file_load_contents (file, NULL, &data, &size, NULL, error))) {
-        if (base_uri != NULL) {
-            GFile *base;
-
-            rsvg_free_error (error);
-
-            g_object_unref (file);
-
-            base = g_file_new_for_uri (base_uri);
-            file = g_file_resolve_relative_path (base, filename);
-            g_object_unref (base);
-
-            res = g_file_load_contents (file, NULL, &data, &size, NULL, error);
-        }
-    }
-
+    res = g_file_load_contents (file, NULL, &data, &size, NULL, error);
     g_object_unref (file);
 
     if (res) {
@@ -356,23 +341,137 @@ rsvg_acquire_vfs_resource (const char *f
 }
 #endif
 
+/* Partial origin-based policy, based on the one implemented in f01aded72c38f0e1  */
+gboolean
+_rsvg_acquire_xlink_allow_load (const char *href, const char *base_uri, GError ** err)
+{
+    char *base_scheme = NULL, *href_scheme = NULL;
+
+    if (base_uri)
+        base_scheme = g_uri_parse_scheme (base_uri);
+    if (href)
+        href_scheme = g_uri_parse_scheme (href);
+
+    /* Not a valid URI */
+    if (href_scheme == NULL)
+        goto deny;
+
+    /* Allow loads of data: from any location */
+    if (g_str_equal (href_scheme, "data"))
+        goto allow;
+
+    /* no valid base URI */
+    if (base_scheme == NULL)
+        goto deny;
+
+    /* Deny loads from differing URI schemes */
+    if (href_scheme == NULL || !g_str_equal (href_scheme, base_scheme))
+        goto deny;
+
+    /* resource: is allowed to load anything from other resources */
+    if (g_str_equal (href_scheme, "resource"))
+        goto allow;
+
+    /* Non-file: isn't allowed to load anything */
+    if (!g_str_equal (href_scheme, "file"))
+        goto deny;
+
+    /* no local-file policy is applied here */
+
+allow:
+    free(base_scheme);
+    free(href_scheme);
+    return TRUE;
+
+deny:
+    free(base_scheme);
+    free(href_scheme);
+    g_set_error (err, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+                 "File may not link to URI \"%s\"", href);
+    return FALSE;
+}
+
 GByteArray *
 _rsvg_acquire_xlink_href_resource (const char *href, const char *base_uri, GError ** err)
 {
     GByteArray *arr = NULL;
+    char *base_scheme = NULL, *href_scheme = NULL;
+    char *href_uri = NULL;
+#ifndef HAVE_GIO
+    /* to be used ONLY for the policy check */
+    GString *href_uri_str = NULL;
+#endif
 
     if (!(href && *href))
         return NULL;
 
-    if (!strncmp (href, "data:", 5))
+    if (base_uri)
+        base_scheme = g_uri_parse_scheme (base_uri);
+    if (href)
+        href_scheme = g_uri_parse_scheme (href);
+
+    if (href_scheme && g_str_equal (href_scheme, "data"))
         arr = rsvg_acquire_base64_resource (href, NULL);
+    if (arr)
+        goto done;
 
-    if (!arr)
+#ifdef HAVE_GIO
+    /* if href is not a URI already, turn it into one based on base_uri */
+    if (href_scheme == NULL) {
+        GFile *file, *base, *parentless_base;
+        base = g_file_new_for_uri (base_uri);
+        /* now strip the file name: */
+        parentless_base = g_file_get_parent (base);
+        base = g_file_new_for_uri (base_uri);
+        file = g_file_resolve_relative_path (parentless_base, href);
+
+        g_object_unref (base);
+        g_object_unref (parentless_base);
+        href_uri = g_file_get_uri(file);
+        g_object_unref (file);
+    } else {
+        href_uri = strdup (href);
+        if (!href_uri) /* FIXME: better handling failure */
+            goto done;
+    }
+#else
+    if (href_scheme == NULL) {
+        href_uri_str = g_string_new(href);
+        if (base_scheme) {
+            /* try to turn href into a uri */
+            g_string_prepend (href_uri_str, "://");
+            g_string_prepend (href_uri_str, base_scheme);
+            /* no need to free, as href_scheme is NULL, remember? */
+            href_scheme = strdup (base_scheme);
+            if (!href_scheme) /* FIXME: better handling failure */
+                goto done;
+        } else
+            goto done;
+    } else {
+        href_uri_str = g_string_new(href);
+    }
+    href_uri = href_uri_str->str;
+#endif
+
+    if (!_rsvg_acquire_xlink_allow_load(href_uri, base_uri, err))
+        goto done;
+
+#ifdef HAVE_GIO
+    arr = rsvg_acquire_vfs_resource (href_uri, base_uri, NULL);
+#else
+    /* href must be a path for fopen() to work */
+    if (g_str_equal (href_scheme, "file"))
         arr = rsvg_acquire_file_resource (href, base_uri, NULL);
+#endif
+
+done:
+    free(href_scheme);
+    free(base_scheme);
 
 #ifdef HAVE_GIO
-    if (!arr)
-        arr = rsvg_acquire_vfs_resource (href, base_uri, NULL);
+    g_free(href_uri);
+#else
+    g_string_free (href_uri_str, TRUE);
 #endif
 
     return arr;
Index: librsvg-2.26.3/rsvg-base.c
===================================================================
--- librsvg-2.26.3.orig/rsvg-base.c	2013-12-19 11:47:57.499003067 +0100
+++ librsvg-2.26.3/rsvg-base.c	2013-12-19 12:18:45.573322740 +0100
@@ -1049,12 +1049,13 @@ rsvg_handle_set_base_uri (RsvgHandle * h
     else
         uri = rsvg_get_base_uri_from_filename (base_uri);
 
-    if (uri) {
-        if (handle->priv->base_uri)
-            g_free (handle->priv->base_uri);
-        handle->priv->base_uri = uri;
-        rsvg_defs_set_base_uri (handle->priv->defs, handle->priv->base_uri);
-    }
+    if (!uri)
+        uri = g_strdup("data:");
+
+    if (handle->priv->base_uri)
+        g_free (handle->priv->base_uri);
+    handle->priv->base_uri = uri;
+    rsvg_defs_set_base_uri (handle->priv->defs, handle->priv->base_uri);
 }
 
 /**
Index: librsvg-2.26.3/rsvg-base-file-util.c
===================================================================
--- librsvg-2.26.3.orig/rsvg-base-file-util.c	2013-12-19 11:47:57.499003067 +0100
+++ librsvg-2.26.3/rsvg-base-file-util.c	2013-12-19 12:19:06.249481571 +0100
@@ -87,10 +87,20 @@ rsvg_handle_new_from_file (const gchar *
     gchar *base_uri;
     GByteArray *f;
     RsvgHandle *handle = NULL;
+    char *base_scheme;
 
     rsvg_return_val_if_fail (file_name != NULL, NULL, error);
 
-    base_uri = rsvg_get_base_uri_from_filename (file_name);
+    /* turn the file name/path into a URI if it is not one already */
+    base_scheme = g_uri_parse_scheme (file_name);
+    if (base_scheme) {
+        free (base_scheme);
+        base_scheme = 0;
+        base_uri = g_strdup(file_name);
+    } else {
+        base_uri = rsvg_get_base_uri_from_filename (file_name);
+    }
+    base_file_name = g_filename_from_uri (base_uri, NULL, error);
     f = _rsvg_acquire_xlink_href_resource (file_name, base_uri, error);
 
     if (f) {

Reply to: