diff --git a/ccan/README b/ccan/README index aeef07c45..f533b5792 100644 --- a/ccan/README +++ b/ccan/README @@ -1,3 +1,3 @@ CCAN imported from http://ccodearchive.net. -CCAN version: init-2136-g64e9e71 +CCAN version: init-2181-g2953f51 diff --git a/ccan/ccan/cdump/cdump.c b/ccan/ccan/cdump/cdump.c index f080b968b..85c818a6d 100644 --- a/ccan/ccan/cdump/cdump.c +++ b/ccan/ccan/cdump/cdump.c @@ -213,7 +213,7 @@ static struct cdump_type *get_type(struct cdump_definitions *defs, enum cdump_type_kind kind, const char *name) { - struct cdump_map *m; + cdump_map_t *m; struct cdump_type *t; switch (kind) { @@ -609,7 +609,7 @@ static bool tok_take_enum(struct parse_state *ps) static bool gather_undefines(const char *name, struct cdump_type *t, - struct cdump_map *undefs) + cdump_map_t *undefs) { if (!type_defined(t)) strmap_add(undefs, name, t); @@ -618,15 +618,15 @@ static bool gather_undefines(const char *name, static bool remove_from_map(const char *name, struct cdump_type *t, - struct cdump_map *map) + cdump_map_t *map) { strmap_del(map, name, NULL); return true; } -static void remove_undefined(struct cdump_map *map) +static void remove_undefined(cdump_map_t *map) { - struct cdump_map undefs; + cdump_map_t undefs; /* We can't delete inside iterator, so gather all the undefs * then remove them. */ diff --git a/ccan/ccan/cdump/cdump.h b/ccan/ccan/cdump/cdump.h index 312767b41..30822ec50 100644 --- a/ccan/ccan/cdump/cdump.h +++ b/ccan/ccan/cdump/cdump.h @@ -50,14 +50,12 @@ struct cdump_type { }; /* The map of typenames to definitions */ -struct cdump_map { - STRMAP_MEMBERS(struct cdump_type *); -}; +typedef STRMAP(struct cdump_type *) cdump_map_t; struct cdump_definitions { - struct cdump_map enums; - struct cdump_map structs; - struct cdump_map unions; + cdump_map_t enums; + cdump_map_t structs; + cdump_map_t unions; }; /** diff --git a/ccan/ccan/crypto/shachain/design.txt b/ccan/ccan/crypto/shachain/design.txt index 02f4c6f6f..b4639763c 100644 --- a/ccan/ccan/crypto/shachain/design.txt +++ b/ccan/ccan/crypto/shachain/design.txt @@ -16,99 +16,107 @@ A simple system is a hash chain: we select a random seed value, the hash it 1,000,000 times. This gives the first "random" number. Hashed 999,999 times gives the second number, etc. ie: - R(1,000,000) = seed - R(N-1) = SHA256(R(N)) + R(0) = seed + R(N+1) = SHA256(R(N)) This way the remote node needs only to remember the last R(N) it was -given, and it can calculate any R for N-1 or below. +given, and it can calculate any R for N+1 or above. However, this means we need to generate 1 million hashes up front, and then do almost as many hashes to derive the next number. That's slow. -A More Complex Solution ------------------------ - -Instead of a one-dimensional chain, we can use two dimensions: 1000 -chains of 1000 values each. Indeed, we can set generate the "top" of -each chain much like we generated a single chain: - - Chain 1000 Chain 999 Chain 998 ...........Chain 1 - seed SHA256(C1000) SHA256(C999) ....... SHA256(C2) - -Now, deriving chain 1000 from seed doesn't quite work, because it'll -look like this chain, so we flip the lower bit to generate the chain: - - Chain 1000 Chain 999 Chain 998 ...........Chain 1 -1000 seed^1 SHA256(C1000)^1 SHA256(C999)^1...... SHA256(C2)^1 - 999 SHA256(above) SHA256(above) SHA256(above) ..... SHA256(above) - 998 SHA256(above) SHA256(above) SHA256(above) ..... SHA256(above) - ... - -Now, we can get the first value to give out (chain 1, position 1) with -999 hashes to get to chain 1, and 999 hashes to get to the end of the -chain. 2000 hashes is much better than the 999,999 hashes it would -have taken previously. - -Why Stop at 2 Dimensions? -------------------------- - -Indeed, the implementation uses 64 dimensions rather than 2, and a -chain length of 2 rather than 1000, giving a worst-case of 63 hashes -to derive any of 2^64 values. Each dimension flips a different bit of -the hash, to ensure the chains are distinct. - -For simplicity, I'll explain what this looks like using 8 dimensions, -ie. 8 bits. The seed value always sits the maximum possible index, in -this case index 0xFF (b11111111). - -To generate the hash for 0xFE (b11111110), we need to move down -dimension 0, so we flip bit 0 of the seed value, then hash it. To -generate the hash for 0xFD (b11111101) we need to move down dimension -1, so we flip bit 1 of the seed value, then hash it. - -To reach 0xFC (b11111100) we need to move down dimension 1 then -dimension 0, in that order. - -Spotting the pattern, it becomes easy to derive how to reach any value: - - hash = seed - for bit in 7 6 5 4 3 2 1 0: - if bit not set in index: - flip(bit) in hash - hash = SHA256(hash) - -Handling Partial Knowledge --------------------------- - -How does the remote node, which doesn't know the seed value, derive -subvalues? - -Once it knows the value for index 1, it can derive the value for index -0 by flipping bit 0 of the value and hashing it. In effect, it can -always derive a value for any index where it only needs to clear bits. - -So, index 1 gives index 0, but index 2 doesn't yield index 1. When -index 3 comes along, it yields 2, 1, and 0. - -How many hash values will we have to remember at once? The answer is -equal to the number of dimensions. It turns out that the worst case -for 8 dimensions is 254 (0b11111110), for which we will have to -remember the following indices: - - 127 0b01111111 - 191 0b10111111 - 223 0b11011111 - 239 0b11101111 - 247 0b11110111 - 251 0b11111011 - 253 0b11111101 - 254 0b11111110 - -127 lets us derive any hash value for index <= 127. Similarly, 191 -lets us derive anything > 127 but <= 191. 254 lets us derive only -itself. - -When we get index 255 this collapses, and we only need to remember -that one index to derive everything. +A Tree Solution +--------------- + +A better solution is to use a binary tree, with the seed at the root. +The left child is the same as the parent, the right child is the +SHA256() of the parent with one bit flipped (corresponding to the +height). + +This gives a tree like so: + + seed + / \ + / \ + / \ + / \ + seed SHA256(seed^1) + / \ / \ + seed SHA256(seed^2) SHA256(seed^1) SHA256(SHA256(seed^1)^2) +Index: 0 1 2 3 + +Clearly, giving R(2) allows you to derive R(3), giving R(1) allows you +to derive nothing new (you still have to remember R(2)), and giving +R(0) allows you to derive everything. + +In pseudocode, this looks like the following for a 64 bit tree: + +generate_from_seed(index): + value = seed + for bit in 0 to 63: + if bit set in index: + flip(bit) in value + value = SHA256(value) + return value + + +The Receiver's Tree +------------------- + +To derive the value for a index N, you need to have the root of a tree +which contains it. That is the same as needing an index I which is N +rounded down in binary: eg. if N is 0b001100001, you need 0b001100000, +0b001000000 or 0b000000000. + +Pseudocode: + +# Can we derive the value for to_index from from_index? +can_derive(from_index, to_index): + # to_index must be a subtree under from_index; this is the same as + # saying that to_index must be the same as from_index up to the + # trailing zeros in from_index. + for bit in count_trailing_zeroes(from_index)..63: + if bit set in from_index != bit set in to_index: + return false + return true + +# Derive a value from a lesser index: generalization of generate_from_seed() +derive(from_index, to_index, from_value): + assert(can_derive(from_index, to_index)) + value = from_value + for bit in 0..63: + if bit set in to_index and not bit set in from_index: + flip bit in value + value = SHA256(value) + return value + +If you are receiving values (in reverse order), you need to remember +up to 64 of them to derive all previous values. The simplest method +is to keep an array, indexed by the number of trailing zeroes in the +received index: + +# Receive a new value (assumes we receive them in order) +receive_value(index, value): + pos = count_trailing_zeroes(index) + # We should be able to generate every lesser value, otherwise invalid + for i in 0..pos-1: + if derive(index, value, known[i].index) != known[i].value: + return false + known[pos].index = index + known[pos].value = value + return true + +To derive a previous value, find an element in that array from which +you can derive the value you want, eg: + +# Find an old value +regenerate_value(index): + for i in known: + if can_derive(i.index, index): + return derive(i.index, i.value, index) + fail + +You can see the implementation for more optimized variants of the +above code. Rusty Russell diff --git a/ccan/ccan/crypto/shachain/shachain.c b/ccan/ccan/crypto/shachain/shachain.c index 8c9fdcf50..6cfb7244f 100644 --- a/ccan/ccan/crypto/shachain/shachain.c +++ b/ccan/ccan/crypto/shachain/shachain.c @@ -5,15 +5,39 @@ #include #include +#define INDEX_BITS ((sizeof(shachain_index_t)) * CHAR_BIT) + static void change_bit(unsigned char *arr, size_t index) { arr[index / CHAR_BIT] ^= (1 << (index % CHAR_BIT)); } -/* We can only ever *unset* bits, so to must only have bits in from. */ +static int count_trailing_zeroes(shachain_index_t index) +{ +#if HAVE_BUILTIN_CTZLL + return index ? __builtin_ctzll(index) : INDEX_BITS; +#else + int i; + + for (i = 0; i < INDEX_BITS; i++) { + if (index & (1ULL << i)) + break; + } + return i; +#endif +} + static bool can_derive(shachain_index_t from, shachain_index_t to) { - return (~from & to) == 0; + shachain_index_t mask; + + /* Corner case: can always derive from seed. */ + if (from == 0) + return true; + + /* Leading bits must be the same */ + mask = ~((1ULL << count_trailing_zeroes(from))-1); + return ((from ^ to) & mask) == 0; } static void derive(shachain_index_t from, shachain_index_t to, @@ -28,7 +52,7 @@ static void derive(shachain_index_t from, shachain_index_t to, /* We start with the first hash. */ *hash = *from_hash; - /* This represents the bits set in from, and not to. */ + /* This represents the bits set in to, and not from. */ branches = from ^ to; for (i = ilog64(branches) - 1; i >= 0; i--) { if (((branches >> i) & 1)) { @@ -41,45 +65,42 @@ static void derive(shachain_index_t from, shachain_index_t to, void shachain_from_seed(const struct sha256 *seed, shachain_index_t index, struct sha256 *hash) { - derive((shachain_index_t)-1ULL, index, seed, hash); + derive(0, index, seed, hash); } void shachain_init(struct shachain *chain) { chain->num_valid = 0; - chain->max_index = 0; + chain->min_index = 0; } bool shachain_add_hash(struct shachain *chain, shachain_index_t index, const struct sha256 *hash) { - int i; + int i, pos; /* You have to insert them in order! */ - assert(index == chain->max_index + 1 || - (index == 0 && chain->num_valid == 0)); - - for (i = 0; i < chain->num_valid; i++) { - /* If we could derive this value, we don't need it, - * not any others (since they're in order). */ - if (can_derive(index, chain->known[i].index)) { - struct sha256 expect; - - /* Make sure the others derive as expected! */ - derive(index, chain->known[i].index, hash, &expect); - if (memcmp(&expect, &chain->known[i].hash, - sizeof(expect)) != 0) - return false; - break; - } + assert(index == chain->min_index - 1 || + (index == (shachain_index_t)(-1ULL) && chain->num_valid == 0)); + + pos = count_trailing_zeroes(index); + + /* All derivable answers must be valid. */ + /* FIXME: Is it sufficient to check just the next answer? */ + for (i = 0; i < pos; i++) { + struct sha256 expect; + + /* Make sure the others derive as expected! */ + derive(index, chain->known[i].index, hash, &expect); + if (memcmp(&expect, &chain->known[i].hash, sizeof(expect))) + return false; } - /* This can happen if you skip indices! */ - assert(i < sizeof(chain->known) / sizeof(chain->known[0])); - chain->known[i].index = index; - chain->known[i].hash = *hash; - chain->num_valid = i+1; - chain->max_index = index; + chain->known[pos].index = index; + chain->known[pos].hash = *hash; + if (pos + 1 > chain->num_valid) + chain->num_valid = pos + 1; + chain->min_index = index; return true; } diff --git a/ccan/ccan/crypto/shachain/shachain.h b/ccan/ccan/crypto/shachain/shachain.h index 4a3051e69..ba4ba11cd 100644 --- a/ccan/ccan/crypto/shachain/shachain.h +++ b/ccan/ccan/crypto/shachain/shachain.h @@ -14,49 +14,49 @@ /** * shachain_from_seed - Generate an unpredictable SHA from a seed value. * @seed: (secret) seed value to use - * @index: index of value to generate. + * @index: index of value to generate (0 == seed) * @hash: value generated * * There will be no way to derive the result from that generated for - * any *lesser* index. + * any *greater* index. * * Example: * #include * * static void next_hash(struct sha256 *hash) * { - * static uint64_t index = 0; + * static uint64_t index = 0xFFFFFFFFFFFFFFFFULL; * static struct sha256 seed; * * // First time, initialize seed. - * if (index == 0) { + * if (index == 0xFFFFFFFFFFFFFFFFULL) { * // DO NOT DO THIS! Very predictable! * time_t now = time(NULL); * memcpy(&seed, &now, sizeof(now)); * } * - * shachain_from_seed(&seed, index++, hash); + * shachain_from_seed(&seed, index--, hash); * } */ void shachain_from_seed(const struct sha256 *seed, shachain_index_t index, struct sha256 *hash); /** - * shachain - structure for recording/deriving incrementing chain members - * @max_index: maximum index value successfully shachain_add_hash()ed. - * @num_valid: number of known[] array valid. If non-zero, @max_index valid. - * @known: known values to allow us to derive those <= @max_index. + * shachain - structure for recording/deriving decrementing chain members + * @min_index: minimum index value successfully shachain_add_hash()ed. + * @num_valid: number of known[] array valid. If non-zero, @min_index valid. + * @known: known values to allow us to derive those >= @min_index. * * This is sufficient storage to derive any shachain hash value previously * added. */ struct shachain { - shachain_index_t max_index; + shachain_index_t min_index; unsigned int num_valid; struct { shachain_index_t index; struct sha256 hash; - } known[sizeof(shachain_index_t) * 8]; + } known[sizeof(shachain_index_t) * 8 + 1]; }; /** @@ -73,8 +73,9 @@ void shachain_init(struct shachain *chain); * @index: the index of the hash * @hash: the hash value. * - * You can only add index 0 (for a freshly initialized chain), or one more - * than the previously successfully added value. + * You can only add index 0xFFFFFFFFFFFFFFFF (for a freshly + * initialized chain), or one less than the previously successfully + * added value. * * This can fail (return false without altering @chain) if the hash * for this index isn't consistent with previous hashes (ie. wasn't @@ -85,10 +86,10 @@ void shachain_init(struct shachain *chain); * Example: * static void next_hash(const struct sha256 *hash) * { - * static uint64_t index = 0; + * static uint64_t index = 0xFFFFFFFFFFFFFFFFULL; * static struct shachain chain; * - * if (!shachain_add_hash(&chain, index++, hash)) + * if (!shachain_add_hash(&chain, index--, hash)) * errx(1, "Corrupted hash value?"); * } */ @@ -111,14 +112,14 @@ bool shachain_add_hash(struct shachain *chain, * * static void next_hash(const struct sha256 *hash) * { - * static uint64_t index = 0; + * static uint64_t index = 0xFFFFFFFFFFFFFFFFULL; * static struct shachain chain; * - * if (!shachain_add_hash(&chain, index++, hash)) + * if (!shachain_add_hash(&chain, index--, hash)) * errx(1, "Corrupted hash value?"); * else { * struct sha256 check; - * assert(shachain_get_hash(&chain, index-1, &check)); + * assert(shachain_get_hash(&chain, index+1, &check)); * assert(structeq(&check, hash)); * } * } diff --git a/ccan/ccan/crypto/shachain/test/run-8bit.c b/ccan/ccan/crypto/shachain/test/run-8bit.c index 64b1c7f44..90b7ef6ce 100644 --- a/ccan/ccan/crypto/shachain/test/run-8bit.c +++ b/ccan/ccan/crypto/shachain/test/run-8bit.c @@ -13,39 +13,41 @@ int main(void) { struct sha256 seed; struct shachain chain; - struct sha256 expect[NUM_TESTS]; - size_t i, j; + struct sha256 expect[NUM_TESTS+1]; + int i, j; /* This is how many tests you plan to run */ - plan_tests(NUM_TESTS * 3 + NUM_TESTS * (NUM_TESTS + 1)); + plan_tests(66559); memset(&seed, 0, sizeof(seed)); - /* Generate a whole heap. */ - for (i = 0; i < NUM_TESTS; i++) { + /* Generate a whole heap; each should be different */ + for (i = 0; i <= NUM_TESTS; i++) { shachain_from_seed(&seed, i, &expect[i]); if (i == 0) - ok1(memcmp(&expect[i], &seed, sizeof(expect[i]))); + ok1(memcmp(&expect[i], &seed, sizeof(expect[i])) == 0); else ok1(memcmp(&expect[i], &expect[i-1], sizeof(expect[i]))); } shachain_init(&chain); - for (i = 0; i < NUM_TESTS; i++) { + for (i = NUM_TESTS; i > 0; i--) { struct sha256 hash; ok1(shachain_add_hash(&chain, i, &expect[i])); - for (j = 0; j <= i; j++) { + for (j = i; j <= NUM_TESTS; j++) { ok1(shachain_get_hash(&chain, j, &hash)); ok1(memcmp(&hash, &expect[j], sizeof(hash)) == 0); } - ok1(!shachain_get_hash(&chain, i+1, &hash)); - if (chain.num_valid == 8) { - printf("%zu: num_valid %u\n", i, chain.num_valid); - for (j = 0; j < 8; j++) - printf("chain.known[%zu] = 0x%02x\n", - j, chain.known[j].index); - } + ok1(!shachain_get_hash(&chain, i-1, &hash)); + } + + /* Now add seed. */ + ok1(shachain_add_hash(&chain, 0, &expect[0])); + for (j = 0; j <= NUM_TESTS; j++) { + struct sha256 hash; + ok1(shachain_get_hash(&chain, j, &hash)); + ok1(memcmp(&hash, &expect[j], sizeof(hash)) == 0); } return exit_status(); diff --git a/ccan/ccan/crypto/shachain/test/run-badhash.c b/ccan/ccan/crypto/shachain/test/run-badhash.c index bc9785120..742a36b83 100644 --- a/ccan/ccan/crypto/shachain/test/run-badhash.c +++ b/ccan/ccan/crypto/shachain/test/run-badhash.c @@ -9,26 +9,27 @@ int main(void) { struct sha256 seed; struct shachain chain; - size_t i; + uint64_t i; plan_tests(NUM_TESTS); memset(&seed, 0xFF, sizeof(seed)); shachain_init(&chain); - for (i = 0; i < NUM_TESTS; i++) { + for (i = 0xFFFFFFFFFFFFFFFFULL; + i > 0xFFFFFFFFFFFFFFFFULL - NUM_TESTS; + i--) { struct sha256 expect; - unsigned int num_known = chain.num_valid; shachain_from_seed(&seed, i, &expect); /* Screw it up. */ expect.u.u8[0]++; - /* Either it should fail, or it couldn't derive any others. */ + /* Either it should fail, or it couldn't derive any others (ie. pos 0). */ if (shachain_add_hash(&chain, i, &expect)) { - ok1(chain.num_valid == num_known + 1); + ok1(chain.known[0].index == i); /* Fix it up in-place */ - chain.known[num_known].hash.u.u8[0]--; + chain.known[0].hash.u.u8[0]--; } else { expect.u.u8[0]--; ok1(shachain_add_hash(&chain, i, &expect)); diff --git a/ccan/ccan/crypto/shachain/test/run-can_derive.c b/ccan/ccan/crypto/shachain/test/run-can_derive.c new file mode 100644 index 000000000..5a1bf4779 --- /dev/null +++ b/ccan/ccan/crypto/shachain/test/run-can_derive.c @@ -0,0 +1,41 @@ +#define shachain_index_t uint8_t + +#include +/* Include the C files directly. */ +#include +#include + +#include + +static bool bit_set(shachain_index_t index, int bit) +{ + return index & (1ULL << bit); +} + +/* As per design.txt */ +static bool naive_can_derive(shachain_index_t from, shachain_index_t to) +{ + int i; + + for (i = count_trailing_zeroes(from); i < 8; i++) { + if (bit_set(from, i) != bit_set(to, i)) + return false; + } + return true; +} + +int main(void) +{ + int i, j; + + /* This is how many tests you plan to run */ + plan_tests(65536); + + for (i = 0; i < 256; i++) { + for (j = 0; j < 256; j++) { + ok1(can_derive(i, j) == naive_can_derive(i, j)); + } + } + + return exit_status(); +} diff --git a/ccan/ccan/crypto/shachain/test/run.c b/ccan/ccan/crypto/shachain/test/run.c index 16fc5e871..36dfaaeb7 100644 --- a/ccan/ccan/crypto/shachain/test/run.c +++ b/ccan/ccan/crypto/shachain/test/run.c @@ -10,32 +10,37 @@ int main(void) struct sha256 seed; struct shachain chain; struct sha256 expect[NUM_TESTS]; - size_t i, j; + uint64_t i, j; /* This is how many tests you plan to run */ - plan_tests(NUM_TESTS * 3 + NUM_TESTS * (NUM_TESTS + 1)); + plan_tests(NUM_TESTS * 3 + NUM_TESTS * (NUM_TESTS + 1) - 1); memset(&seed, 0, sizeof(seed)); /* Generate a whole heap. */ - for (i = 0; i < NUM_TESTS; i++) { - shachain_from_seed(&seed, i, &expect[i]); - if (i == 0) - ok1(memcmp(&expect[i], &seed, sizeof(expect[i]))); - else - ok1(memcmp(&expect[i], &expect[i-1], sizeof(expect[i]))); + for (i = 0xFFFFFFFFFFFFFFFFULL; + i > 0xFFFFFFFFFFFFFFFFULL - NUM_TESTS; + i--) { + int expidx = 0xFFFFFFFFFFFFFFFFULL - i; + shachain_from_seed(&seed, i, &expect[expidx]); + if (i != 0xFFFFFFFFFFFFFFFFULL) + ok1(memcmp(&expect[expidx], &expect[expidx-1], + sizeof(expect[expidx]))); } shachain_init(&chain); - for (i = 0; i < NUM_TESTS; i++) { + for (i = 0xFFFFFFFFFFFFFFFFULL; + i > 0xFFFFFFFFFFFFFFFFULL - NUM_TESTS; + i--) { struct sha256 hash; - - ok1(shachain_add_hash(&chain, i, &expect[i])); - for (j = 0; j <= i; j++) { + int expidx = 0xFFFFFFFFFFFFFFFFULL - i; + ok1(shachain_add_hash(&chain, i, &expect[expidx])); + for (j = i; j != 0; j++) { ok1(shachain_get_hash(&chain, j, &hash)); - ok1(memcmp(&hash, &expect[j], sizeof(hash)) == 0); + expidx = 0xFFFFFFFFFFFFFFFFULL - j; + ok1(memcmp(&hash, &expect[expidx], sizeof(hash)) == 0); } - ok1(!shachain_get_hash(&chain, i+1, &hash)); + ok1(!shachain_get_hash(&chain, i-1, &hash)); } return exit_status(); diff --git a/ccan/ccan/htable/htable_type.h b/ccan/ccan/htable/htable_type.h index ad3974c5e..2afa14847 100644 --- a/ccan/ccan/htable/htable_type.h +++ b/ccan/ccan/htable/htable_type.h @@ -2,6 +2,7 @@ #ifndef CCAN_HTABLE_TYPE_H #define CCAN_HTABLE_TYPE_H #include +#include #include "config.h" /** @@ -30,9 +31,15 @@ * bool _del(struct *ht, const *e); * bool _delkey(struct *ht, const *k); * - * Find function return the matching element, or NULL: + * Find and return the (first) matching element, or NULL: * type *_get(const struct @name *ht, const *k); * + * Find and return all matching elements, or NULL: + * type *_getfirst(const struct @name *ht, const *k, + * struct _iter *i); + * type *_getnext(const struct @name *ht, const *k, + * struct _iter *i); + * * Iteration over hashtable is also supported: * type *_first(const struct *ht, struct _iter *i); * type *_next(const struct *ht, struct _iter *i); @@ -50,15 +57,16 @@ { \ return hashfn(keyof((const type *)elem)); \ } \ - static inline void name##_init(struct name *ht) \ + static inline UNNEEDED void name##_init(struct name *ht) \ { \ htable_init(&ht->raw, name##_hash, NULL); \ } \ - static inline void name##_init_sized(struct name *ht, size_t s) \ + static inline UNNEEDED void name##_init_sized(struct name *ht, \ + size_t s) \ { \ htable_init_sized(&ht->raw, name##_hash, NULL, s); \ } \ - static inline void name##_clear(struct name *ht) \ + static inline UNNEEDED void name##_clear(struct name *ht) \ { \ htable_clear(&ht->raw); \ } \ @@ -66,11 +74,12 @@ { \ return htable_add(&ht->raw, hashfn(keyof(elem)), elem); \ } \ - static inline bool name##_del(struct name *ht, const type *elem) \ + static inline UNNEEDED bool name##_del(struct name *ht, \ + const type *elem) \ { \ return htable_del(&ht->raw, hashfn(keyof(elem)), elem); \ } \ - static inline type *name##_get(const struct name *ht, \ + static inline UNNEEDED type *name##_get(const struct name *ht, \ const HTABLE_KTYPE(keyof) k) \ { \ /* Typecheck for eqfn */ \ @@ -81,7 +90,36 @@ (bool (*)(const void *, void *))(eqfn), \ k); \ } \ - static inline bool name##_delkey(struct name *ht, \ + static inline UNNEEDED type *name##_getmatch_(const struct name *ht, \ + const HTABLE_KTYPE(keyof) k, \ + size_t h, \ + type *v, \ + struct name##_iter *iter) \ + { \ + while (v) { \ + if (eqfn(v, k)) \ + break; \ + v = htable_nextval(&ht->raw, &iter->i, h); \ + } \ + return v; \ + } \ + static inline UNNEEDED type *name##_getfirst(const struct name *ht, \ + const HTABLE_KTYPE(keyof) k, \ + struct name##_iter *iter) \ + { \ + size_t h = hashfn(k); \ + type *v = htable_firstval(&ht->raw, &iter->i, h); \ + return name##_getmatch_(ht, k, h, v, iter); \ + } \ + static inline UNNEEDED type *name##_getnext(const struct name *ht, \ + const HTABLE_KTYPE(keyof) k, \ + struct name##_iter *iter) \ + { \ + size_t h = hashfn(k); \ + type *v = htable_nextval(&ht->raw, &iter->i, h); \ + return name##_getmatch_(ht, k, h, v, iter); \ + } \ + static inline UNNEEDED bool name##_delkey(struct name *ht, \ const HTABLE_KTYPE(keyof) k) \ { \ type *elem = name##_get(ht, k); \ @@ -89,12 +127,12 @@ return name##_del(ht, elem); \ return false; \ } \ - static inline type *name##_first(const struct name *ht, \ + static inline UNNEEDED type *name##_first(const struct name *ht, \ struct name##_iter *iter) \ { \ return htable_first(&ht->raw, &iter->i); \ } \ - static inline type *name##_next(const struct name *ht, \ + static inline UNNEEDED type *name##_next(const struct name *ht, \ struct name##_iter *iter) \ { \ return htable_next(&ht->raw, &iter->i); \ diff --git a/ccan/ccan/htable/test/run-type.c b/ccan/ccan/htable/test/run-type.c index f97e7270b..11ce54bac 100644 --- a/ccan/ccan/htable/test/run-type.c +++ b/ccan/ccan/htable/test/run-type.c @@ -111,12 +111,12 @@ int main(int argc, char *argv[]) { unsigned int i; struct htable_obj ht; - struct obj val[NUM_VALS]; + struct obj val[NUM_VALS], *result; unsigned int dne; void *p; struct htable_obj_iter iter; - plan_tests(20); + plan_tests(26); for (i = 0; i < NUM_VALS; i++) val[i].key = i; dne = i; @@ -169,7 +169,33 @@ int main(int argc, char *argv[]) /* Delete them all by key. */ del_vals_bykey(&ht, val, NUM_VALS); - htable_obj_clear(&ht); + /* Write two of the same value. */ + val[1] = val[0]; + htable_obj_add(&ht, &val[0]); + htable_obj_add(&ht, &val[1]); + i = 0; + + result = htable_obj_getfirst(&ht, &i, &iter); + ok1(result == &val[0] || result == &val[1]); + if (result == &val[0]) { + ok1(htable_obj_getnext(&ht, &i, &iter) == &val[1]); + ok1(htable_obj_getnext(&ht, &i, &iter) == NULL); + + /* Deleting first should make us iterate over the other. */ + ok1(htable_obj_del(&ht, &val[0])); + ok1(htable_obj_getfirst(&ht, &i, &iter) == &val[1]); + ok1(htable_obj_getnext(&ht, &i, &iter) == NULL); + } else { + ok1(htable_obj_getnext(&ht, &i, &iter) == &val[0]); + ok1(htable_obj_getnext(&ht, &i, &iter) == NULL); + + /* Deleting first should make us iterate over the other. */ + ok1(htable_obj_del(&ht, &val[1])); + ok1(htable_obj_getfirst(&ht, &i, &iter) == &val[0]); + ok1(htable_obj_getnext(&ht, &i, &iter) == NULL); + } + + htable_obj_clear(&ht); return exit_status(); } diff --git a/ccan/ccan/mem/mem.c b/ccan/ccan/mem/mem.c index 5eb15070e..13027a2a7 100644 --- a/ccan/ccan/mem/mem.c +++ b/ccan/ccan/mem/mem.c @@ -107,3 +107,22 @@ bool memeqzero(const void *data, size_t length) /* Now we know that's zero, memcmp with self. */ return memcmp(data, p, length) == 0; } + +void memtaint(void *data, size_t len) +{ + /* Using 16 bytes is a bit quicker than 4 */ + const unsigned tainter[] + = { 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef }; + char *p = data; + + while (len >= sizeof(tainter)) { + memcpy(p, tainter, sizeof(tainter)); + p += sizeof(tainter); + len -= sizeof(tainter); + } + memcpy(p, tainter, len); + +#if HAVE_VALGRIND_MEMCHECK_H + VALGRIND_MAKE_MEM_UNDEFINED(data, len); +#endif +} diff --git a/ccan/ccan/mem/mem.h b/ccan/ccan/mem/mem.h index a3403c4ee..f2c3d5c7a 100644 --- a/ccan/ccan/mem/mem.h +++ b/ccan/ccan/mem/mem.h @@ -275,4 +275,20 @@ static inline void *memcheck_(const void *data, size_t len) #else #define memcheck(data, len) memcheck_((data), (len)) #endif + +/** + * memtaint - mark a memory region unused + * @data: start of region + * @len: length in bytes + * + * This writes an "0xdeadbeef" eyecatcher repeatedly to the memory. + * When running under valgrind, it also tells valgrind that the memory is + * uninitialized, triggering valgrind errors if it is used for branches + * or written out (or passed to memcheck!) in future. + * + * Example: + * // We'll reuse this buffer later, but be sure we don't access it. + * memtaint(somebytes, bytes_len); + */ +void memtaint(void *data, size_t len); #endif /* CCAN_MEM_H */ diff --git a/ccan/ccan/strmap/_info b/ccan/ccan/strmap/_info index 55319a82d..c128cc27b 100644 --- a/ccan/ccan/strmap/_info +++ b/ccan/ccan/strmap/_info @@ -29,7 +29,7 @@ * int main(int argc, char *argv[]) * { * size_t i; - * struct { STRMAP_MEMBERS(size_t); } map; + * STRMAP(size_t) map; * * strmap_init(&map); * for (i = 1; i < argc; i++) diff --git a/ccan/ccan/strmap/strmap.h b/ccan/ccan/strmap/strmap.h index 8fabc359a..0b32e6bef 100644 --- a/ccan/ccan/strmap/strmap.h +++ b/ccan/ccan/strmap/strmap.h @@ -21,7 +21,7 @@ struct strmap { }; /** - * STRMAP_MEMBERS - declare members for a type-specific strmap. + * STRMAP - declare a type-specific strmap * @type: type for this map's values, or void * for any pointer. * * You use this to create your own typed strmap for a particular type. @@ -29,14 +29,11 @@ struct strmap { * value! * * Example: - * struct strmap_intp { - * STRMAP_MEMBERS(int *); - * }; + * STRMAP(int *) int_strmap; + * strmap_init(&int_strmap); */ -#define STRMAP_MEMBERS(type) \ - struct strmap raw; \ - TCON(type canary) - +#define STRMAP(type) \ + TCON_WRAP(struct strmap, type canary) /** * strmap_init - initialize a string map (empty) @@ -46,11 +43,11 @@ struct strmap { * need this. * * Example: - * struct strmap_intp map; + * STRMAP(int *) map; * * strmap_init(&map); */ -#define strmap_init(map) strmap_init_(&(map)->raw) +#define strmap_init(map) strmap_init_(tcon_unwrap(map)) static inline void strmap_init_(struct strmap *map) { @@ -65,7 +62,7 @@ static inline void strmap_init_(struct strmap *map) * if (!strmap_empty(&map)) * abort(); */ -#define strmap_empty(map) strmap_empty_(&(map)->raw) +#define strmap_empty(map) strmap_empty_(tcon_unwrap(map)) static inline bool strmap_empty_(const struct strmap *map) { @@ -85,7 +82,7 @@ static inline bool strmap_empty_(const struct strmap *map) * printf("hello => %i\n", *val); */ #define strmap_get(map, member) \ - tcon_cast((map), canary, strmap_get_(&(map)->raw, (member))) + tcon_cast((map), canary, strmap_get_(tcon_unwrap(map), (member))) void *strmap_get_(const struct strmap *map, const char *member); /** @@ -106,8 +103,8 @@ void *strmap_get_(const struct strmap *map, const char *member); * if (!strmap_add(&map, "goodbye", val)) * printf("goodbye was already in the map\n"); */ -#define strmap_add(map, member, value) \ - strmap_add_(&tcon_check((map), canary, (value))->raw, \ +#define strmap_add(map, member, value) \ + strmap_add_(tcon_unwrap(tcon_check((map), canary, (value))), \ (member), (void *)(value)) bool strmap_add_(struct strmap *map, const char *member, const void *value); @@ -130,7 +127,7 @@ bool strmap_add_(struct strmap *map, const char *member, const void *value); * printf("goodbye was not in the map?\n"); */ #define strmap_del(map, member, valuep) \ - strmap_del_(&tcon_check_ptr((map), canary, valuep)->raw, \ + strmap_del_(tcon_unwrap(tcon_check_ptr((map), canary, valuep)), \ (member), (void **)valuep) char *strmap_del_(struct strmap *map, const char *member, void **valuep); @@ -143,7 +140,7 @@ char *strmap_del_(struct strmap *map, const char *member, void **valuep); * Example: * strmap_clear(&map); */ -#define strmap_clear(map) strmap_clear_(&(map)->raw) +#define strmap_clear(map) strmap_clear_(tcon_unwrap(map)) void strmap_clear_(struct strmap *map); @@ -160,9 +157,7 @@ void strmap_clear_(struct strmap *map); * You should not alter the map within the @handle function! * * Example: - * struct strmap_intp { - * STRMAP_MEMBERS(int *); - * }; + * typedef STRMAP(int *) strmap_intp; * static bool dump_some(const char *member, int *value, int *num) * { * // Only dump out num nodes. @@ -172,7 +167,7 @@ void strmap_clear_(struct strmap *map); * return true; * } * - * static void dump_map(const struct strmap_intp *map) + * static void dump_map(const strmap_intp *map) * { * int max = 100; * strmap_iterate(map, dump_some, &max); @@ -181,7 +176,7 @@ void strmap_clear_(struct strmap *map); * } */ #define strmap_iterate(map, handle, arg) \ - strmap_iterate_(&(map)->raw, \ + strmap_iterate_(tcon_unwrap(map), \ typesafe_cb_cast(bool (*)(const char *, \ void *, void *), \ bool (*)(const char *, \ @@ -202,7 +197,7 @@ void strmap_iterate_(const struct strmap *map, * strmap_empty() on the returned pointer. * * Example: - * static void dump_prefix(const struct strmap_intp *map, + * static void dump_prefix(const strmap_intp *map, * const char *prefix) * { * int max = 100; @@ -214,10 +209,10 @@ void strmap_iterate_(const struct strmap *map, */ #if HAVE_TYPEOF #define strmap_prefix(map, prefix) \ - ((const __typeof__(map))strmap_prefix_(&(map)->raw, (prefix))) + ((const __typeof__(map))strmap_prefix_(tcon_unwrap(map), (prefix))) #else #define strmap_prefix(map, prefix) \ - ((const void *)strmap_prefix_(&(map)->raw, (prefix))) + ((const void *)strmap_prefix_(tcon_unwrap(map), (prefix))) #endif const struct strmap *strmap_prefix_(const struct strmap *map, diff --git a/ccan/ccan/strmap/test/run-iterate-const.c b/ccan/ccan/strmap/test/run-iterate-const.c index 07c814a3d..63bea9523 100644 --- a/ccan/ccan/strmap/test/run-iterate-const.c +++ b/ccan/ccan/strmap/test/run-iterate-const.c @@ -14,9 +14,7 @@ static bool find_string(const char *str, char *member, const char *cmp) int main(void) { - struct strmap_charp { - STRMAP_MEMBERS(char *); - } map; + STRMAP(char *) map; plan_tests(3); diff --git a/ccan/ccan/strmap/test/run-order.c b/ccan/ccan/strmap/test/run-order.c index 68062eab0..b541666d8 100644 --- a/ccan/ccan/strmap/test/run-order.c +++ b/ccan/ccan/strmap/test/run-order.c @@ -33,9 +33,7 @@ static bool dump(const char *member, char *value, bool *ok) int main(void) { - struct strmap_charp { - STRMAP_MEMBERS(char *); - } map; + STRMAP(char *) map; unsigned int i; char *str[NUM]; bool dump_ok; diff --git a/ccan/ccan/strmap/test/run-prefix.c b/ccan/ccan/strmap/test/run-prefix.c index 9c5156e6e..d88eb5565 100644 --- a/ccan/ccan/strmap/test/run-prefix.c +++ b/ccan/ccan/strmap/test/run-prefix.c @@ -24,11 +24,9 @@ static bool find_empty(const char *index, char *value, char *empty) int main(void) { - struct map { - STRMAP_MEMBERS(char *); - }; - struct map map; - const struct map *sub; + typedef STRMAP(char *) map_t; + map_t map; + const map_t *sub; unsigned int i; char *str[NUM], *empty; @@ -56,9 +54,9 @@ int main(void) /* Everything */ sub = strmap_prefix(&map, "0"); - ok1(sub->raw.u.n == map.raw.u.n); + ok1(tcon_unwrap(sub)->u.n == tcon_unwrap(&map)->u.n); sub = strmap_prefix(&map, ""); - ok1(sub->raw.u.n == map.raw.u.n); + ok1(tcon_unwrap(sub)->u.n == tcon_unwrap(&map)->u.n); /* Single. */ sub = strmap_prefix(&map, "00000000"); diff --git a/ccan/ccan/strmap/test/run.c b/ccan/ccan/strmap/test/run.c index aaa861812..f64ddc5e5 100644 --- a/ccan/ccan/strmap/test/run.c +++ b/ccan/ccan/strmap/test/run.c @@ -4,9 +4,7 @@ int main(void) { - struct strmap_charp { - STRMAP_MEMBERS(char *); - } map; + STRMAP(char *) map; const char str[] = "hello"; const char val[] = "there"; const char none[] = ""; diff --git a/ccan/config.h b/ccan/config.h index bd5662ad4..da7d01396 100644 --- a/ccan/config.h +++ b/ccan/config.h @@ -66,4 +66,6 @@ #define HAVE_WARN_UNUSED_RESULT 1 #define HAVE_OPENMP 1 #define HAVE_VALGRIND_MEMCHECK_H 1 +#define HAVE_UCONTEXT 1 +#define HAVE_POINTER_SAFE_MAKECONTEXT 1 #endif /* CCAN_CONFIG_H */ diff --git a/ccan/tools/configurator/configurator.c b/ccan/tools/configurator/configurator.c index a590a8d4f..5d959cf33 100644 --- a/ccan/tools/configurator/configurator.c +++ b/ccan/tools/configurator/configurator.c @@ -319,6 +319,52 @@ static struct test tests[] = { "-Werror -fopenmp" }, { "HAVE_VALGRIND_MEMCHECK_H", OUTSIDE_MAIN, NULL, NULL, "#include \n" }, + { "HAVE_UCONTEXT", DEFINES_EVERYTHING|EXECUTE, + NULL, NULL, + "#include \n" + "static int x = 0;\n" + "static char stack[2048];\n" + "static ucontext_t a, b;\n" + "static void fn(void) {\n" + " x |= 2;\n" + " setcontext(&b);\n" + " x |= 4;\n" + "}\n" + "int main(int argc, char *argv[]) {\n" + " x |= 1;\n" + " getcontext(&a);\n" + " a.uc_stack.ss_sp = stack;\n" + " a.uc_stack.ss_size = sizeof(stack);\n" + " makecontext(&a, fn, 0);\n" + " swapcontext(&b, &a);\n" + " return (x == 3) ? 0 : 1;\n" + "}\n" + }, + { "HAVE_POINTER_SAFE_MAKECONTEXT", DEFINES_EVERYTHING|EXECUTE, + "HAVE_UCONTEXT", NULL, + "#include \n" + "#include \n" + "static int worked = 0;\n" + "static char stack[1024];\n" + "static ucontext_t a, b;\n" + "static void fn(void *p, void *q) {\n" + " void *cp = &worked;\n" + " void *cq = (void *)(~((ptrdiff_t)cp));\n" + " if ((p == cp) && (q == cq))\n" + " worked = 1;\n" + " setcontext(&b);\n" + "}\n" + "int main(int argc, char *argv[]) {\n" + " void *ap = &worked;\n" + " void *aq = (void *)(~((ptrdiff_t)ap));\n" + " getcontext(&a);\n" + " a.uc_stack.ss_sp = stack;\n" + " a.uc_stack.ss_size = sizeof(stack);\n" + " makecontext(&a, (void (*)(void))fn, 2, ap, aq);\n" + " swapcontext(&b, &a);\n" + " return worked ? 0 : 1;\n" + "}\n" + }, }; static char *grab_fd(int fd) @@ -497,7 +543,8 @@ static bool run_test(const char *cmd, struct test *test) fclose(outf); if (verbose > 1) - if (system("cat " INPUT_FILE) == -1); + if (system("cat " INPUT_FILE) == -1) + ; newcmd = strdup(cmd);