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: