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

2013-12-20 Thread Raphael Geissert
Hi again,

Found another case where it didn't work as expected. Updated,
attached, patch should do it.

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-20 14:28:57.731991069 +0100
+++ librsvg-2.26.3/rsvg-image.c	2013-12-20 14:38:59.384692376 +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,136 @@ 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);
+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);
+

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

2013-12-19 Thread Raphael Geissert
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))