Fix invalid object key hashing in json_unpack() strict checking mode
The keys which are stored temporarily to a hashtable to make sure that all object keys are unpacked, were hashed with the object key hashing function. It is meant to compute hashes for object_key_t values, and it works incorrectly for plain strings. Fixed by introducing suitable functions for hashing and comparing strings for string-keyed hashtables.
This commit is contained in:
@@ -66,8 +66,8 @@ typedef struct {
|
||||
#define json_to_real(json_) container_of(json_, json_real_t, json)
|
||||
#define json_to_integer(json_) container_of(json_, json_integer_t, json)
|
||||
|
||||
size_t jsonp_hash_key(const void *ptr);
|
||||
int jsonp_key_equal(const void *ptr1, const void *ptr2);
|
||||
size_t jsonp_hash_str(const void *ptr);
|
||||
int jsonp_str_equal(const void *ptr1, const void *ptr2);
|
||||
|
||||
typedef struct {
|
||||
size_t serial;
|
||||
|
||||
@@ -233,7 +233,7 @@ static int unpack_object(scanner_t *s, json_t *root, va_list *ap)
|
||||
*/
|
||||
hashtable_t key_set;
|
||||
|
||||
if(hashtable_init(&key_set, jsonp_hash_key, jsonp_key_equal, NULL, NULL)) {
|
||||
if(hashtable_init(&key_set, jsonp_hash_str, jsonp_str_equal, NULL, NULL)) {
|
||||
set_error(s, "<internal>", "Out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
35
src/value.c
35
src/value.c
@@ -26,15 +26,10 @@ static JSON_INLINE void json_init(json_t *json, json_type type)
|
||||
|
||||
/*** object ***/
|
||||
|
||||
/* This macro just returns a pointer that's a few bytes backwards from
|
||||
string. This makes it possible to pass a pointer to object_key_t
|
||||
when only the string inside it is used, without actually creating
|
||||
an object_key_t instance. */
|
||||
#define string_to_key(string) container_of(string, object_key_t, key)
|
||||
|
||||
size_t jsonp_hash_key(const void *ptr)
|
||||
/* From http://www.cse.yorku.ca/~oz/hash.html */
|
||||
size_t jsonp_hash_str(const void *ptr)
|
||||
{
|
||||
const char *str = ((const object_key_t *)ptr)->key;
|
||||
const char *str = (const char *)ptr;
|
||||
|
||||
size_t hash = 5381;
|
||||
size_t c;
|
||||
@@ -48,10 +43,26 @@ size_t jsonp_hash_key(const void *ptr)
|
||||
return hash;
|
||||
}
|
||||
|
||||
int jsonp_key_equal(const void *ptr1, const void *ptr2)
|
||||
int jsonp_str_equal(const void *ptr1, const void *ptr2)
|
||||
{
|
||||
return strcmp(((const object_key_t *)ptr1)->key,
|
||||
((const object_key_t *)ptr2)->key) == 0;
|
||||
return strcmp((const char *)ptr1, (const char *)ptr2) == 0;
|
||||
}
|
||||
|
||||
/* This macro just returns a pointer that's a few bytes backwards from
|
||||
string. This makes it possible to pass a pointer to object_key_t
|
||||
when only the string inside it is used, without actually creating
|
||||
an object_key_t instance. */
|
||||
#define string_to_key(string) container_of(string, object_key_t, key)
|
||||
|
||||
static size_t hash_key(const void *ptr)
|
||||
{
|
||||
return jsonp_hash_str(((const object_key_t *)ptr)->key);
|
||||
}
|
||||
|
||||
static int key_equal(const void *ptr1, const void *ptr2)
|
||||
{
|
||||
return jsonp_str_equal(((const object_key_t *)ptr1)->key,
|
||||
((const object_key_t *)ptr2)->key);
|
||||
}
|
||||
|
||||
static void value_decref(void *value)
|
||||
@@ -67,7 +78,7 @@ json_t *json_object(void)
|
||||
json_init(&object->json, JSON_OBJECT);
|
||||
|
||||
if(hashtable_init(&object->hashtable,
|
||||
jsonp_hash_key, jsonp_key_equal,
|
||||
hash_key, key_equal,
|
||||
jsonp_free, value_decref))
|
||||
{
|
||||
jsonp_free(object);
|
||||
|
||||
Reference in New Issue
Block a user