Compare cJSON objects in the same code every time program is executed - c

I have a code which is always running in the background. compareContents() reads contents from a file periodically (based on an event) and stores it in a cSJON object. I have to compare current contents of the file (cJSON object) with the previous contents (again a cJSON object) everytime, but I am getting a memory leak. Please help.
cJSON * prev = NULL, *current = NULL;
bool compare = false;
bool compareJSON(cJSON *i,cJSON *j) /* referred from https://cjson.docsforge.com/master/api/cJSON_Compare/ */
{
if (i->type != j->type) {
return false;
}
if (i->type == cJSON_Number && (i->valueint != j->valueint)) {
return false;
}
if (i->type == cJSON_String && strcmp(i->valuestring,j->valuestring)){
return false;
}
if (i->type==cJSON_Array)
{
cJSON *ic = i->child, *jc = j->child;
while (ic && jc)
{
if (!compareJSON(ic, jc)) {
return false;
}
ic = ic->next, jc = jc->next;
}
if (ic || jc)
return false;
}
if (i->type == cJSON_Object)
{
cJSON *ic = i->child;
while (ic)
{
cJSON *jc = cJSON_GetObjectItem(j,ic->string);
if (!jc || !compareJSON(ic,jc)){
return false;
}
ic = ic->next;
}
// And again, for j == i.
cJSON *jc = j->child;
while (jc)
{
cJSON *ic=cJSON_GetObjectItem(i,jc->string);
if (!ic || !compareJSON(ic,jc)){
return false;
}
jc = jc->next;
}
}
return true;
}
bool compareContents(){
int fd = open("/tmp/abc.txt", O_RDONLY);
char* data = (char *)malloc(st.st_size + 1); //st.st_size obtained from fstat
int n = read(fd, data, st.st_size);
data[n] = '\0';
cJSON* root = cJSON_Parse(data);
if(prev == NULL){ //first time execution of program
prev = root;
}
else {
if(current){
prev = current;
}
}
current = cJSON_Duplicate(root,1);
if (prev && current)
{
compare = compareJSON(prev,current);
}
if (fd >= 0)
close(fd);
if (access("/tmp/abc.txt", F_OK) == 0 && remove("/tmp/abc.txt") != 0){
printf("Error deleting the file\n");
}
if (data)
free(data);
if (root)
cJSON_Delete(root);
return compare;
}

I am not sure, but this seems like dynamic copy?
current = cJSON_Duplicate(root,1);
That is you never free current and prev if it was not null. Maybe start from this point? Seems like memory leak.

Related

Heap buffer overflow on a getline() - C

I am coding a local server, I need to parse a file to get the config of the server.
Problem : I have a heap buffer overflow indicated at on the while.
This probeme is shown when I run with -fsanitize but I don't have any trouble without.
Here is the code :
struct container *configParse(FILE *file)
{
char *line = NULL;
size_t n;
char *token = NULL;
char *saveptr = NULL;
struct container *head = NULL;
struct container *container = NULL;
int key = 0;
int first = 1;
while ((getline(&line, &n, file)) != -1)
{
token = strtok_r(saveptr, " =\n\r", &line);
while (token != NULL)
{
if (token[0] == '[')
{
if (first)
{
container = container_init();
container->title = token;
head = container;
first = 0;
}
else
{
container = container_add_back(container);
container = container->next;
container->item = NULL;
container->title = token;
}
key = 0;
}
else
{
if (key == 0)
{
if (container->item == NULL)
{
container->item = items_init();
container->item->key = token;
}
else
{
struct item *itemcpy = container->item;
while (itemcpy->next != NULL)
{
itemcpy = itemcpy->next;
}
itemcpy->next = items_init();
itemcpy->next->key = token;
}
key = 1;
}
else
{
struct item *itemcpy = container->item;
while (itemcpy->next != NULL)
{
itemcpy = itemcpy->next;
}
itemcpy->value = token;
key = 0;
}
}
token = strtok_r(NULL, " =\n\r", &line);
}
}
container_print(head);
printf("\n*****Parsing du .conf*****\n\n");
if (isvalid(head))
printf("Parsing OK\n");
else
{
printf("Parsing KO\n");
return NULL;
}
return head;
}
Thanks in advance.
As explained I try to run the program without -fsanitze, and everything was fine

