[gtk/wip/otte/json: 16/21] jsonparser: Don't stack overflow




commit 35a018fb15e8bb069d3d6d1f07b71f1fe809f795
Author: Benjamin Otte <otte redhat com>
Date:   Sun Dec 5 18:05:14 2021 +0100

    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.

 gtk/json/gtkjsonparser.c        | 48 ++++++++++++++++++++++++++++++-----------
 gtk/json/gtkjsonparserprivate.h |  1 +
 2 files changed, 36 insertions(+), 13 deletions(-)
---
diff --git a/gtk/json/gtkjsonparser.c b/gtk/json/gtkjsonparser.c
index 91c59a32f3..2f0ba96ed9 100644
--- a/gtk/json/gtkjsonparser.c
+++ b/gtk/json/gtkjsonparser.c
@@ -1009,24 +1009,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
@@ -1144,6 +1160,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,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]