bgo#787895 - Use xmlCreateIOParserCtxt() for I/O callbacks instead of a push parser

We were using libxml2 incorrectly since 2010 (!).  We have to use
xmlCreatePushParserCtxt() with xmlParseChunk(), *OR*
xmlCreateIOParserCtxt(io_callbacks) with xmlParseDocument().

https://bugzilla.gnome.org/show_bug.cgi?id=787895
parent 65cc957c
......@@ -750,32 +750,26 @@ rsvg_start_xinclude (RsvgHandle * ctx, RsvgPropertyBag * atts)
GInputStream *stream;
GError *err = NULL;
xmlParserCtxtPtr xml_parser;
xmlParserInputBufferPtr buffer;
xmlParserInputPtr input;
stream = _rsvg_handle_acquire_stream (ctx, href, NULL, NULL);
if (stream == NULL)
goto fallback;
xml_parser = create_xml_parser (ctx, NULL);
xml_parser = rsvg_create_xml_parser_from_stream (&rsvgSAXHandlerStruct,
ctx,
stream,
NULL, /* cancellable */
&err);
rsvg_set_xml_parse_options (xml_parser, ctx);
buffer = _rsvg_xml_input_buffer_new_from_stream (stream, NULL /* cancellable */, &err);
g_object_unref (stream);
input = xmlNewIOInputStream (xml_parser, buffer /* adopts */, XML_CHAR_ENCODING_NONE);
if (xmlPushInput (xml_parser, input) < 0) {
g_clear_error (&err);
xmlFreeInputStream (input);
if (xml_parser) {
(void) xmlParseDocument (xml_parser);
xml_parser = rsvg_free_xml_parser_and_doc (xml_parser);
goto fallback;
}
(void) xmlParseDocument (xml_parser);
xml_parser = rsvg_free_xml_parser_and_doc (xml_parser);
g_clear_error (&err);
}
......@@ -2036,8 +2030,6 @@ rsvg_handle_read_stream_sync (RsvgHandle *handle,
GError **error)
{
RsvgHandlePrivate *priv;
xmlParserInputBufferPtr buffer;
xmlParserInputPtr input;
int result;
GError *err = NULL;
gboolean res = FALSE;
......@@ -2085,14 +2077,18 @@ rsvg_handle_read_stream_sync (RsvgHandle *handle,
priv->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
g_assert (handle->priv->ctxt == NULL);
handle->priv->ctxt = create_xml_parser (handle, rsvg_handle_get_base_uri (handle));
buffer = _rsvg_xml_input_buffer_new_from_stream (stream, cancellable, &err);
input = xmlNewIOInputStream (priv->ctxt, buffer, XML_CHAR_ENCODING_NONE);
handle->priv->ctxt = rsvg_create_xml_parser_from_stream (&rsvgSAXHandlerStruct,
handle,
stream,
cancellable,
&err);
rsvg_set_xml_parse_options (handle->priv->ctxt, handle);
if (!handle->priv->ctxt) {
if (err) {
g_propagate_error (error, err);
}
if (xmlPushInput (priv->ctxt, input) < 0) {
rsvg_set_error (error, priv->ctxt);
xmlFreeInputStream (input);
goto out;
}
......
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 sts=4 expandtab: */
/*
* Copyright © 2010 Christian Persch
*
......@@ -19,6 +21,7 @@
#include "config.h"
#include "rsvg-private.h"
#include "rsvg-xml.h"
typedef struct {
......@@ -29,10 +32,11 @@ typedef struct {
/* this should use gsize, but libxml2 is borked */
static int
context_read (RsvgXmlInputStreamContext *context,
context_read (void *data,
char *buffer,
int len)
{
RsvgXmlInputStreamContext *context = data;
gssize n_read;
if (*(context->error))
......@@ -48,8 +52,9 @@ context_read (RsvgXmlInputStreamContext *context,
}
static int
context_close (RsvgXmlInputStreamContext *context)
context_close (void *data)
{
RsvgXmlInputStreamContext *context = data;
gboolean ret;
/* Don't overwrite a previous error */
......@@ -64,20 +69,14 @@ context_close (RsvgXmlInputStreamContext *context)
return ret ? 0 : -1;
}
/**
* _rsvg_xml_input_buffer_new_from_stream:
* @context: a #xmlParserCtxtPtr
* @input_stream: a #GInputStream
*
* Returns: a new #xmlParserInputPtr wrapping @input_stream
*/
xmlParserInputBufferPtr
_rsvg_xml_input_buffer_new_from_stream (GInputStream *stream,
GCancellable *cancellable,
GError **error)
xmlParserCtxtPtr rsvg_create_xml_parser_from_stream (xmlSAXHandlerPtr sax,
void *sax_user_data,
GInputStream *stream,
GCancellable *cancellable,
GError **error)
{
RsvgXmlInputStreamContext *context;
xmlParserCtxtPtr parser;
g_return_val_if_fail (G_IS_INPUT_STREAM (stream), NULL);
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
......@@ -88,8 +87,18 @@ _rsvg_xml_input_buffer_new_from_stream (GInputStream *stream,
context->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
context->error = error;
return xmlParserInputBufferCreateIO ((xmlInputReadCallback) context_read,
(xmlInputCloseCallback) context_close,
context,
XML_CHAR_ENCODING_NONE);
parser = xmlCreateIOParserCtxt (sax,
sax_user_data,
context_read,
context_close,
context,
XML_CHAR_ENCODING_NONE);
if (!parser) {
g_set_error (error, rsvg_error_quark (), 0, _("Error creating XML parser"));
/* on error, xmlCreateIOParserCtxt() frees our context via the context_close function */
}
return parser;
}
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 sts=4 expandtab: */
/*
* Copyright © 2010 Christian Persch
*
......@@ -25,9 +27,12 @@
G_BEGIN_DECLS
xmlParserInputBufferPtr _rsvg_xml_input_buffer_new_from_stream (GInputStream *stream,
GCancellable *cancellable,
GError **error);
G_GNUC_INTERNAL
xmlParserCtxtPtr rsvg_create_xml_parser_from_stream (xmlSAXHandlerPtr sax,
void *sax_user_data,
GInputStream *stream,
GCancellable *cancellable,
GError **error);
G_END_DECLS
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment