I am making a JSON interpreter. The problem I am running across is that every time I add the value of an object, it will result in a segmentation fault once i call json->pairsSize++
. I have tried looking through the code, and found that every time i call realloc
or malloc
on json->pairs[json->pairsSize]->values
inside of case NEXT_PAIR
, it will cause the error, but if i were to comment out the json->pairsSize++
, the code will run fine, since it is replacing already existing data.
json.c
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <stdbool.h>
#include <json.h>
/* Local Data */
void remove_spacing(char * contents);
/* Init/Cleanup */
struct JSON * init_json() {
struct JSON * json = malloc(sizeof(struct JSON)+1);
json->objectName = malloc(1);
json->objectName[0] = '\0';
json->pairs = malloc(sizeof(struct Pair *));
json->pairsSize = 0;
json->objects = malloc(sizeof(struct JSON *));
json->objectsSize = 0;
json->prev = NULL;
return json;
}
struct Pair * init_pair() {
struct Pair * pair = malloc(sizeof(struct Pair));
pair->key = malloc(1);
pair->key[0] = '\0';
pair->values = malloc(sizeof(void*));
pair->valuesSize = 0;
return pair;
}
void interpret(struct JSON * json, char * filePath) {
FILE * json_file;
json_file = fopen(filePath, "r");
if (!json_file) {
printf("Couldn't find JSON file %s\n", filePath);
exit(EXIT_FAILURE);
}
char * jsonContent = malloc(1);
unsigned int jsonContentPtr = 0;
char ch;
while(!feof(json_file)) {
ch = fgetc(json_file);
jsonContent = realloc(jsonContent, jsonContentPtr+1);
jsonContent[jsonContentPtr] = ch;
jsonContentPtr++;
}
jsonContent[jsonContentPtr] = '\0';
printf("%s\n", jsonContent);
// Now the fun begins...
size_t jsonContentLen = strlen(jsonContent);
char * placeHolder = malloc(1);
unsigned int placeHolderIndex = 0;
bool isArray = false;
for (size_t i = 0; i < jsonContentLen; i++) {
switch(jsonContent[i]) {
case OBJECT_OPEN: {
if (i != 0 && isArray == false) {
struct JSON * newJson = init_json();
add_object(json, newJson);
json = json->objects[json->objectsSize-1];
// // Set objectName
placeHolder[placeHolderIndex] = '\0';
set_objectName(json, placeHolder);
placeHolder[0] = '\0';
placeHolderIndex = 0;
}
else if (isArray == true) {
}
break;
}
case OBJECT_CLOSE: {
// Add last value
if (json->prev != NULL) {
json = json->prev;
}
break;
}
case KEYPAIR_DELIM: {
placeHolder[placeHolderIndex] = '\0';
json->pairs = realloc(json->pairs, sizeof(struct Pair *) * (json->pairsSize+1));
json->pairs[json->pairsSize] = init_pair();
json->pairs[json->pairsSize]->key = realloc(json->pairs[json->pairsSize]->key, placeHolderIndex+1);
strncpy(json->pairs[json->pairsSize]->key, placeHolder, placeHolderIndex+1);
printf("%s\n", json->pairs[json->pairsSize]->key);
placeHolder[0] = '\0';
placeHolderIndex = 0;
}
case NEXT_PAIR: {
placeHolder[placeHolderIndex] = '\0';
size_t placeHolderLen = strlen(placeHolder);
// Where the error occurs everytime i have json->pairsSize++ uncommented
json->pairs[json->pairsSize]->values = realloc(json->pairs[json->pairsSize]->values, sizeof(void *) * (json->pairs[json->pairsSize]->valuesSize+1));
json->pairs[json->pairsSize]->values[json->pairs[json->pairsSize]->valuesSize] = malloc(placeHolderLen+1);
strncpy(json->pairs[json->pairsSize]->values[json->pairs[json->pairsSize]->valuesSize], placeHolder, placeHolderLen+1);
printf("%s\n", json->pairs[json->pairsSize]->values[json->pairs[json->pairsSize]->valuesSize]);
placeHolder[0] = '\0';
placeHolderIndex = 0;
json->pairs[json->pairsSize]->valuesSize++;
if (isArray == false) {
// Causes a segmentation fault for some reason, can't figure it out
json->pairsSize++;
}
break;
}
case DOUBLE_QUOTE: {
break;
}
default: {
placeHolder = realloc(placeHolder, placeHolderIndex+1);
placeHolder[placeHolderIndex] = jsonContent[i];
placeHolderIndex++;
break;
}
}
}
free(placeHolder);
fclose(json_file);
}
/* Setters */
void set_objectName(struct JSON * json, char * value) {
size_t valueLen = strlen(value);
json->objectName = realloc(json->objectName, valueLen+1);
strcpy(json->objectName, value);
}
void add_object(struct JSON * json, struct JSON * newJSON) {
newJSON->prev = json;
json->objects = realloc(json->objects, sizeof(struct JSON *)*(json->objectsSize+1));
json->objects[json->objectsSize] = newJSON;
json->objectsSize++;
}
json.h
#ifndef C_JSON_H
#define C_JSON_H
#define DOUBLE_QUOTE '"'
#define KEYPAIR_DELIM ':'
#define OBJECT_OPEN '{'
#define OBJECT_CLOSE '}'
#define ARRAY_OPEN '['
#define ARRAY_CLOSE ']'
#define NEXT_PAIR ','
struct Pair {
char * key;
void ** values;
unsigned int valuesSize;
};
struct JSON {
char * objectName;
struct Pair ** pairs;
unsigned int pairsSize;
struct JSON ** objects;
unsigned int objectsSize;
struct JSON * prev;
};
struct JSON * init_json();
struct Pair * init_pair();
void interpret(struct JSON * json, char * filePath);
/* Setters */
void set_objectName(struct JSON * json, char * value);
#endif
main.c
#include <json.h>
#include <stdio.h>
int main(void) {
struct JSON * json = init_json();
interpret(json, "./tests/objects.json");
printf("\n%s\n", json->objects[0]->pairs[0]->key);
return 0;
}
JSON test file (objects.json)
{
"Test-Object-1": {
"Song": "My Heroine",
"Author": "Silverstein",
"Length": 240
}
}