Bug#732144: Bug#731357: opu: package librsvg/2.26.3-2
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
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))