Search code examples
cjansson

Jansson JSON with C - json_set_object() causing application crash


I have a condition I cannot explain when using Jansson in a C application. Here is an example of the code:

{
  "nodes": {
    "master": "10.0.0.9",
    "connected": [
      {
        "socket": 18,
        "IP": "10.0.0.9"
      }
    ]
  }
}

Code snippet

STATUS writeMasterNode(char *newMaster)
{
static char configFilename[] = "/path/to/file.json";

obj = json_load_file(configFilename, 0, &error);
// check to see if the string parsed fine
if (!obj)
{
    printf("Error parsing system configuration on line %d, column %d:%s", error.line, error.column, error.text);
  return;
}
// read the object into a temporary json objects
node_obj = json_object_get(obj, "nodes");
if (!node_obj)
{
  node_obj = json_pack("{{s:s},[{s:i},{s:s}]}", "master", NULL, "socket", NULL, "IP", NULL);
}
master_obj    = json_object_get(node_obj, "master");
connected_obj = json_object_get(node_obj, "connected");

//Update
//************* Good code ***************
master_obj = json_string(newMaster);
json_object_set(node_obj, "master", master_obj);
//***************************************
//
//************* Bad Code ***************
//json_object_set(node_obj, "master", json_string(newMaster))
//**************************************
//
json_object_set(obj, "nodes", node_obj);
//Write
if (!obj)
  {
    printf("Error parsing system configuration on line %d, column %d:%s", error.line, error.column, error.text);
    return;
  }
else
  {
    json_dump_file(obj, configFilename, JSON_INDENT(2));
  }
//Cleanup
json_decref(obj);
json_decref(node_obj);
son_decref(connected_obj);
json_decref(master_obj);
}

If I use: json_object_set(node_obj, "master", json_string(newMaster)) the app will update the file and seem fine until I recall this block of code, then it will crash upon second usage.

Changing the offending code line with:

master_obj = json_string(newMaster);
json_object_set(node_obj, "master", master_obj);

works fine and I can recall this function over and over without issue. Any ideas?


Solution

  • When you run the bad code:

    master_obj = json_object_get(node_obj, "master");
    ...
    json_object_set(node_obj, "master", json_string(newMaster))
    ...
    json_decref(node_obj);
    json_decref(master_obj);
    

    The master_obj is borrowed reference from node_obj, and it is already freed, when json_decref(master_obj) is called.

    The good code:

    master_obj = json_object_get(node_obj, "master");
    ...    
    master_obj = json_string(newMaster);
    json_object_set(node_obj, "master", master_obj);
    ...
    json_decref(node_obj);
    json_decref(master_obj);
    

    A new json_string object is created and pointer is stored to master_obj. The json_string object still exists when you call json_decref(master_obj), so it does not cause the issue.