Passed pointer becomes 0x1

I'm working on a school assignment and am stuck on this part. To summarize what the code is supposed to do, it is meant to put 100 random integers into a B-Tree and print out the sorted list of numbers. I get my random numbers easily enough and begin to insert them using the following function:
void BTree_Insert(BTREE* tree, int* dataInPtr) {
bool taller;
NODE* newPtr;
ENTRY upEntry;
if (tree->root == NULL) {
if (newPtr = (NODE*)malloc(sizeof(NODE))) {
newPtr->firstPtr = NULL;
newPtr->numEntries = 1;
newPtr->entries[0].dataPtr = dataInPtr;
newPtr->entries[0].rightPtr = NULL;
tree->root = newPtr;
(tree->count)++;
for (int i = 1; i < ORDER - 1; i++) {
newPtr->entries[i].dataPtr = NULL;
newPtr->entries[i].rightPtr = NULL;
}
return;
}
else {
printf("Overflow error 100 in BTree_Insert\a\n"), exit(100);
}
}
taller = _insert(tree, tree->root, dataInPtr, &upEntry);
if (taller) {
newPtr = (NODE*)malloc(sizeof(NODE));
if (newPtr) {
newPtr->entries[0] = upEntry;
newPtr->firstPtr = tree->root;
newPtr->numEntries = 1;
tree->root = newPtr;
}
else {
printf("Overflow error 101\a\n"), exit(100);
}
}
(tree->count)++;
return;
}
The first number enters fine (tree->root would be null at this point), but when the second number is inserted, it calls _insert, which is where my problems start. Here is the code for _insert:
bool _insert(BTREE* tree, NODE* root, int* dataInPtr, ENTRY* upEntry) {
if (root == 0x1) {
//printf("root is now 0x1");
}
int compResult;
int entryNdx;
bool taller;
NODE* subtreePtr;
if (!root) {
(*upEntry).dataPtr = dataInPtr;
(*upEntry).rightPtr = NULL;
return true;
}
entryNdx = _searchNode(tree, root, dataInPtr);
compResult = tree->compare(dataInPtr, root->entries[entryNdx].dataPtr);
if (entryNdx <= 0 && compResult < 0) {
subtreePtr = root->firstPtr;
}
else {
subtreePtr = root->entries[entryNdx].rightPtr;
}
taller = _insert(tree, subtreePtr, dataInPtr, upEntry);
if (taller) {
if (root->numEntries >= ORDER - 1) {
_splitNode(root, entryNdx, compResult, upEntry);
taller = true;
}
else {
if (compResult >= 0) {
_insertEntry(root, entryNdx + 1, *upEntry);
}
else {
_insertEntry(root, entryNdx, *upEntry);
}
(root->numEntries)++;
taller = false;
}
}
return taller;
}
When passing through root, it for some reason becomes 0x1 and I get a read access violation. I have verified that in BTree_Insert tree->root is not 0x1, so I really have no idea what's going on. Any insight as to how to fix this would be much appreciated.

C invalid memory access

