Browse Source

ccan: update (for htable_getfirst/getnext)

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 9 years ago
parent
commit
ab09a42350
  1. 2
      ccan/README
  2. 10
      ccan/ccan/cdump/cdump.c
  3. 10
      ccan/ccan/cdump/cdump.h
  4. 184
      ccan/ccan/crypto/shachain/design.txt
  5. 77
      ccan/ccan/crypto/shachain/shachain.c
  6. 37
      ccan/ccan/crypto/shachain/shachain.h
  7. 32
      ccan/ccan/crypto/shachain/test/run-8bit.c
  8. 13
      ccan/ccan/crypto/shachain/test/run-badhash.c
  9. 41
      ccan/ccan/crypto/shachain/test/run-can_derive.c
  10. 33
      ccan/ccan/crypto/shachain/test/run.c
  11. 56
      ccan/ccan/htable/htable_type.h
  12. 32
      ccan/ccan/htable/test/run-type.c
  13. 19
      ccan/ccan/mem/mem.c
  14. 16
      ccan/ccan/mem/mem.h
  15. 2
      ccan/ccan/strmap/_info
  16. 43
      ccan/ccan/strmap/strmap.h
  17. 4
      ccan/ccan/strmap/test/run-iterate-const.c
  18. 4
      ccan/ccan/strmap/test/run-order.c
  19. 12
      ccan/ccan/strmap/test/run-prefix.c
  20. 4
      ccan/ccan/strmap/test/run.c
  21. 2
      ccan/config.h
  22. 49
      ccan/tools/configurator/configurator.c

2
ccan/README

@ -1,3 +1,3 @@
CCAN imported from http://ccodearchive.net.
CCAN version: init-2136-g64e9e71
CCAN version: init-2181-g2953f51

10
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. */

10
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;
};
/**

184
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 <rusty@rustcorp.com.au>

77
ccan/ccan/crypto/shachain/shachain.c

@ -5,15 +5,39 @@
#include <string.h>
#include <assert.h>
#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;
}

37
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 <time.h>
*
* 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));
* }
* }

32
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();

13
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));

41
ccan/ccan/crypto/shachain/test/run-can_derive.c

@ -0,0 +1,41 @@
#define shachain_index_t uint8_t
#include <ccan/crypto/shachain/shachain.h>
/* Include the C files directly. */
#include <ccan/crypto/shachain/shachain.c>
#include <ccan/tap/tap.h>
#include <stdio.h>
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();
}

33
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();

56
ccan/ccan/htable/htable_type.h

@ -2,6 +2,7 @@
#ifndef CCAN_HTABLE_TYPE_H
#define CCAN_HTABLE_TYPE_H
#include <ccan/htable/htable.h>
#include <ccan/compiler/compiler.h>
#include "config.h"
/**
@ -30,9 +31,15 @@
* bool <name>_del(struct <name> *ht, const <type> *e);
* bool <name>_delkey(struct <name> *ht, const <keytype> *k);
*
* Find function return the matching element, or NULL:
* Find and return the (first) matching element, or NULL:
* type *<name>_get(const struct @name *ht, const <keytype> *k);
*
* Find and return all matching elements, or NULL:
* type *<name>_getfirst(const struct @name *ht, const <keytype> *k,
* struct <name>_iter *i);
* type *<name>_getnext(const struct @name *ht, const <keytype> *k,
* struct <name>_iter *i);
*
* Iteration over hashtable is also supported:
* type *<name>_first(const struct <name> *ht, struct <name>_iter *i);
* type *<name>_next(const struct <name> *ht, struct <name>_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); \

32
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();
}

19
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
}

16
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 */

2
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++)

43
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,

4
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);

4
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;

12
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");

4
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[] = "";

2
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 */

49
ccan/tools/configurator/configurator.c

@ -319,6 +319,52 @@ static struct test tests[] = {
"-Werror -fopenmp" },
{ "HAVE_VALGRIND_MEMCHECK_H", OUTSIDE_MAIN, NULL, NULL,
"#include <valgrind/memcheck.h>\n" },
{ "HAVE_UCONTEXT", DEFINES_EVERYTHING|EXECUTE,
NULL, NULL,
"#include <ucontext.h>\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 <stddef.h>\n"
"#include <ucontext.h>\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);

Loading…
Cancel
Save