Use of json_object_put() in C library - c

I am using the json-c in my C program (not C++). I am getting segfaults from time to time and trying to debug. To be honest, I might not have the full understanding how the library works so I am looking for any advice.
This is partially how I am using:
char* createjsonstatusstring()
{
json_object *jsonmain,
*jsontmp;
const char *conststring;
char *string;
jsonmain = json_object_new_object();
jsontmp = json_object_new_object();
json_object_object_add(jsontmp,"test",json_object_new_string("Beispiel"));
json_object_object_add(jsontmp,"test2",json_object_new_string("Beispiel2"));
json_object_object_add(jsonmain,"Data",jsontmp);
conststring = json_object_to_json_string_ext(jsonmain,JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY);
json_object_put(jsontmp);
json_object_put(jsonmain);
string = malloc(strlen(conststring)+1);
strcpy(string,conststring);
return string;
}
When doing the last json_object_put I am getting the segfault.
Can you explain why and how to improve?
Thanks!
/KNEBB

From https://json-c.github.io/json-c/json-c-0.10/doc/html/json__object_8h.html#a04448b1c63173e1bfe49965835732075 :
void json_object_object_add ( struct json_object * obj,
const char * key,
struct json_object * val
)
Upon calling this, the ownership of val transfers to obj. [..]
and
void json_object_put ( struct json_object * obj )
Decrement the reference count of json_object and free if it reaches zero. You must have ownership of obj prior to doing this or you will cause an imbalance in the reference count.
You do not have ownership in jsontmp, so doing json_object_put(jsontmp); is invalid. Just only call json_object_put(jsonmain);, jsonmain has ownership of jsontmp.

Related

Segmentation fault 11 in following code. How to avoid overflow?