I am new to C language and I'm trying to compare the characters a pointer points. But when I inspect my code with Intel Inspector for memory errors I am getting invalid memory access errors in this function.
Inspectors says that these two lines cause this.
for (int i = 0; currentPathParameter[i] != '\0'; ++i) {
if (currentPathParameter[i] == '/')
}
Whole function:
bool asteriskControl(char* currentPathParameter) {
int directory = 1;
for (int i = 0; currentPathParameter[i] != '\0'; ++i) {
if (currentPathParameter[i] == '/')
directory++;
}
if (asteriskCounter > directory) {
printf("Can not use '*' operator for the folder that the program is currently in.");
return false;
}
return true;}
This is the line that I call the function.
noAsteriskError = asteriskControl(currentPath);
I am passing currentPath to function and I initialize it here.
char* currentPath = NULL;
char erdem[12] = { 'e','r','d','e','m','/','h','a','k','a','n','\0' };
currentPath = strdup(erdem);
Minimal code example:
int asteriskCounter = 1;
bool asteriskControl(char* currentPathParameter) {
int directory = 1;
for (int i = 0; currentPathParameter[i] != '\0'; ++i) {
if (currentPathParameter[i] == '/')
directory++;
}
if (asteriskCounter > directory) {
printf("Can not use '*' operator for the folder that the program is currently in.");
return false;
}
return true;}
int main() {
char* currentPath = NULL;
char erdem[] = "erdem/hakan";
currentPath = strdup(erdem);
bool noAsteriskError = false;
if (asteriskCounter > 0)
if (currentPath != NULL) {
noAsteriskError = asteriskControl(currentPath);
}
else {
noAsteriskError = false;
}
else {
noAsteriskError = true;
}
return 0;}
Any help is appreciated.

How to free char** array that allocated in calling function from main?

this is the function that i am calling from main:
char** readTokens(char *userInput, const char *seperator)
{
char** c;
char line1[512],line2[512];
int wordCount = 0;
int index;
char* tmp;
strcpy(line1, userInput);
for (index=0;line1[index]!='\n';index++);
line1[index]='\0';
strcpy(line2,line1);
tmp = strtok(line1,seperator);
while (tmp!=NULL)
{
tmp=strtok(NULL,seperator);
wordCount = wordCount + 1;
}
if((wordCount) == ERROR)
{
return NULL;
}
c=(char**)malloc(((wordCount)+1)*sizeof(char*));
if (c == NULL)
{
printf("failed to allocate memory.\n");
return NULL;
}
tmp = strtok(line2,seperator);
index=0;
while (tmp!=NULL)
{
c[index]=(char*)malloc((strlen(tmp)+1*sizeof(char)));
if (c[index]==NULL)
{
printf("failed to allocate memory.\n");
return NULL;
}
strcpy(c[index],tmp);
tmp=strtok(NULL,seperator);
index++;
}
c[index] = NULL;//put NULL on last place
return c;
}
And this how i use it in main:
while (fgets(words, sizeof(words), filePointer) != NULL) // this line is a command of reading a line from the file.
{
/*here i am calling the function*/
array = readTokens(words, " ");
theGraph->graphEdges[index_i].sourceVertex = array[ZERO];
theGraph->graphEdges[index_i].destinationVertex = array[ONE];
theGraph->graphEdges[index_i].arcValue = atoi(array[TWO]);
for(index_j = ZERO ; index_j < vertexes ; index_j++)
{
if(theGraph->placeInTableIndex[index_j] == NULL)
{
theGraph->placeInTableIndex[index_j] = array[ZERO];
break;
}
else if(strcmp(theGraph->placeInTableIndex[index_j],array[ZERO]) == ZERO)
break;
}
for(index_j = ZERO ; index_j < vertexes ; index_j++)
{
if(theGraph->placeInTableIndex[index_j] == NULL)
{
theGraph->placeInTableIndex[index_j] = array[ONE];
break;
}
else if(strcmp(theGraph->placeInTableIndex[index_j],array[ONE]) == ZERO)
break;
}
theGraph->graphEdges[index_i+ONE].sourceVertex = array[ONE];
theGraph->graphEdges[index_i+ONE].destinationVertex = array[ZERO];
theGraph->graphEdges[index_i+ONE].arcValue = atoi(array[TWO]);
index_i+= TWO;
//freeTokens(array);
}
I tried to do free to the array in the end of the while but it not work i still have memory leak from this function (valgrind check). i am using this function to free:
void freeTokens(char** tokens)
{
while(*tokens != NULL)
{
*tokens = NULL;
free(*tokens);
*tokens++;
}
tokens = NULL;
free(tokens);
}
You're losing the original value of tokens (the thing you need to free) by incrementing it; then you set it to NULL, then try to free NULL.
Instead:
void freeTokens(char** tokens)
{
char **freeTokens = tokens;
while (*freeTokens != NULL)
{
free(*freeTokens);
*freeTokens = NULL; // not actually necessary, but must happen *after* if at all
freeTokens++;
}
free(tokens);
// tokens = NULL; // accomplishes nothing; doesn't change the caller's version
}

