summaryrefslogtreecommitdiff
path: root/glib/gmarkup.c
diff options
context:
space:
mode:
authorMichael Meeks <michael.meeks@novell.com>2009-06-09 11:31:42 +0100
committerMichael Meeks <michael.meeks@novell.com>2009-06-09 11:32:44 +0100
commit059ec81c9e88ee5ec67aafd135714754ea5b9552 (patch)
treee375f03c3c5cf610e2441e22cc3d95db68d3fcb6 /glib/gmarkup.c
parentced88fd0de4aedb537552561582875b427081eeb (diff)
downloadglib-059ec81c9e88ee5ec67aafd135714754ea5b9552.tar.gz
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.
Diffstat (limited to 'glib/gmarkup.c')
-rw-r--r--glib/gmarkup.c76
1 files changed, 42 insertions, 34 deletions
diff --git a/glib/gmarkup.c b/glib/gmarkup.c
index 35118ad05..bb8165b75 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;