void main(int argc, char* argv[]) {
char* hostname = (char*)malloc(sizeof(char)*1024);
hostname = getClientHostName("122.205.26.34");
printf("%s\n", hostname);
free(hostname);
}
char* getClientHostName(char* client_ip) {
char hostnames[5][2];
hostnames[0][0] = "122.205.26.34";
hostnames[0][1] = "aaaaa";
hostnames[1][0] = "120.205.36.30";
hostnames[1][1] = "bbbbb";
hostnames[2][0] = "120.205.16.36";
hostnames[2][1] = "ccccc";
hostnames[3][0] = "149.205.36.46";
hostnames[3][1] = "dddddd";
hostnames[4][0] = "169.205.36.33";
hostnames[4][1] = "eeeeee";
for(int i = 0; i<5; i++) {
if(!strcmp(hostnames[i][0], client_ip))
return (char*)hostnames[i][1];
}
return NULL;
}
Beginner in C.
I am not sure if there would be a better way to implement what I am trying to implement. The code is self-explanatory. Is there any way that I can predefine the size of hostname, using some general size of IP addresses, to avoid seg fault? Is there a even better way where I don't have to hardcode the size?
After fixing the compiler errors and warnings you get:
const char* getClientHostName(const char* client_ip) {
const char * hostnames[5][2];
hostnames[0][0] = "122.205.26.34";
hostnames[0][1] = "aaaaa";
hostnames[1][0] = "120.205.36.30";
hostnames[1][1] = "bbbbb";
hostnames[2][0] = "120.205.16.36";
hostnames[2][1] = "ccccc";
hostnames[3][0] = "149.205.36.46";
hostnames[3][1] = "dddddd";
hostnames[4][0] = "169.205.36.33";
hostnames[4][1] = "eeeeee";
for(int i = 0; i<5; i++) {
if(!strcmp(hostnames[i][0], client_ip))
return hostnames[i][1];
}
return NULL;
}
int main(int argc, char* argv[]) {
const char * hostname = getClientHostName("128.205.36.34");
printf("%s\n", hostname);
}
Is there a even better way where I don't have to hardcode the size?
Take the habit to compile with all warnings and debug info: gcc -Wall -Wextra -g with GCC. Improve the code to get no warnings at all.
If you want to get genuine IP addresses, this is operating system specific (since standard C11 don't know about IP addresses; check by reading n1570). On Linux you would use name service routines such as getaddrinfo(3) & getnameinfo(3) or the obsolete gethostbyname(3).
If this is just an exercise without actual relationship to TCP/IP sockets (see tcp(7), ip(7), socket(7)) you could store the table in some global array:
struct myipentry_st {
const char* myip_hostname;
const char* myip_address;
};
then define a global array containing them, with the convention of terminating it by some {NULL, NULL} entry:
const struct myipentry_st mytable[] = {
{"aaaaa", "122.205.26.34"},
{"bbbb", "120.205.36.30"},
/// etc
{NULL, NULL} // end marker
};
You'll better have a global or static variable (not an automatic one sitting on the call stack) because you don't want to fill it on every call to your getClientHostName.
Then your lookup routine (inefficient, since in linear time) would be:
const char* getClientHostName(char* client_ip) {
for (const struct myipentry_st* ent = mytable;
ent->myip_hostname != NULL;
ent++)
// the if below is the only statement of the body of `for` loop
if (!strcmp(ent->myip_address, client_ip))
return ent->myip_hostname;
// this happens after the `for` when nothing was found
return NULL;
}
You could even declare that table as a heap allocated pointer:
const struct myipentry_st**mytable;
then use calloc to allocate it and read its data from some text file.
Read the documentation of every standard or external function that you are using. Don't forget to check against failure (e.g. of calloc, like here). Avoid memory leaks by appropriate calls to free. Use the debugger gdb and valgrind. Beware of undefined behavior.
In the real world, you would have perhaps thousands of entries and you would perform the lookup many times (perhaps millions of times, e.g. once per every HTTP request in a web server or client). Then choose a better data structure (hash table or red-black tree perhaps). Read some Introduction to Algorithms.
Add * to type definition char * hostnames[5][2]. This must be array of pointers, not simple chars. Another necessary change is strcpy instead of = in strcpy( hostname, getClientHostName("122.205.26.34") );.
PS: Always try to compile with 0 compiler warnings, not only 0 errors!

Json parsing and string management in C

Considering the following functions:
int get_timestamp(json_object *json_obj, double *timestamp) {
json_object *value_obj;
int status;
if (json_object_object_get_ex(json_obj, "timestamp", &value_obj)) {
if (json_object_is_type(value_obj, json_type_double)) {
*timestamp = json_object_get_double(value_obj);
status = JSONPARSER_OK;
}
else
status = JSONPARSER_EBADTYPE;
} else
status = JSONPARSER_ENODENOTFOUND;
free(value_obj);
return status;
}
int get_display_name(json_object *json_obj, char **display_name) {
json_object *value_obj;
int status;
const char* holder;
if (json_object_object_get_ex(json_obj, "display_name", &value_obj)) {
if (json_object_is_type(value_obj, json_type_string)) {
// The returned string memory is managed by the json_object and will
// be freed when the reference count of the json_object drops to zero.
holder = json_object_get_string(value_obj);
strcpy(*display_name, holder);
status = JSONPARSER_OK;
}
else
status = JSONPARSER_EBADTYPE;
} else
status = JSONPARSER_ENODENOTFOUND;
free(value_obj);
return status;
}
int get_organization(json_object *json_obj, char **organization) {
json_object *value_obj;
int status;
const char* holder;
if (json_object_object_get_ex(json_obj, "organization", &value_obj)) {
if (json_object_is_type(value_obj, json_type_string)) {
// The returned string memory is managed by the json_object and will
// be freed when the reference count of the json_object drops to zero.
holder = json_object_get_string(value_obj);
strcpy(*organization, holder);
status = JSONPARSER_OK;
}
else
status = JSONPARSER_EBADTYPE;
} else
status = JSONPARSER_ENODENOTFOUND;
free(value_obj);
return status;
}
Used as:
json_object *response_obj, *idp_obj;
int status;
char *display_name;
char *organization;
response_obj = json_tokener_parse(raw_data);
json_object_object_get_ex(response_obj, "idp", &idp_obj);
get_timestamp(response_obj, timestamp);
get_display_name(idp_obj, &display_name);
get_organization(idp_obj, &organization);
free(idp_obj);
free(response_obj);
return status;
What happens:
1) by removing get_organization(idp_obj, &organization); everything seems work fine;
2) by removing get_display_name(idp_obj, &display_name); everything seems work fine again;
3) with the code "as is", there is an error on the strcpy used inside the method get_organization:
No source available for "__strcpy_sse2_unaligned() at 0x7ffff763f001"
I would really like to understand this behavior in order to improve my knowledge in this amazing but hard languages.
That error message is a debugger error message, because it's in a function which it can't locate source to. The only thing you need to do is to walk up the function call stack until you reach your code.
As for why the debugger stops in that function, that's really should be another question, but I'll answer it anyway: It's because of undefined behavior because the destination pointer you pass to it is an uninitialized local variable: display_name. In the code where you call get_display_name you declare the local variable display_name, but you don't initialize it. The value of uninitialized non-static local variable is indeterminate, and using them without initialization leads to undefined behavior.
You have basically two solutions to this problem: Either declare display_name as an array of a fixed size, or use make it point to valid allocated memory, for example by using malloc.
You will also have the same problem with the organization variable.