C Custom Database writing errors

I have an assignment for class that I have to write a program to read and write key, value pairs to disk. I am using a linked list to store the keys, and read in values whenever I need to from disk. However, I am having trouble changing and deleting values. I am using this to test it: http://gaming.jhu.edu/~phf/2010/fall/cs120/src/sdbm-examples.tar.gz. Code below. Basically, I need some help figuring out errors, because this is the first assignment we have had to use pointers on, and I am just dying in all the segfaults and everything else. Just some advice would be greatly appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <stdbool.h>
#include "sdbm.h"
FILE *db;
bool opened = false, needNewDB = false;
int err = 0, keyLen = 0;
char *filename;
typedef struct Key_{
char *name;
char *val;
long offset;
struct Key_ *next;
} Key;
Key *head = NULL,*tail = NULL, *lastHas = NULL, *beforeLastHas = NULL;
/**
* Create new database with given name. You still have
* to sdbm_open() the database to access it. Return true
* on success, false on failure.
*/
void listAdd() {
if (tail != NULL) {
tail->next = (Key *) malloc(sizeof(Key));
tail = tail->next;
}
else {
tail = (Key *)malloc(sizeof(Key));
head = tail;
}
tail->next = NULL;
tail->name = NULL;
tail->val = NULL;
}
bool sdbm_create( const char *name ) { //Errors: 1) fopen failed 2) fclose failed on new db
filename = malloc(sizeof(*name));
strcpy(filename,name);
FILE *temp = fopen(name, "w");
if (temp == NULL) {
printf("Couldn't create file %s\n",name);
err = 1;
return false;
}
if (fclose(temp) == EOF) {
printf("Couldn't close created file %s\n",name);
err = 2;
return false;
}
return true;
}
/**
* Open existing database with given name. Return true on
* success, false on failure.
*/
bool sdbm_open( const char *name ) { //Errors: 3) couldn't open database
db = fopen(name,"r+");
if (db == NULL) {
err = 3;
printf("Couldn't open database file %s\n",name);
return false;
}
opened = true;
int c;
bool inKey = true;
char currKey[MAX_KEY_LENGTH];
while ((c = getc(db)) != EOF) {
if (!inKey && c == '\0') {
inKey = true;
}
else if (inKey && c == '\0') {
currKey[keyLen] = '\0';
listAdd();
tail->offset = ftell(db);
tail->name = malloc(sizeof(*currKey));
strcpy(tail->name,currKey);
keyLen = 0;
inKey = false;
}
else if (inKey) {
currKey[keyLen] = c;
keyLen++;
}
}
Key *curr = head;
while (curr != NULL) {
printf("Key: %s\n",curr->name);
curr = curr->next;
}
return true;
}
void readVal(char *value, long offset) {
fseek(db,offset,SEEK_SET);
int c;
for (int i = 0; (c = getc(db)) != '\0'; i++) {
*(value + i) = c;
}
}
/**
* Synchronize all changes in database (if any) to disk.
* Useful if implementation caches intermediate results
* in memory instead of writing them to disk directly.
* Return true on success, false on failure.
*/
bool sdbm_sync() {
if (!needNewDB) {
Key *curr = head;
fseek(db,0,SEEK_END);
while (curr != NULL) {
if (curr->val != NULL) {
fprintf(db,"%s%c%s%c",curr->name,'\0',curr->val,'\0');
}
curr = curr->next;
}
}
else {
FILE *temp;
sdbm_create("tRpdxD.p4ed");
temp = fopen("tRpdxD.p4ed","w");
Key *curr = head;
while (curr != NULL) {
if (curr->val != NULL) {
fprintf(temp,"%s%c%s%c",curr->name, '\0', curr->val, '\0');
}else {
char *tempS = malloc(MAX_VALUE_LENGTH);
readVal(tempS, curr->offset);
fprintf(temp,"%s%c%s%c",curr->name,'\0',tempS,'\0');
free(tempS);
}
fflush(temp);
fflush(db);
curr = curr->next;
}
fclose(db);
remove(filename);
rename("tRpdxD.p4ed",filename);
db = fopen(filename,"r+");
}
fflush(db);
return true;
}
/**
* Close database, synchronizing changes (if any). Return
* true on success, false on failure.
*/
bool sdbm_close() { // Errors: 5) Couldn't close database
sdbm_sync();
Key *tmp = head;
while (head->next != NULL) {
tmp = head;
head = head->next;
free(tmp->name);
if (tmp->val != NULL) {
free(tmp->val);
}
free(tmp);
}
if (fclose(db) == EOF) {
err = 5;
printf("Couldn't close database.\n");
return false;
}
return true;
}
/**
* Return error code for last failed database operation.
*/
int sdbm_error() {
return err;
}
/**
* Is given key in database?
*/
bool sdbm_has( const char *key ) {
if (head == NULL) {
return false;
}
Key *curr = head;
lastHas = NULL;
beforeLastHas = NULL;
while (curr != NULL) {
if (!strcmp(curr->name,key)) {
lastHas = curr;
return true;
}
beforeLastHas = curr;
curr = curr->next;
}
return false;
}
/**
* Get value associated with given key in database.
* Return true on success, false on failure.
*
* Precondition: sdbm_has(key)
*/
bool sdbm_get( const char *key, char *value ) { //Errors: 6)Don't have key
if (!sdbm_has(key)) {
printf("Precondition sdbm_has(%s) failed", key);
err = 6;
return false;
}
readVal(value, lastHas->offset);
return true;
}
/**
* Update value associated with given key in database
* to given value. Return true on success, false on
* failure.
*
* Precondition: sdbm_has(key)
*/
bool sdbm_put( const char *key, const char *value ) {
if (!sdbm_has(key)) {
printf("Precondition !sdbm_has(%s) failed",key);
err = 7;
return false;
}
sdbm_remove(key);
sdbm_insert(key,value);
return true;
}
/**
* Insert given key and value into database as a new
* association. Return true on success, false on
* failure.
*
* Precondition: !sdbm_has(key)
*/
bool sdbm_insert( const char *key, const char *value ) { //Errors: 7)Already have key 8)Invalid key or value length
if (sdbm_has(key)) {
printf("Precondition !sdbm_has(%s) failed",key);
err = 7;
return false;
}
if (strlen(key) < MIN_KEY_LENGTH || strlen(key) > MAX_KEY_LENGTH || strlen(value) < MIN_VALUE_LENGTH || strlen(value) > MAX_VALUE_LENGTH) {
printf("Invalid key or value length");
err = 8;
return false;
}
listAdd();
tail->name = (char *)key;
tail->val = malloc(sizeof(*value));
strcpy(tail->val,value);
return true;
}
/**
* Remove given key and associated value from database.
* Return true on success, false on failure.
*
* Precondition: sdbm_has(key)
*/
bool sdbm_remove( const char *key ) {
if (!sdbm_has(key)) {
printf("Precondition !sdbm_has(%s) failed",key);
err = 7;
return false;
}
needNewDB = true;
if (beforeLastHas == NULL) {
head = lastHas->next;
}
else if (lastHas->next == NULL) {
tail = beforeLastHas;
}
else {
beforeLastHas->next = lastHas->next;
}
if (lastHas->val != NULL) {
free(lastHas->val);
}
free(lastHas->name);
free(lastHas);
return true;
}
There's a lot of errors in this code. To name just one:
filename = malloc(sizeof(*name));
*name is the first element of name, so it's a char, so sizeof(*name) == 1. To get the size of a string, use strlen(name) + 1. Better yet, use strdup if your system has it.
i would advise against global variables. you can not change the program (in the future) to use two of your databases in parallel.
so all your sdbm_xxx functions should get (or infer) all necessary values on their own.

Resources