diff --git a/.gitignore b/.gitignore index ba9d0ae..aab4b40 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/jansson-2.4.tar.bz2 +SOURCES/jansson-2.10.tar.bz2 diff --git a/.jansson.metadata b/.jansson.metadata index baf7b40..e4ed455 100644 --- a/.jansson.metadata +++ b/.jansson.metadata @@ -1 +1 @@ -f11ff89dd484d89210d9f52a9ccc2ce2b9d2c1ae SOURCES/jansson-2.4.tar.bz2 +d8eb6d1144d7392673f3d2a25bb1cf9e8454e252 SOURCES/jansson-2.10.tar.bz2 diff --git a/SOURCES/0001-Change-hash-function-randomize-hashes.patch b/SOURCES/0001-Change-hash-function-randomize-hashes.patch deleted file mode 100644 index 3cc723a..0000000 --- a/SOURCES/0001-Change-hash-function-randomize-hashes.patch +++ /dev/null @@ -1,1198 +0,0 @@ -From 08777c4edd48739d56bf5f5d492fa753722026ca Mon Sep 17 00:00:00 2001 -From: Jiri Pirko -Date: Thu, 13 Feb 2014 08:45:45 +0100 -Subject: [patch jansson] Change hash function, randomize hashes - -BZ1063831 -CVE-2013-6401 - -upstream commit 8f80c2d83808150724d31793e6ade92749b1faa4 -Author: Petri Lehtinen -Date: Tue Jan 14 11:16:39 2014 +0200 - - CVE-2013-6401: Change hash function, randomize hashes - - Thanks to Florian Weimer and Eric Sesterhenn for reporting, reviewing - and testing. - -Signed-off-by: Jiri Pirko ---- - -diff --git a/configure.ac b/configure.ac -index 3b595a4..3540824 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -14,10 +14,11 @@ AM_CONDITIONAL([GCC], [test x$GCC = xyes]) - # Checks for libraries. - - # Checks for header files. --AC_CHECK_HEADERS([locale.h]) -+AC_CHECK_HEADERS([endian.h fcntl.h locale.h sched.h unistd.h sys/param.h sys/stat.h sys/time.h sys/types.h]) - - # Checks for typedefs, structures, and compiler characteristics. - AC_TYPE_INT32_T -+AC_TYPE_UINT32_T - AC_TYPE_LONG_LONG_INT - - AC_C_INLINE -@@ -29,7 +30,31 @@ esac - AC_SUBST([json_inline]) - - # Checks for library functions. --AC_CHECK_FUNCS([strtoll localeconv]) -+AC_CHECK_FUNCS([close getpid gettimeofday localeconv open read sched_yield strtoll]) -+ -+AC_MSG_CHECKING([for gcc __sync builtins]) -+have_sync_builtins=no -+AC_TRY_LINK( -+ [], [unsigned long val; __sync_bool_compare_and_swap(&val, 0, 1);], -+ [have_sync_builtins=yes], -+) -+if test "x$have_sync_builtins" = "xyes"; then -+ AC_DEFINE([HAVE_SYNC_BUILTINS], [1], -+ [Define to 1 if gcc's __sync builtins are available]) -+fi -+AC_MSG_RESULT([$have_sync_builtins]) -+ -+AC_MSG_CHECKING([for gcc __atomic builtins]) -+have_atomic_builtins=no -+AC_TRY_LINK( -+ [], [char l; unsigned long v; __atomic_test_and_set(&l, __ATOMIC_RELAXED); __atomic_store_n(&v, 1, __ATOMIC_ACQ_REL); __atomic_load_n(&v, __ATOMIC_ACQUIRE);], -+ [have_atomic_builtins=yes], -+) -+if test "x$have_atomic_builtins" = "xyes"; then -+ AC_DEFINE([HAVE_ATOMIC_BUILTINS], [1], -+ [Define to 1 if gcc's __atomic builtins are available]) -+fi -+AC_MSG_RESULT([$have_atomic_builtins]) - - case "$ac_cv_type_long_long_int$ac_cv_func_strtoll" in - yesyes) json_have_long_long=1;; -@@ -43,6 +68,27 @@ case "$ac_cv_header_locale_h$ac_cv_func_localeconv" in - esac - AC_SUBST([json_have_localeconv]) - -+# Features -+AC_ARG_ENABLE([urandom], -+ [AS_HELP_STRING([--disable-urandom], -+ [Don't use /dev/urandom to seed the hash function])], -+ [use_urandom=$enableval], [use_urandom=yes]) -+ -+if test "x$use_urandom" = xyes; then -+AC_DEFINE([USE_URANDOM], [1], -+ [Define to 1 if /dev/urandom should be used for seeding the hash function]) -+fi -+ -+AC_ARG_ENABLE([windows-cryptoapi], -+ [AS_HELP_STRING([--disable-windows-cryptoapi], -+ [Don't use CryptGenRandom to seed the hash function])], -+ [use_windows_cryptoapi=$enableval], [use_windows_cryptoapi=yes]) -+ -+if test "x$use_windows_cryptoapi" = xyes; then -+AC_DEFINE([USE_WINDOWS_CRYPTOAPI], [1], -+ [Define to 1 if CryptGenRandom should be used for seeding the hash function]) -+fi -+ - AC_CONFIG_FILES([ - jansson.pc - Makefile -diff --git a/src/Makefile.am b/src/Makefile.am -index 9d040f6..cc2aa1c 100644 ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -8,6 +8,7 @@ libjansson_la_SOURCES = \ - error.c \ - hashtable.c \ - hashtable.h \ -+ hashtable_seed.c \ - jansson_private.h \ - load.c \ - memory.c \ -diff --git a/src/hashtable.c b/src/hashtable.c -index 76cf69b..2e09326 100644 ---- a/src/hashtable.c -+++ b/src/hashtable.c -@@ -5,8 +5,17 @@ - * it under the terms of the MIT license. See LICENSE for details. - */ - -+#if HAVE_CONFIG_H -+#include -+#endif -+ - #include - #include -+ -+#if HAVE_STDINT_H -+#include -+#endif -+ - #include /* for JSON_INLINE */ - #include "jansson_private.h" /* for container_of() */ - #include "hashtable.h" -@@ -15,24 +24,13 @@ typedef struct hashtable_list list_t; - typedef struct hashtable_pair pair_t; - typedef struct hashtable_bucket bucket_t; - --#define list_to_pair(list_) container_of(list_, pair_t, list) -- --/* From http://www.cse.yorku.ca/~oz/hash.html */ --static size_t hash_str(const void *ptr) --{ -- const char *str = (const char *)ptr; -- -- size_t hash = 5381; -- size_t c; -+extern volatile uint32_t hashtable_seed; - -- while((c = (size_t)*str)) -- { -- hash = ((hash << 5) + hash) + c; -- str++; -- } -+/* Implementation of the hash function */ -+#include "lookup3.h" - -- return hash; --} -+#define list_to_pair(list_) container_of(list_, pair_t, list) -+#define hash_str(key) ((size_t)hashlittle((key), strlen(key), hashtable_seed)) - - static JSON_INLINE void list_init(list_t *list) - { -@@ -74,19 +72,6 @@ static void insert_to_bucket(hashtable_t *hashtable, bucket_t *bucket, - } - } - --static size_t primes[] = { -- 5, 13, 23, 53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593, -- 49157, 98317, 196613, 393241, 786433, 1572869, 3145739, 6291469, -- 12582917, 25165843, 50331653, 100663319, 201326611, 402653189, -- 805306457, 1610612741 --}; -- --static JSON_INLINE size_t num_buckets(hashtable_t *hashtable) --{ -- return primes[hashtable->num_buckets]; --} -- -- - static pair_t *hashtable_find_pair(hashtable_t *hashtable, bucket_t *bucket, - const char *key, size_t hash) - { -@@ -120,7 +105,7 @@ static int hashtable_do_del(hashtable_t *hashtable, - bucket_t *bucket; - size_t index; - -- index = hash % num_buckets(hashtable); -+ index = hash & hashmask(hashtable->order); - bucket = &hashtable->buckets[index]; - - pair = hashtable_find_pair(hashtable, bucket, key, hash); -@@ -167,14 +152,14 @@ static int hashtable_do_rehash(hashtable_t *hashtable) - - jsonp_free(hashtable->buckets); - -- hashtable->num_buckets++; -- new_size = num_buckets(hashtable); -+ hashtable->order++; -+ new_size = hashsize(hashtable->order); - - hashtable->buckets = jsonp_malloc(new_size * sizeof(bucket_t)); - if(!hashtable->buckets) - return -1; - -- for(i = 0; i < num_buckets(hashtable); i++) -+ for(i = 0; i < hashsize(hashtable->order); i++) - { - hashtable->buckets[i].first = hashtable->buckets[i].last = - &hashtable->list; -@@ -199,14 +184,14 @@ int hashtable_init(hashtable_t *hashtable) - size_t i; - - hashtable->size = 0; -- hashtable->num_buckets = 0; /* index to primes[] */ -- hashtable->buckets = jsonp_malloc(num_buckets(hashtable) * sizeof(bucket_t)); -+ hashtable->order = 3; -+ hashtable->buckets = jsonp_malloc(hashsize(hashtable->order) * sizeof(bucket_t)); - if(!hashtable->buckets) - return -1; - - list_init(&hashtable->list); - -- for(i = 0; i < num_buckets(hashtable); i++) -+ for(i = 0; i < hashsize(hashtable->order); i++) - { - hashtable->buckets[i].first = hashtable->buckets[i].last = - &hashtable->list; -@@ -230,12 +215,12 @@ int hashtable_set(hashtable_t *hashtable, - size_t hash, index; - - /* rehash if the load ratio exceeds 1 */ -- if(hashtable->size >= num_buckets(hashtable)) -+ if(hashtable->size >= hashsize(hashtable->order)) - if(hashtable_do_rehash(hashtable)) - return -1; - - hash = hash_str(key); -- index = hash % num_buckets(hashtable); -+ index = hash & hashmask(hashtable->order); - bucket = &hashtable->buckets[index]; - pair = hashtable_find_pair(hashtable, bucket, key, hash); - -@@ -273,7 +258,7 @@ void *hashtable_get(hashtable_t *hashtable, const char *key) - bucket_t *bucket; - - hash = hash_str(key); -- bucket = &hashtable->buckets[hash % num_buckets(hashtable)]; -+ bucket = &hashtable->buckets[hash & hashmask(hashtable->order)]; - - pair = hashtable_find_pair(hashtable, bucket, key, hash); - if(!pair) -@@ -294,7 +279,7 @@ void hashtable_clear(hashtable_t *hashtable) - - hashtable_do_clear(hashtable); - -- for(i = 0; i < num_buckets(hashtable); i++) -+ for(i = 0; i < hashsize(hashtable->order); i++) - { - hashtable->buckets[i].first = hashtable->buckets[i].last = - &hashtable->list; -@@ -316,7 +301,7 @@ void *hashtable_iter_at(hashtable_t *hashtable, const char *key) - bucket_t *bucket; - - hash = hash_str(key); -- bucket = &hashtable->buckets[hash % num_buckets(hashtable)]; -+ bucket = &hashtable->buckets[hash & hashmask(hashtable->order)]; - - pair = hashtable_find_pair(hashtable, bucket, key, hash); - if(!pair) -diff --git a/src/hashtable.h b/src/hashtable.h -index de1df26..aec978d 100644 ---- a/src/hashtable.h -+++ b/src/hashtable.h -@@ -32,7 +32,7 @@ struct hashtable_bucket { - typedef struct hashtable { - size_t size; - struct hashtable_bucket *buckets; -- size_t num_buckets; /* index to primes[] */ -+ size_t order; /* hashtable has pow(2, order) buckets */ - struct hashtable_list list; - } hashtable_t; - -@@ -40,6 +40,7 @@ typedef struct hashtable { - #define hashtable_key_to_iter(key_) \ - (&(container_of(key_, struct hashtable_pair, key)->list)) - -+ - /** - * hashtable_init - Initialize a hashtable object - * -diff --git a/src/hashtable_seed.c b/src/hashtable_seed.c -new file mode 100644 -index 0000000..a07d145 ---- /dev/null -+++ b/src/hashtable_seed.c -@@ -0,0 +1,278 @@ -+/* Generate sizeof(uint32_t) bytes of as random data as possible to seed -+ the hash function. -+*/ -+ -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ -+#include -+#include -+ -+#ifdef HAVE_STDINT_H -+#include -+#endif -+ -+#ifdef HAVE_FCNTL_H -+#include -+#endif -+ -+#ifdef HAVE_SCHED_H -+#include -+#endif -+ -+#ifdef HAVE_UNISTD_H -+#include -+#endif -+ -+#ifdef HAVE_SYS_STAT_H -+#include -+#endif -+ -+#ifdef HAVE_SYS_TIME_H -+#include -+#endif -+ -+#ifdef HAVE_SYS_TYPES_H -+#include -+#endif -+ -+#if defined(_WIN32) -+/* For _getpid() */ -+#include -+#endif -+ -+#include "jansson.h" -+ -+ -+static uint32_t buf_to_uint32(char *data) { -+ size_t i; -+ uint32_t result = 0; -+ -+ for (i = 0; i < sizeof(uint32_t); i++) -+ result = (result << 8) | (unsigned char)data[i]; -+ -+ return result; -+} -+ -+ -+ -+/* /dev/urandom */ -+#if !defined(_WIN32) && defined(USE_URANDOM) -+static int seed_from_urandom(uint32_t *seed) { -+ /* Use unbuffered I/O if we have open(), close() and read(). Otherwise -+ fall back to fopen() */ -+ -+ char data[sizeof(uint32_t)]; -+ int ok; -+ -+#if defined(HAVE_OPEN) && defined(HAVE_CLOSE) && defined(HAVE_READ) -+ int urandom; -+ urandom = open("/dev/urandom", O_RDONLY); -+ if (urandom == -1) -+ return 1; -+ -+ ok = read(urandom, data, sizeof(uint32_t)) == sizeof(uint32_t); -+ close(urandom); -+#else -+ FILE *urandom; -+ -+ urandom = fopen("/dev/urandom", "rb"); -+ if (!urandom) -+ return 1; -+ -+ ok = fread(data, 1, sizeof(uint32_t), urandom) == sizeof(uint32_t); -+ fclose(urandom); -+#endif -+ -+ if (!ok) -+ return 1; -+ -+ *seed = buf_to_uint32(data); -+ return 0; -+} -+#endif -+ -+/* Windows Crypto API */ -+#if defined(_WIN32) && defined(USE_WINDOWS_CRYPTOAPI) -+#include -+#include -+ -+typedef BOOL (WINAPI *CRYPTACQUIRECONTEXTA)(HCRYPTPROV *phProv, LPCSTR pszContainer, LPCSTR pszProvider, DWORD dwProvType, DWORD dwFlags); -+typedef BOOL (WINAPI *CRYPTGENRANDOM)(HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer); -+typedef BOOL (WINAPI *CRYPTRELEASECONTEXT)(HCRYPTPROV hProv, DWORD dwFlags); -+ -+static int seed_from_windows_cryptoapi(uint32_t *seed) -+{ -+ HINSTANCE hAdvAPI32 = NULL; -+ CRYPTACQUIRECONTEXTA pCryptAcquireContext = NULL; -+ CRYPTGENRANDOM pCryptGenRandom = NULL; -+ CRYPTRELEASECONTEXT pCryptReleaseContext = NULL; -+ HCRYPTPROV hCryptProv = 0; -+ BYTE data[sizeof(uint32_t)]; -+ int ok; -+ -+ hAdvAPI32 = GetModuleHandle("advapi32.dll"); -+ if(hAdvAPI32 == NULL) -+ return 1; -+ -+ pCryptAcquireContext = (CRYPTACQUIRECONTEXTA)GetProcAddress(hAdvAPI32, "CryptAcquireContextA"); -+ if (!pCryptAcquireContext) -+ return 1; -+ -+ pCryptGenRandom = (CRYPTGENRANDOM)GetProcAddress(hAdvAPI32, "CryptGenRandom"); -+ if (!pCryptGenRandom) -+ return 1; -+ -+ pCryptReleaseContext = (CRYPTRELEASECONTEXT)GetProcAddress(hAdvAPI32, "CryptReleaseContext"); -+ if (!pCryptReleaseContext) -+ return 1; -+ -+ if (!pCryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) -+ return 1; -+ -+ ok = CryptGenRandom(hCryptProv, sizeof(uint32_t), data); -+ pCryptReleaseContext(hCryptProv, 0); -+ -+ if (!ok) -+ return 1; -+ -+ *seed = buf_to_uint32((char *)data); -+ return 0; -+} -+#endif -+ -+/* gettimeofday() and getpid() */ -+static int seed_from_timestamp_and_pid(uint32_t *seed) { -+#ifdef HAVE_GETTIMEOFDAY -+ /* XOR of seconds and microseconds */ -+ struct timeval tv; -+ gettimeofday(&tv, NULL); -+ *seed = (uint32_t)tv.tv_sec ^ (uint32_t)tv.tv_usec; -+#else -+ /* Seconds only */ -+ *seed = (uint32_t)time(NULL); -+#endif -+ -+ /* XOR with PID for more randomness */ -+#if defined(_WIN32) -+ *seed ^= (uint32_t)_getpid(); -+#elif defined(HAVE_GETPID) -+ *seed ^= (uint32_t)getpid(); -+#endif -+ -+ return 0; -+} -+ -+static uint32_t generate_seed() { -+ uint32_t seed; -+ int done = 0; -+ -+#if !defined(_WIN32) && defined(USE_URANDOM) -+ if (!done && seed_from_urandom(&seed) == 0) -+ done = 1; -+#endif -+ -+#if defined(_WIN32) && defined(USE_WINDOWS_CRYPTOAPI) -+ if (!done && seed_from_windows_cryptoapi(&seed) == 0) -+ done = 1; -+#endif -+ -+ if (!done) { -+ /* Fall back to timestamp and PID if no better randomness is -+ available */ -+ seed_from_timestamp_and_pid(&seed); -+ } -+ -+ /* Make sure the seed is never zero */ -+ if (seed == 0) -+ seed = 1; -+ -+ return seed; -+} -+ -+ -+volatile uint32_t hashtable_seed = 0; -+ -+#if defined(HAVE_ATOMIC_BUILTINS) && (defined(HAVE_SCHED_YIELD) || !defined(_WIN32)) -+static volatile char seed_initialized = 0; -+ -+void json_object_seed(size_t seed) { -+ uint32_t new_seed = (uint32_t)seed; -+ -+ if (hashtable_seed == 0) { -+ if (__atomic_test_and_set(&seed_initialized, __ATOMIC_RELAXED) == 0) { -+ /* Do the seeding ourselves */ -+ if (new_seed == 0) -+ new_seed = generate_seed(); -+ -+ __atomic_store_n(&hashtable_seed, new_seed, __ATOMIC_ACQ_REL); -+ } else { -+ /* Wait for another thread to do the seeding */ -+ do { -+#ifdef HAVE_SCHED_YIELD -+ sched_yield(); -+#endif -+ } while(__atomic_load_n(&hashtable_seed, __ATOMIC_ACQUIRE) == 0); -+ } -+ } -+} -+#elif defined(HAVE_SYNC_BUILTINS) && (defined(HAVE_SCHED_YIELD) || !defined(_WIN32)) -+void json_object_seed(size_t seed) { -+ uint32_t new_seed = (uint32_t)seed; -+ -+ if (hashtable_seed == 0) { -+ if (new_seed == 0) { -+ /* Explicit synchronization fences are not supported by the -+ __sync builtins, so every thread getting here has to -+ generate the seed value. -+ */ -+ new_seed = generate_seed(); -+ } -+ -+ do { -+ if (__sync_bool_compare_and_swap(&hashtable_seed, 0, new_seed)) { -+ /* We were the first to seed */ -+ break; -+ } else { -+ /* Wait for another thread to do the seeding */ -+#ifdef HAVE_SCHED_YIELD -+ sched_yield(); -+#endif -+ } -+ } while(hashtable_seed == 0); -+ } -+} -+#elif defined(_WIN32) -+static long seed_initialized = 0; -+void json_object_seed(size_t seed) { -+ uint32_t new_seed = (uint32_t)seed; -+ -+ if (hashtable_seed == 0) { -+ if (InterlockedIncrement(&seed_initialized) == 1) { -+ /* Do the seeding ourselves */ -+ if (new_seed == 0) -+ new_seed = generate_seed(); -+ -+ hashtable_seed = new_seed; -+ } else { -+ /* Wait for another thread to do the seeding */ -+ do { -+ SwitchToThread(); -+ } while (hashtable_seed == 0); -+ } -+ } -+} -+#else -+/* Fall back to a thread-unsafe version */ -+void json_object_seed(size_t seed) { -+ uint32_t new_seed = (uint32_t)seed; -+ -+ if (hashtable_seed == 0) { -+ if (new_seed == 0) -+ new_seed = generate_seed(); -+ -+ hashtable_seed = new_seed; -+ } -+} -+#endif -diff --git a/src/jansson.def b/src/jansson.def -index 6b2c8a7..a43ba2d 100644 ---- a/src/jansson.def -+++ b/src/jansson.def -@@ -43,6 +43,7 @@ EXPORTS - json_object_iter_value - json_object_iter_set_new - json_object_key_to_iter -+ json_object_seed - json_dumps - json_dumpf - json_dump_file -diff --git a/src/jansson.h b/src/jansson.h -index 352c6ce..d9c56f3 100644 ---- a/src/jansson.h -+++ b/src/jansson.h -@@ -124,6 +124,7 @@ typedef struct { - - /* getters, setters, manipulation */ - -+void json_object_seed(size_t seed); - size_t json_object_size(const json_t *object); - json_t *json_object_get(const json_t *object, const char *key); - int json_object_set_new(json_t *object, const char *key, json_t *value); -diff --git a/src/lookup3.h b/src/lookup3.h -new file mode 100644 -index 0000000..dc76138 ---- /dev/null -+++ b/src/lookup3.h -@@ -0,0 +1,366 @@ -+/* -+------------------------------------------------------------------------------- -+lookup3.c, by Bob Jenkins, May 2006, Public Domain. -+ -+These are functions for producing 32-bit hashes for hash table lookup. -+hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() -+are externally useful functions. Routines to test the hash are included -+if SELF_TEST is defined. You can use this free for any purpose. It's in -+the public domain. It has no warranty. -+ -+You probably want to use hashlittle(). hashlittle() and hashbig() -+hash byte arrays. hashlittle() is is faster than hashbig() on -+little-endian machines. Intel and AMD are little-endian machines. -+On second thought, you probably want hashlittle2(), which is identical to -+hashlittle() except it returns two 32-bit hashes for the price of one. -+You could implement hashbig2() if you wanted but I haven't bothered here. -+ -+If you want to find a hash of, say, exactly 7 integers, do -+ a = i1; b = i2; c = i3; -+ mix(a,b,c); -+ a += i4; b += i5; c += i6; -+ mix(a,b,c); -+ a += i7; -+ final(a,b,c); -+then use c as the hash value. If you have a variable length array of -+4-byte integers to hash, use hashword(). If you have a byte array (like -+a character string), use hashlittle(). If you have several byte arrays, or -+a mix of things, see the comments above hashlittle(). -+ -+Why is this so big? I read 12 bytes at a time into 3 4-byte integers, -+then mix those integers. This is fast (you can do a lot more thorough -+mixing with 12*3 instructions on 3 integers than you can with 3 instructions -+on 1 byte), but shoehorning those bytes into integers efficiently is messy. -+------------------------------------------------------------------------------- -+*/ -+ -+#include -+ -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ -+#ifdef HAVE_STDINT_H -+#include /* defines uint32_t etc */ -+#endif -+ -+#ifdef HAVE_SYS_PARAM_H -+#include /* attempt to define endianness */ -+#endif -+ -+#ifdef HAVE_ENDIAN_H -+# include /* attempt to define endianness */ -+#endif -+ -+/* -+ * My best guess at if you are big-endian or little-endian. This may -+ * need adjustment. -+ */ -+#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \ -+ __BYTE_ORDER == __LITTLE_ENDIAN) || \ -+ (defined(i386) || defined(__i386__) || defined(__i486__) || \ -+ defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL)) -+# define HASH_LITTLE_ENDIAN 1 -+# define HASH_BIG_ENDIAN 0 -+#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \ -+ __BYTE_ORDER == __BIG_ENDIAN) || \ -+ (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel)) -+# define HASH_LITTLE_ENDIAN 0 -+# define HASH_BIG_ENDIAN 1 -+#else -+# define HASH_LITTLE_ENDIAN 0 -+# define HASH_BIG_ENDIAN 0 -+#endif -+ -+#define hashsize(n) ((uint32_t)1<<(n)) -+#define hashmask(n) (hashsize(n)-1) -+#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) -+ -+/* -+------------------------------------------------------------------------------- -+mix -- mix 3 32-bit values reversibly. -+ -+This is reversible, so any information in (a,b,c) before mix() is -+still in (a,b,c) after mix(). -+ -+If four pairs of (a,b,c) inputs are run through mix(), or through -+mix() in reverse, there are at least 32 bits of the output that -+are sometimes the same for one pair and different for another pair. -+This was tested for: -+* pairs that differed by one bit, by two bits, in any combination -+ of top bits of (a,b,c), or in any combination of bottom bits of -+ (a,b,c). -+* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed -+ the output delta to a Gray code (a^(a>>1)) so a string of 1's (as -+ is commonly produced by subtraction) look like a single 1-bit -+ difference. -+* the base values were pseudorandom, all zero but one bit set, or -+ all zero plus a counter that starts at zero. -+ -+Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that -+satisfy this are -+ 4 6 8 16 19 4 -+ 9 15 3 18 27 15 -+ 14 9 3 7 17 3 -+Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing -+for "differ" defined as + with a one-bit base and a two-bit delta. I -+used http://burtleburtle.net/bob/hash/avalanche.html to choose -+the operations, constants, and arrangements of the variables. -+ -+This does not achieve avalanche. There are input bits of (a,b,c) -+that fail to affect some output bits of (a,b,c), especially of a. The -+most thoroughly mixed value is c, but it doesn't really even achieve -+avalanche in c. -+ -+This allows some parallelism. Read-after-writes are good at doubling -+the number of bits affected, so the goal of mixing pulls in the opposite -+direction as the goal of parallelism. I did what I could. Rotates -+seem to cost as much as shifts on every machine I could lay my hands -+on, and rotates are much kinder to the top and bottom bits, so I used -+rotates. -+------------------------------------------------------------------------------- -+*/ -+#define mix(a,b,c) \ -+{ \ -+ a -= c; a ^= rot(c, 4); c += b; \ -+ b -= a; b ^= rot(a, 6); a += c; \ -+ c -= b; c ^= rot(b, 8); b += a; \ -+ a -= c; a ^= rot(c,16); c += b; \ -+ b -= a; b ^= rot(a,19); a += c; \ -+ c -= b; c ^= rot(b, 4); b += a; \ -+} -+ -+/* -+------------------------------------------------------------------------------- -+final -- final mixing of 3 32-bit values (a,b,c) into c -+ -+Pairs of (a,b,c) values differing in only a few bits will usually -+produce values of c that look totally different. This was tested for -+* pairs that differed by one bit, by two bits, in any combination -+ of top bits of (a,b,c), or in any combination of bottom bits of -+ (a,b,c). -+* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed -+ the output delta to a Gray code (a^(a>>1)) so a string of 1's (as -+ is commonly produced by subtraction) look like a single 1-bit -+ difference. -+* the base values were pseudorandom, all zero but one bit set, or -+ all zero plus a counter that starts at zero. -+ -+These constants passed: -+ 14 11 25 16 4 14 24 -+ 12 14 25 16 4 14 24 -+and these came close: -+ 4 8 15 26 3 22 24 -+ 10 8 15 26 3 22 24 -+ 11 8 15 26 3 22 24 -+------------------------------------------------------------------------------- -+*/ -+#define final(a,b,c) \ -+{ \ -+ c ^= b; c -= rot(b,14); \ -+ a ^= c; a -= rot(c,11); \ -+ b ^= a; b -= rot(a,25); \ -+ c ^= b; c -= rot(b,16); \ -+ a ^= c; a -= rot(c,4); \ -+ b ^= a; b -= rot(a,14); \ -+ c ^= b; c -= rot(b,24); \ -+} -+ -+/* -+------------------------------------------------------------------------------- -+hashlittle() -- hash a variable-length key into a 32-bit value -+ k : the key (the unaligned variable-length array of bytes) -+ length : the length of the key, counting by bytes -+ initval : can be any 4-byte value -+Returns a 32-bit value. Every bit of the key affects every bit of -+the return value. Two keys differing by one or two bits will have -+totally different hash values. -+ -+The best hash table sizes are powers of 2. There is no need to do -+mod a prime (mod is sooo slow!). If you need less than 32 bits, -+use a bitmask. For example, if you need only 10 bits, do -+ h = (h & hashmask(10)); -+In which case, the hash table should have hashsize(10) elements. -+ -+If you are hashing n strings (uint8_t **)k, do it like this: -+ for (i=0, h=0; i 12) -+ { -+ a += k[0]; -+ b += k[1]; -+ c += k[2]; -+ mix(a,b,c); -+ length -= 12; -+ k += 3; -+ } -+ -+ /*----------------------------- handle the last (probably partial) block */ -+ /* -+ * "k[2]&0xffffff" actually reads beyond the end of the string, but -+ * then masks off the part it's not allowed to read. Because the -+ * string is aligned, the masked-off tail is in the same word as the -+ * rest of the string. Every machine with memory protection I've seen -+ * does it on word boundaries, so is OK with this. But VALGRIND will -+ * still catch it and complain. The masking trick does make the hash -+ * noticably faster for short strings (like English words). -+ */ -+#ifndef VALGRIND -+ -+ switch(length) -+ { -+ case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; -+ case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break; -+ case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break; -+ case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break; -+ case 8 : b+=k[1]; a+=k[0]; break; -+ case 7 : b+=k[1]&0xffffff; a+=k[0]; break; -+ case 6 : b+=k[1]&0xffff; a+=k[0]; break; -+ case 5 : b+=k[1]&0xff; a+=k[0]; break; -+ case 4 : a+=k[0]; break; -+ case 3 : a+=k[0]&0xffffff; break; -+ case 2 : a+=k[0]&0xffff; break; -+ case 1 : a+=k[0]&0xff; break; -+ case 0 : return c; /* zero length strings require no mixing */ -+ } -+ -+#else /* make valgrind happy */ -+ -+ k8 = (const uint8_t *)k; -+ switch(length) -+ { -+ case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; -+ case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ -+ case 10: c+=((uint32_t)k8[9])<<8; /* fall through */ -+ case 9 : c+=k8[8]; /* fall through */ -+ case 8 : b+=k[1]; a+=k[0]; break; -+ case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ -+ case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */ -+ case 5 : b+=k8[4]; /* fall through */ -+ case 4 : a+=k[0]; break; -+ case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ -+ case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */ -+ case 1 : a+=k8[0]; break; -+ case 0 : return c; -+ } -+ -+#endif /* !valgrind */ -+ -+ } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { -+ const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */ -+ const uint8_t *k8; -+ -+ /*--------------- all but last block: aligned reads and different mixing */ -+ while (length > 12) -+ { -+ a += k[0] + (((uint32_t)k[1])<<16); -+ b += k[2] + (((uint32_t)k[3])<<16); -+ c += k[4] + (((uint32_t)k[5])<<16); -+ mix(a,b,c); -+ length -= 12; -+ k += 6; -+ } -+ -+ /*----------------------------- handle the last (probably partial) block */ -+ k8 = (const uint8_t *)k; -+ switch(length) -+ { -+ case 12: c+=k[4]+(((uint32_t)k[5])<<16); -+ b+=k[2]+(((uint32_t)k[3])<<16); -+ a+=k[0]+(((uint32_t)k[1])<<16); -+ break; -+ case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ -+ case 10: c+=k[4]; -+ b+=k[2]+(((uint32_t)k[3])<<16); -+ a+=k[0]+(((uint32_t)k[1])<<16); -+ break; -+ case 9 : c+=k8[8]; /* fall through */ -+ case 8 : b+=k[2]+(((uint32_t)k[3])<<16); -+ a+=k[0]+(((uint32_t)k[1])<<16); -+ break; -+ case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ -+ case 6 : b+=k[2]; -+ a+=k[0]+(((uint32_t)k[1])<<16); -+ break; -+ case 5 : b+=k8[4]; /* fall through */ -+ case 4 : a+=k[0]+(((uint32_t)k[1])<<16); -+ break; -+ case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ -+ case 2 : a+=k[0]; -+ break; -+ case 1 : a+=k8[0]; -+ break; -+ case 0 : return c; /* zero length requires no mixing */ -+ } -+ -+ } else { /* need to read the key one byte at a time */ -+ const uint8_t *k = (const uint8_t *)key; -+ -+ /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ -+ while (length > 12) -+ { -+ a += k[0]; -+ a += ((uint32_t)k[1])<<8; -+ a += ((uint32_t)k[2])<<16; -+ a += ((uint32_t)k[3])<<24; -+ b += k[4]; -+ b += ((uint32_t)k[5])<<8; -+ b += ((uint32_t)k[6])<<16; -+ b += ((uint32_t)k[7])<<24; -+ c += k[8]; -+ c += ((uint32_t)k[9])<<8; -+ c += ((uint32_t)k[10])<<16; -+ c += ((uint32_t)k[11])<<24; -+ mix(a,b,c); -+ length -= 12; -+ k += 12; -+ } -+ -+ /*-------------------------------- last block: affect all 32 bits of (c) */ -+ switch(length) /* all the case statements fall through */ -+ { -+ case 12: c+=((uint32_t)k[11])<<24; -+ case 11: c+=((uint32_t)k[10])<<16; -+ case 10: c+=((uint32_t)k[9])<<8; -+ case 9 : c+=k[8]; -+ case 8 : b+=((uint32_t)k[7])<<24; -+ case 7 : b+=((uint32_t)k[6])<<16; -+ case 6 : b+=((uint32_t)k[5])<<8; -+ case 5 : b+=k[4]; -+ case 4 : a+=((uint32_t)k[3])<<24; -+ case 3 : a+=((uint32_t)k[2])<<16; -+ case 2 : a+=((uint32_t)k[1])<<8; -+ case 1 : a+=k[0]; -+ break; -+ case 0 : return c; -+ } -+ } -+ -+ final(a,b,c); -+ return c; -+} -diff --git a/src/utf.h b/src/utf.h -index 2495cdd..7a54be6 100644 ---- a/src/utf.h -+++ b/src/utf.h -@@ -10,23 +10,11 @@ - - #ifdef HAVE_CONFIG_H - #include -+#endif - --#ifdef HAVE_INTTYPES_H --/* inttypes.h includes stdint.h in a standard environment, so there's --no need to include stdint.h separately. If inttypes.h doesn't define --int32_t, it's defined in config.h. */ --#include --#endif /* HAVE_INTTYPES_H */ -- --#else /* !HAVE_CONFIG_H */ --#ifdef _WIN32 --typedef int int32_t; --#else /* !_WIN32 */ --/* Assume a standard environment */ --#include --#endif /* _WIN32 */ -- --#endif /* HAVE_CONFIG_H */ -+#ifdef HAVE_STDINT_H -+#include -+#endif - - int utf8_encode(int codepoint, char *buffer, int *size); - -diff --git a/src/value.c b/src/value.c -index ba9908e..a5ca052 100644 ---- a/src/value.c -+++ b/src/value.c -@@ -7,11 +7,19 @@ - - #define _GNU_SOURCE - -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ - #include - #include - #include - #include - -+#ifdef HAVE_STDINT_H -+#include -+#endif -+ - #include "jansson.h" - #include "hashtable.h" - #include "jansson_private.h" -@@ -34,11 +42,19 @@ static JSON_INLINE void json_init(json_t *json, json_type type) - - /*** object ***/ - -+extern volatile uint32_t hashtable_seed; -+ - json_t *json_object(void) - { - json_object_t *object = jsonp_malloc(sizeof(json_object_t)); - if(!object) - return NULL; -+ -+ if (!hashtable_seed) { -+ /* Autoseed */ -+ json_object_seed(0); -+ } -+ - json_init(&object->json, JSON_OBJECT); - - if(hashtable_init(&object->hashtable)) -diff --git a/test/bin/json_process.c b/test/bin/json_process.c -index 40183c7..106f1ce 100644 ---- a/test/bin/json_process.c -+++ b/test/bin/json_process.c -@@ -107,6 +107,9 @@ int main(int argc, char *argv[]) - if(getenv_int("JSON_SORT_KEYS")) - flags |= JSON_SORT_KEYS; - -+ if(getenv("HASHSEED")) -+ json_object_seed(getenv_int("HASHSEED")); -+ - if(getenv_int("STRIP")) { - /* Load to memory, strip leading and trailing whitespace */ - size_t size = 0, used = 0; -diff --git a/test/suites/api/test_memory_funcs.c b/test/suites/api/test_memory_funcs.c -index 4d6a81e..2f8bd2d 100644 ---- a/test/suites/api/test_memory_funcs.c -+++ b/test/suites/api/test_memory_funcs.c -@@ -24,13 +24,13 @@ static void create_and_free_complex_object() - - static void *my_malloc(size_t size) - { -- malloc_called += 1; -+ malloc_called = 1; - return malloc(size); - } - - static void my_free(void *ptr) - { -- free_called += 1; -+ free_called = 1; - free(ptr); - } - -@@ -39,7 +39,7 @@ static void test_simple() - json_set_alloc_funcs(my_malloc, my_free); - create_and_free_complex_object(); - -- if(malloc_called != 20 || free_called != 20) -+ if(malloc_called != 1 || free_called != 1) - fail("Custom allocation failed"); - } - -diff --git a/test/suites/api/test_object.c b/test/suites/api/test_object.c -index b317745..eb43500 100644 ---- a/test/suites/api/test_object.c -+++ b/test/suites/api/test_object.c -@@ -249,7 +249,11 @@ static void test_set_nocheck() - - static void test_iterators() - { -+ int i; - json_t *object, *foo, *bar, *baz; -+ const char *iter_keys[3]; -+ int have_key[3] = { 0, 0, 0 }; -+ json_t *iter_values[3]; - void *iter; - - if(json_object_iter(NULL)) -@@ -276,30 +280,50 @@ static void test_iterators() - iter = json_object_iter(object); - if(!iter) - fail("unable to get iterator"); -- if(strcmp(json_object_iter_key(iter), "a")) -- fail("iterating failed: wrong key"); -- if(json_object_iter_value(iter) != foo) -- fail("iterating failed: wrong value"); -+ iter_keys[0] = json_object_iter_key(iter); -+ iter_values[0] = json_object_iter_value(iter); - - iter = json_object_iter_next(object, iter); - if(!iter) - fail("unable to increment iterator"); -- if(strcmp(json_object_iter_key(iter), "b")) -- fail("iterating failed: wrong key"); -- if(json_object_iter_value(iter) != bar) -- fail("iterating failed: wrong value"); -+ iter_keys[1] = json_object_iter_key(iter); -+ iter_values[1] = json_object_iter_value(iter); - - iter = json_object_iter_next(object, iter); - if(!iter) - fail("unable to increment iterator"); -- if(strcmp(json_object_iter_key(iter), "c")) -- fail("iterating failed: wrong key"); -- if(json_object_iter_value(iter) != baz) -- fail("iterating failed: wrong value"); -+ iter_keys[2] = json_object_iter_key(iter); -+ iter_values[2] = json_object_iter_value(iter); - - if(json_object_iter_next(object, iter) != NULL) - fail("able to iterate over the end"); - -+ /* Check that keys have correct values */ -+ for (i = 0; i < 3; i++) { -+ if (strcmp(iter_keys[i], "a") == 0) { -+ if (iter_values[i] != foo) -+ fail("wrong value for iter key a"); -+ else -+ have_key[0] = 1; -+ } else if (strcmp(iter_keys[i], "b") == 0) { -+ if (iter_values[i] != bar) -+ fail("wrong value for iter key b"); -+ else -+ have_key[1] = 1; -+ } else if (strcmp(iter_keys[i], "c") == 0) { -+ if (iter_values[i] != baz) -+ fail("wrong value for iter key c"); -+ else -+ have_key[2] = 1; -+ } -+ } -+ -+ /* Check that we got all keys */ -+ for(i = 0; i < 3; i++) { -+ if(!have_key[i]) -+ fail("a key wasn't iterated over"); -+ } -+ - if(json_object_iter_at(object, "foo")) - fail("json_object_iter_at() succeeds for non-existent key"); - -@@ -312,22 +336,14 @@ static void test_iterators() - if(json_object_iter_value(iter) != bar) - fail("iterating failed: wrong value"); - -- iter = json_object_iter_next(object, iter); -- if(!iter) -- fail("unable to increment iterator"); -- if(strcmp(json_object_iter_key(iter), "c")) -- fail("iterating failed: wrong key"); -- if(json_object_iter_value(iter) != baz) -- fail("iterating failed: wrong value"); -- -- if(json_object_iter_set(object, iter, bar)) -+ if(json_object_iter_set(object, iter, baz)) - fail("unable to set value at iterator"); - -- if(strcmp(json_object_iter_key(iter), "c")) -+ if(strcmp(json_object_iter_key(iter), "b")) - fail("json_object_iter_key() fails after json_object_iter_set()"); -- if(json_object_iter_value(iter) != bar) -+ if(json_object_iter_value(iter) != baz) - fail("json_object_iter_value() fails after json_object_iter_set()"); -- if(json_object_get(object, "c") != bar) -+ if(json_object_get(object, "b") != baz) - fail("json_object_get() fails after json_object_iter_set()"); - - json_decref(object); --- -1.8.5.3 - diff --git a/SPECS/jansson.spec b/SPECS/jansson.spec index 7b76856..5c9313c 100644 --- a/SPECS/jansson.spec +++ b/SPECS/jansson.spec @@ -1,18 +1,14 @@ Name: jansson -Version: 2.4 -Release: 6%{?dist} +Version: 2.10 +Release: 1%{?dist} Summary: C library for encoding, decoding and manipulating JSON data Group: System Environment/Libraries License: MIT URL: http://www.digip.org/jansson/ Source0: http://www.digip.org/jansson/releases/jansson-%{version}.tar.bz2 -BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) -BuildRequires: python-sphinx -BuildRequires: libtool - -Patch0: 0001-Change-hash-function-randomize-hashes.patch +BuildRequires: python-sphinx %description Small library for parsing and writing JSON documents. @@ -20,8 +16,7 @@ Small library for parsing and writing JSON documents. %package devel Summary: Header files for jansson Group: Development/Libraries -Requires: %{name} = %{version}-%{release} -Requires: pkgconfig +Requires: %{name}%{?_isa} = %{version}-%{release} %description devel Header files for developing applications making use of jansson. @@ -35,8 +30,10 @@ Development documentation for jansson. %prep %setup -q -%patch0 -p1 -b .change_hash_function_randomize_hashes -autoreconf -i + +%if 0%{?rhel} == 6 +%{__sed} -i 's/code-block:: shell/code-block:: none/g' doc/*.rst +%endif %build %configure --disable-static @@ -47,24 +44,18 @@ make html make check %install -rm -rf "$RPM_BUILD_ROOT" make install INSTALL="install -p" DESTDIR="$RPM_BUILD_ROOT" rm "$RPM_BUILD_ROOT%{_libdir}"/*.la -%clean -rm -rf "$RPM_BUILD_ROOT" - %post -p /sbin/ldconfig %postun -p /sbin/ldconfig %files -%defattr(-,root,root,-) %doc LICENSE CHANGES %{_libdir}/*.so.* %files devel -%defattr(-,root,root,-) %{_libdir}/*.so %{_libdir}/pkgconfig/%{name}.pc %{_includedir}/* @@ -73,6 +64,10 @@ rm -rf "$RPM_BUILD_ROOT" %doc doc/_build/html/* %changelog +* Fri Mar 10 2017 Nathaniel McCallum - 2.10-1 +- Update to 2.10 [1389805] +- Merge spec file with Fedora + * Fri Mar 14 2014 Jiri Pirko 2.4-6 - Fix multilib conflicts by creating devel-doc package [1076415]