[json-glib: 1/2] json-parser: Fix getting immutable root nodes from empty input



commit ef5707cd0b8d1a1a4ab4edf9ae58c7b3176ef93b
Author: Philip Withnall <withnall endlessm com>
Date:   Fri Dec 15 16:10:47 2017 +0000

    json-parser: Fix getting immutable root nodes from empty input
    
    If parsing an empty document, it’s allowed to return NULL from
    json_parser_get_root(). This was broken for immutable parsers when
    immutability support was added (an assertion fails). Fix that, and also
    document that json_parser_get_root() may return NULL.
    
    Do the same for json_parser_steal_root() too, which is another way that
    the root node may be NULL.
    
    Add a unit test.
    
    Signed-off-by: Philip Withnall <withnall endlessm com>

 json-glib/json-parser.c  | 19 ++++++++++++++-----
 json-glib/tests/parser.c | 22 +++++++++++++++++-----
 2 files changed, 31 insertions(+), 10 deletions(-)
---
diff --git a/json-glib/json-parser.c b/json-glib/json-parser.c
index bdb7123..0f87ba4 100644
--- a/json-glib/json-parser.c
+++ b/json-glib/json-parser.c
@@ -1179,9 +1179,11 @@ json_parser_load_from_data (JsonParser   *parser,
  * json_parser_get_root:
  * @parser: a #JsonParser
  *
- * Retrieves the top level node from the parsed JSON stream.
+ * Retrieves the top level node from the parsed JSON stream. If the parser input
+ * was an empty string, or if parsing failed, this will be %NULL. It will also
+ * be %NULL if it has been stolen using json_parser_steal_root().
  *
- * Return value: (transfer none): the root #JsonNode . The returned
+ * Return value: (transfer none) (nullable): the root #JsonNode . The returned
  *   node is owned by the #JsonParser and should never be modified
  *   or freed.
  */
@@ -1191,7 +1193,8 @@ json_parser_get_root (JsonParser *parser)
   g_return_val_if_fail (JSON_IS_PARSER (parser), NULL);
 
   /* Sanity check. */
-  g_return_val_if_fail (!parser->priv->is_immutable ||
+  g_return_val_if_fail (parser->priv->root == NULL ||
+                        !parser->priv->is_immutable ||
                         json_node_is_immutable (parser->priv->root), NULL);
 
   return parser->priv->root;
@@ -1201,9 +1204,10 @@ json_parser_get_root (JsonParser *parser)
  * json_parser_steal_root:
  * @parser: a #JsonParser
  *
- * Steals the top level node from the parsed JSON stream.
+ * Steals the top level node from the parsed JSON stream. This will be %NULL
+ * in the same situations as json_parser_get_root() returns %NULL.
  *
- * Returns: (transfer full): the top level #JsonNode
+ * Returns: (transfer full) (nullable): the top level #JsonNode
  *
  * Since: 1.4
  */
@@ -1214,6 +1218,11 @@ json_parser_steal_root (JsonParser *parser)
 
   g_return_val_if_fail (JSON_IS_PARSER (parser), NULL);
 
+  /* Sanity check. */
+  g_return_val_if_fail (parser->priv->root == NULL ||
+                        !parser->priv->is_immutable ||
+                        json_node_is_immutable (parser->priv->root), NULL);
+
   return g_steal_pointer (&priv->root);
 }
 
diff --git a/json-glib/tests/parser.c b/json-glib/tests/parser.c
index 8c52a1d..7af4329 100644
--- a/json-glib/tests/parser.c
+++ b/json-glib/tests/parser.c
@@ -144,14 +144,10 @@ static guint n_test_assignments    = G_N_ELEMENTS (test_assignments);
 static guint n_test_unicode        = G_N_ELEMENTS (test_unicode);
 
 static void
-test_empty (void)
+test_empty_with_parser (JsonParser *parser)
 {
-  JsonParser *parser;
   GError *error = NULL;
 
-  parser = json_parser_new ();
-  g_assert (JSON_IS_PARSER (parser));
-
   if (g_test_verbose ())
     g_print ("checking json_parser_load_from_data with empty string...\n");
 
@@ -170,7 +166,23 @@ test_empty (void)
 
       g_assert (NULL == json_parser_get_root (parser));
     }
+}
+
+static void
+test_empty (void)
+{
+  JsonParser *parser;
+
+  /* Check with and without immutability enabled, as there have been bugs with
+   * NULL root nodes on immutable parsers. */
+  parser = json_parser_new ();
+  g_assert (JSON_IS_PARSER (parser));
+  test_empty_with_parser (parser);
+  g_object_unref (parser);
 
+  parser = json_parser_new_immutable ();
+  g_assert (JSON_IS_PARSER (parser));
+  test_empty_with_parser (parser);
   g_object_unref (parser);
 }
 


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