call json_node_init to already initialized node might cause SIGSEGV
By the documentation, json_node_init
function will "reset to the given type, and any data contained will be cleared"
It means that it is possible to call json_node_init
function on already initialized node.
However, call json_node_init
to already initialized node with different JsonNodeType will cause SIGSEGV.
I've added a following test function.
/* Test that reinit used node */
static void
test_node_reinit (void)
{
JsonNode *node = NULL;
JsonArray *array = NULL;
array = json_array_new ();
node = json_node_init_array (json_node_alloc (), array);
json_node_init_int(node, 1);
json_node_free (node);
json_array_unref (array);
}
Problem is caused by json_node_init
calls json_node_unset
(which doesn't clear node->data
pointer),
and keep using freed address.
So resetting pointer to NULL will make json_node_set
to allocate new pointer.
Following code will be the possible solution for the issue.
static void
json_node_unset (JsonNode *node)
{
/* Note: Don't use JSON_NODE_IS_VALID here because this may legitimately be
* called with (node->ref_count == 0) from json_node_unref(). */
g_assert (node != NULL);
switch (node->type)
{
case JSON_NODE_OBJECT:
if (node->data.object)
json_object_unref (node->data.object);
+ node->data.object = NULL;
break;
case JSON_NODE_ARRAY:
if (node->data.array)
json_array_unref (node->data.array);
+ node->data.array = NULL;
break;
case JSON_NODE_VALUE:
if (node->data.value)
json_value_unref (node->data.value);
+ node->data.value = NULL;
break;
case JSON_NODE_NULL:
break;
}
}