summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2021-12-05 18:05:14 +0100
committerBenjamin Otte <otte@redhat.com>2023-04-15 06:11:54 +0200
commita7a3ec8a168832500bd0ec0796fbf23b608b2fc7 (patch)
treeba652ebbe398ee92a3ffc6e9c21cb3c2f0d8e49c
parent506b009925ce44b7458b0dad5fb34275ee38e7b6 (diff)
downloadgtk+-a7a3ec8a168832500bd0ec0796fbf23b608b2fc7.tar.gz
jsonparser: Don't stack overflow
Handle skipping deep nested object/array trees when skipping them without causing stack overflow. The code is somewhat brittle, but it seems to work.
-rw-r--r--gtk/json/gtkjsonparser.c48
-rw-r--r--gtk/json/gtkjsonparserprivate.h1
2 files changed, 36 insertions, 13 deletions
diff --git a/gtk/json/gtkjsonparser.c b/gtk/json/gtkjsonparser.c
index 7c112eab42..2c1b94de2c 100644
--- a/gtk/json/gtkjsonparser.c
+++ b/gtk/json/gtkjsonparser.c
@@ -1012,24 +1012,40 @@ gtk_json_parser_free (GtkJsonParser *self)
static gboolean
gtk_json_parser_skip_block (GtkJsonParser *self)
{
+ gsize depth;
+
if (self->reader != self->block->value)
return TRUE;
- if (*self->reader == '{')
- {
- return gtk_json_parser_start_object (self) &&
- gtk_json_parser_end (self);
- }
- else if (*self->reader == '[')
- {
- return gtk_json_parser_start_array (self) &&
- gtk_json_parser_end (self);
- }
- else
+ depth = gtk_json_parser_get_depth (self);
+ while (TRUE)
{
- g_assert_not_reached ();
- return FALSE;
+ if (*self->reader == '{')
+ {
+ if (!gtk_json_parser_start_object (self))
+ return FALSE;
+ }
+ else if (*self->reader == '[')
+ {
+ if (!gtk_json_parser_start_array (self))
+ return FALSE;
+ }
+
+ while (self->reader != self->block->value)
+ {
+ /* This should never be reentrant to this function or we might
+ * loop causing stack overflow */
+ if (!gtk_json_parser_next (self))
+ {
+ if (!gtk_json_parser_end (self))
+ return FALSE;
+ if (depth >= gtk_json_parser_get_depth (self))
+ return TRUE;
+ }
+ }
}
+
+ return TRUE;
}
gboolean
@@ -1147,6 +1163,12 @@ gtk_json_parser_next (GtkJsonParser *self)
return TRUE;
}
+gsize
+gtk_json_parser_get_depth (GtkJsonParser *self)
+{
+ return self->block - self->blocks;
+}
+
GtkJsonNode
gtk_json_parser_get_node (GtkJsonParser *self)
{
diff --git a/gtk/json/gtkjsonparserprivate.h b/gtk/json/gtkjsonparserprivate.h
index fe737fb719..155a5b7603 100644
--- a/gtk/json/gtkjsonparserprivate.h
+++ b/gtk/json/gtkjsonparserprivate.h
@@ -55,6 +55,7 @@ GtkJsonParser * gtk_json_parser_new_for_string (const char
void gtk_json_parser_free (GtkJsonParser *self);
gboolean gtk_json_parser_next (GtkJsonParser *self);
+gsize gtk_json_parser_get_depth (GtkJsonParser *self);
GtkJsonNode gtk_json_parser_get_node (GtkJsonParser *self);
char * gtk_json_parser_get_member_name (GtkJsonParser *self);
gssize gtk_json_parser_select_member (GtkJsonParser *self,