Invalid read in hash table

I'm using uthash.h in order to store my application's configuration. As the config comes from a file that is read at runtime, the keys and values within the hash are both dynamically allocated char *'s:
typedef struct config_entry {
char *name;
char *value;
UT_hash_handle hh;
} CONFIG_ENTRY;
As explained in the user guide, I implemented my own function to add keys to the config-hash that ensures uniqueness. Here it is:
void cfg_put( char *name, char *value, FREE_FLAGS flags ) {
CONFIG_ENTRY *entry;
//first, check if the key is already in the hash
HASH_FIND_STR( config_, name, entry );
if( entry == NULL ) {
//key doesn't exist yet => create new one
entry = (CONFIG_ENTRY *)malloc( sizeof( CONFIG_ENTRY ) );
entry->name = name;
HASH_ADD_KEYPTR( hh, config_, entry->name, strlen(entry->name), entry );
} else {
//key exists => possibly free existing pointers before setting value
if( (flags & FREE_NAME) == FREE_NAME ) { //
free( entry->name ); // these lines seem to be
} // problematic.
entry->name = name; //
if( (flags & FREE_VALUE) == FREE_VALUE ) {
free( entry->value );
}
}
//Finally, set the value
entry->value = value;
}
I also wrote up some testcases for checking my implementation, and they seem to run just fine. However, if I run the tests using valgrind to check for memleaks, I always get the following:
==2561== Invalid read of size 1
==2561== at 0x4026097: bcmp (mc_replace_strmem.c:541)
==2561== by 0x804ADF5: cfg_get (in /home/gj/..../test/config_test)
==2561== by 0x804B2C7: test_config1 (in /home/..../test/config_test)
==2561== by 0x402E446: run_single_test (in /usr/local/lib/libcunit.so.1.0.1)
[...]
==2561== Address 0x4194210 is 0 bytes inside a block of size 4 free'd
==2561== at 0x4023B6A: free (vg_replace_malloc.c:366)
==2561== by 0x804A872: cfg_put (in /home/..../test/config_test)
==2561== by 0x804B27D: test_config1 (in /home/..../test/config_test)
==2561== by 0x402E446: run_single_test (in /usr/local/lib/libcunit.so.1.0.1)
[...]
Here's the test case and the implementation of cfg_get for completeness:
void test_config1( void ) {
cfg_clear( FREE_ALL );
cfg_put( strdup("foo"), "bar", FREE_NONE );
CU_ASSERT_EQUAL( cfg_count(), 1 );
CU_ASSERT_STRING_EQUAL( cfg_get("foo"), "bar" );
cfg_dump();
cfg_put( "foo", "baz", FREE_NAME );
CU_ASSERT_EQUAL( cfg_count(), 2 );
CU_ASSERT_STRING_EQUAL( cfg_get("foo"), "baz" );
cfg_clear( FREE_NONE );
cfg_dump();
}
cfg_get:
char *cfg_get( const char *name ) {
CONFIG_ENTRY *entry = NULL;
HASH_FIND_STR( config_, name, entry );
if( entry ) {
return entry->value;
} else {
return NULL;
}
}
Somehow, it seems I'm accessing the old name-pointer in cfg_get after I've overwritten it in cfg_put. The problem only occurs for the name, not for the value. I'm too stupid to figure it out, thx for any advice.
You'll have to provide the complete program — that is, a complete minimal example that reproduces the valgrind issue. The code you've posted in your question looks fine, so the bug must be hiding somewhere else; e.g. in the code of cfg_clear() or cfg_count().
(Originally I thought that cfg_count() must be return HASH_COUNT(config_); — but that implementation wouldn't pass your test case, so you must be doing something weirder. Which means cfg_count is probably the wrong name for that function anyway.)
Stylistically, you might find your code easier to debug if you avoided the use of global variables (config_), and definitely you'd find it easier if you stored the "necessity to free this value" bits directly alongside the "value" bits, instead of requiring the user to keep track of FREE_NAME, FREE_VALUE, etc., on his own. That is, instead of
typedef struct config_entry {
char *name;
char *value;
UT_hash_handle hh;
} CONFIG_ENTRY;
void cfg_put(char *name, char *value, FREE_FLAGS flags);
void cfg_clear(FREE_FLAGS flags);
you should provide merely
typedef struct config_entry {
char *name;
char *value;
UT_hash_handle hh;
bool must_free_name;
bool must_free_value;
} CONFIG_ENTRY;
void cfg_put(char *name, char *value, FREE_FLAGS flags);
void cfg_clear(void);
at which point your test case becomes the more manageable
void test_config1()
{
cfg_clear(); // use the stored bits to figure out what needs freeing
cfg_put(strdup("foo"), "bar", FREE_NAME); // name is alloc'ed, so name must be freed later
CU_ASSERT_EQUAL( cfg_count(), 1 );
CU_ASSERT_STRING_EQUAL( cfg_get("foo"), "bar" );
cfg_put("foo", "baz", FREE_NONE); // neither name nor value is alloc'ed
CU_ASSERT_EQUAL( cfg_count(), 2 );
CU_ASSERT_STRING_EQUAL( cfg_get("foo"), "baz" );
}
There is a problem in your config_put() function: it modifies the key of an item already inserted in to the hash. You are not supposed to do this. It may be OK to change the name pointer to one that points to the same string, but it may be not, the implementation of uthash.h is a bit obscure.
I suggest you change the API so config_put() does all the string management, letting the config_ hash own all the strings, and no longer call strdup() in test_config1. This is much simpler and avoids the potentially complicated and error prone tracking of the life cycle of string values outside of the hash structure:
void cfg_put(const char *name, const char *value) {
CONFIG_ENTRY *entry;
//first, check if the key is already in the hash
HASH_FIND_STR(config_, name, entry);
if (entry == NULL) {
//key doesn't exist yet => create new one
entry = malloc(sizeof(*entry));
entry->name = strdup(name);
HASH_ADD_KEYPTR(hh, config_, entry->name, strlen(entry->name), entry );
} else {
//key exists => free existing value pointer if any
free(entry->value);
}
//Finally, set the value
entry->value = value ? strdup(value) : NULL;
}

Best practice for managing allocated variables when writing a small library

I'm currently writing a little library of secure char and secure list (just .c/.h files that I will add to future projects) and something is bothering me, I know that some of you will think it is subjective but I think there is a "real" best way to do it. I've searched but there is nothing that give me a close answer. Here is a sample of my code.
The struct and functions used :
typedef struct _secure_list
{
cookie secret; // MUST be set to Cookie
secure_char * schar;
struct _secure_list * next;
} secure_list;
typedef struct _secure_char
{
int length; // number of characters in the string
char * str; // the string (no \0 byte at the end of the string)
} secure_char;
/**
* Create a secure list with schar
* Initialize Cookie on first use
**/
ret_value createSecureList( secure_char * scIn, secure_list ** slist )
I think there is two possible ways to write the createSecureList function :
// FIRST WAY
ret_value createSecureList( secure_char * scIn, secure_list ** slist )
{
(*slist) = NULL;
(*slist) = (secure_list *) malloc( sizeof(secure_list) );
// we copy the secure_char so it can be freed in the caller
createSecureChar("",&((*slist)->schar));
concat2SecureChar(&((*slist)->schar), scIn);
...
 }
// SECOND WAY
ret_value createSecureList( secure_char * scIn, secure_list ** slist )
{
(*slist) = NULL;
(*slist) = (secure_list *) malloc( sizeof(secure_list) );
(*slist)->schar = scIn;
...
 }
In my main() I have :
void main()
{
secure_list * slist_Test;
secure_char * schar_Test;
....
createSecureChar("test test",&schar_test);
createSecureList(schar_Test,&slist_Test);
....
}
My problem is that despite the fact the second way is easier to code and understand, the secure list which is a linked list will point to the same memory space as schar_Test, so if we free one of them, we free both. The first way basically create a copy of schar_Test so it can be freed in the calling function.
Can someone tell me which is the "right" way ?

Passing queue as parameter in c

I am passing queues like these between source files a.c and b.c
File : a.c
sq[a]=new_queue();
pthread_create(&st[a],NULL,sendPacket,sq[a]);
File : b.c
void *sendPacket(void *queue){
/* here i need to know which queue has come ,determine
the index of queue how can I do it? */
}
Create a more high-level representation of your queue. It seems the queue can be a void * (you're not showing its actual type, i.e. what does the new_queue() call return?), so embed that in a structure while adding the additional parameters:
struct queue_state {
void *queue;
int index;
};
Then instantiate a structure, and pass a pointer to it to the thread function:
struct queue_state qsa = malloc(sizeof *qsa);
if(qsa != NULL)
{
qsa->queue = new_queue();
qsa->index = 4711; /* or whatever */
pthread_create(&st[a], NULL, sendPacket, qsa);
}
Then the thread function can use the struct declaration to access all the fields. Of course, the declaration needs to be in a shared header (say queue.h) which is included from both C files.
Your question description is very rough. But at least from what I understand, you actually need to pass 2 parameters to your function: the (pointer to) queue (which seems an array for me), and the index within this queue.
You may not pack both your parameters in a single variable of type void*. What you may do is declare a struct with all the needed parameters, fill it, and pass a pointer to it to your thread.
Like this (error handling omitted):
struct Params
{
queue* m_Queue;
size_t m_Idx;
};
// ...
Params* pParams = new Params;
pParams->m_Queue = sq;
pParams->m_Idx = a;
pthread_create(&st[a],NULL,sendPacket, pParams);
void *sendPacket(void *pPtr)
{
Params* pParams = (Params*) pPtr;
// ...
delete pParams;
}
Probably it is easier if you just pass the index to the function:
void *sendPacket(int queue_idx) {
queue_t *queue = &sq[queue_idx];
}
If in b.c you have access to sq, you can just pass the index to the queue. Otherwise you can pass a struct containing the actual queue and the index

Resources