From 059ec81c9e88ee5ec67aafd135714754ea5b9552 Mon Sep 17 00:00:00 2001 From: Michael Meeks Date: Tue, 9 Jun 2009 11:31:42 +0100 Subject: [PATCH] move start_element emission out into a new (inlined) function, so the alloca'd memory is released on return, rather than slowly blowing the stack. --- glib/gmarkup.c | 76 ++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 42 insertions(+), 34 deletions(-) diff --git a/glib/gmarkup.c b/glib/gmarkup.c index 35118ad..bb8165b 100644 --- a/glib/gmarkup.c +++ b/glib/gmarkup.c @@ -891,6 +891,47 @@ clear_attributes (GMarkupParseContext *context) g_assert (context->attr_values == NULL || context->attr_values[0] == NULL); } + +/* This has to be a separate function to ensure the alloca's + are unwound on exit - otherwise we grow & blow the stack + with large documents */ +static inline void +emit_start_element (GMarkupParseContext *context, GError **error) +{ + int i; + const gchar *start_name; + const gchar **attr_names; + const gchar **attr_values; + GError *tmp_error; + + attr_names = g_newa (const gchar *, context->cur_attr + 2); + attr_values = g_newa (const gchar *, context->cur_attr + 2); + for (i = 0; i < context->cur_attr + 1; i++) + { + attr_names[i] = context->attr_names[i]->str; + attr_values[i] = context->attr_values[i]->str; + } + attr_names[i] = NULL; + attr_values[i] = NULL; + + /* Call user callback for element start */ + tmp_error = NULL; + start_name = current_element (context); + + if (context->parser->start_element && + name_validate (context, start_name, error)) + (* context->parser->start_element) (context, + start_name, + (const gchar **)attr_names, + (const gchar **)attr_values, + context->user_data, + &tmp_error); + clear_attributes (context); + + if (tmp_error != NULL) + propagate_error (context, error, tmp_error); +} + /** * g_markup_parse_context_parse: * @context: a #GMarkupParseContext @@ -1217,40 +1258,7 @@ g_markup_parse_context_parse (GMarkupParseContext *context, */ if (context->state == STATE_AFTER_ELISION_SLASH || context->state == STATE_AFTER_CLOSE_ANGLE) - { - int i; - const gchar *start_name; - const gchar **attr_names; - const gchar **attr_values; - GError *tmp_error; - - attr_names = g_newa (const gchar *, context->cur_attr + 2); - attr_values = g_newa (const gchar *, context->cur_attr + 2); - for (i = 0; i < context->cur_attr + 1; i++) - { - attr_names[i] = context->attr_names[i]->str; - attr_values[i] = context->attr_values[i]->str; - } - attr_names[i] = NULL; - attr_values[i] = NULL; - - /* Call user callback for element start */ - tmp_error = NULL; - start_name = current_element (context); - - if (context->parser->start_element && - name_validate (context, start_name, error)) - (* context->parser->start_element) (context, - start_name, - (const gchar **)attr_names, - (const gchar **)attr_values, - context->user_data, - &tmp_error); - clear_attributes (context); - - if (tmp_error != NULL) - propagate_error (context, error, tmp_error); - } + emit_start_element (context, error); } break; -- 2.7.4