diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/birdlib.h | 14 | ||||
-rw-r--r-- | lib/ip.c | 5 | ||||
-rw-r--r-- | lib/ip_test.c | 37 | ||||
-rw-r--r-- | lib/lists.c | 79 | ||||
-rw-r--r-- | lib/lists_test.c | 13 | ||||
-rw-r--r-- | lib/resource.c | 3 | ||||
-rw-r--r-- | lib/slab.c | 7 | ||||
-rw-r--r-- | lib/string.h | 9 | ||||
-rw-r--r-- | lib/timer.c | 2 |
9 files changed, 138 insertions, 31 deletions
diff --git a/lib/birdlib.h b/lib/birdlib.h index 5202b0c8..23036c1b 100644 --- a/lib/birdlib.h +++ b/lib/birdlib.h @@ -72,6 +72,7 @@ static inline int u64_cmp(u64 i1, u64 i2) #define NORET __attribute__((noreturn)) #define UNUSED __attribute__((unused)) #define PACKED __attribute__((packed)) +#define NONNULL(...) __attribute__((nonnull((__VA_ARGS__)))) #ifndef HAVE_THREAD_LOCAL #define _Thread_local @@ -162,12 +163,23 @@ void debug(const char *msg, ...); /* Printf to debug output */ #define DBG(x, y...) do { } while(0) #endif +#define ASSERT_DIE(x) do { if (!(x)) bug("Assertion '%s' failed at %s:%d", #x, __FILE__, __LINE__); } while(0) + +#define EXPENSIVE_CHECK(x) /* intentionally left blank */ + #ifdef DEBUGGING -#define ASSERT(x) do { if (!(x)) bug("Assertion '%s' failed at %s:%d", #x, __FILE__, __LINE__); } while(0) +#define ASSERT(x) ASSERT_DIE(x) +#define ASSUME(x) ASSERT_DIE(x) +#ifdef ENABLE_EXPENSIVE_CHECKS +#undef EXPENSIVE_CHECK +#define EXPENSIVE_CHECK(x) ASSERT_DIE(x) +#endif #else #define ASSERT(x) do { if (!(x)) log(L_BUG "Assertion '%s' failed at %s:%d", #x, __FILE__, __LINE__); } while(0) +#define ASSUME(x) /* intentionally left blank */ #endif + #ifdef DEBUGGING asm( ".pushsection \".debug_gdb_scripts\", \"MS\",@progbits,1\n" @@ -264,6 +264,9 @@ ip6_pton(const char *a, ip6_addr *o) int i, j, k, l, hfil; const char *start; + if (!a[0]) /* Empty string check */ + return 0; + if (a[0] == ':') /* Leading :: */ { if (a[1] != ':') @@ -333,6 +336,8 @@ ip6_pton(const char *a, ip6_addr *o) for (; i>=hfil; i--) words[i] = 0; } + else if (i != 8) /* Incomplete address */ + return 0; /* Convert the address to ip6_addr format */ for (i=0; i<4; i++) diff --git a/lib/ip_test.c b/lib/ip_test.c index fd70c957..36d10d68 100644 --- a/lib/ip_test.c +++ b/lib/ip_test.c @@ -13,25 +13,38 @@ #define IP4_MAX_LEN 16 static int -test_ipa_pton(void *out_, const void *in_, const void *expected_out_) +test_ip4_pton(void *out_, const void *in_, const void *expected_out_) { ip_addr *out = out_; const char *in = in_; const ip_addr *expected_out = expected_out_; + ip4_addr ip4; - if (ipa_is_ip4(*expected_out)) + if (expected_out) { - ip4_addr ip4; bt_assert(ip4_pton(in, &ip4)); *out = ipa_from_ip4(ip4); + return ipa_equal(*out, *expected_out); } else + return !ip4_pton(in, &ip4); + +} + +static int +test_ip6_pton(void *out_, const void *in_, const void *expected_out_) +{ + ip_addr *out = out_; + const char *in = in_; + const ip_addr *expected_out = expected_out_; + + if (expected_out) { bt_assert(ip6_pton(in, out)); - /* ip_addr == ip6_addr */ + return ipa_equal(*out, *expected_out); } - - return ipa_equal(*out, *expected_out); + else + return !ip6_pton(in, out); } static int @@ -52,7 +65,7 @@ t_ip4_pton(void) }, }; - return bt_assert_batch(test_vectors, test_ipa_pton, bt_fmt_str, bt_fmt_ipa); + return bt_assert_batch(test_vectors, test_ip4_pton, bt_fmt_str, bt_fmt_ipa); } static int @@ -87,9 +100,17 @@ t_ip6_pton(void) .in = "2605:2700:0:3::4713:93e3", .out = & ipa_build6(0x26052700, 0x00000003, 0x00000000, 0x471393E3), }, + { + .in = "2605:2700:0:3:4713:93e3", + .out = NULL, + }, + { + .in = "2", + .out = NULL, + }, }; - return bt_assert_batch(test_vectors, test_ipa_pton, bt_fmt_str, bt_fmt_ipa); + return bt_assert_batch(test_vectors, test_ip6_pton, bt_fmt_str, bt_fmt_ipa); } static int diff --git a/lib/lists.c b/lib/lists.c index 4a48d3b7..200576cf 100644 --- a/lib/lists.c +++ b/lib/lists.c @@ -29,6 +29,42 @@ #include "nest/bird.h" #include "lib/lists.h" +LIST_INLINE int +check_list(list *l, node *n) +{ + if (!l) + { + ASSERT_DIE(n); + ASSERT_DIE(n->prev); + + do { n = n->prev; } while (n->prev); + + l = SKIP_BACK(list, head_node, n); + } + + int seen = 0; + + ASSERT_DIE(l->null == NULL); + ASSERT_DIE(l->head != NULL); + ASSERT_DIE(l->tail != NULL); + + node *prev = &l->head_node, *cur = l->head, *next = l->head->next; + while (next) + { + if (cur == n) + seen++; + ASSERT_DIE(cur->prev == prev); + prev = cur; + cur = next; + next = next->next; + } + + ASSERT_DIE(cur == &(l->tail_node)); + ASSERT_DIE(!n || (seen == 1)); + + return 1; +} + /** * add_tail - append a node to a list * @l: linked list @@ -39,6 +75,10 @@ LIST_INLINE void add_tail(list *l, node *n) { + EXPENSIVE_CHECK(check_list(l, NULL)); + ASSUME(n->prev == NULL); + ASSUME(n->next == NULL); + node *z = l->tail; n->next = &l->tail_node; @@ -57,6 +97,10 @@ add_tail(list *l, node *n) LIST_INLINE void add_head(list *l, node *n) { + EXPENSIVE_CHECK(check_list(l, NULL)); + ASSUME(n->prev == NULL); + ASSUME(n->next == NULL); + node *z = l->head; n->next = z; @@ -76,6 +120,10 @@ add_head(list *l, node *n) LIST_INLINE void insert_node(node *n, node *after) { + EXPENSIVE_CHECK(check_list(l, after)); + ASSUME(n->prev == NULL); + ASSUME(n->next == NULL); + node *z = after->next; n->next = z; @@ -93,6 +141,8 @@ insert_node(node *n, node *after) LIST_INLINE void rem_node(node *n) { + EXPENSIVE_CHECK(check_list(NULL, n)); + node *z = n->prev; node *x = n->next; @@ -103,24 +153,20 @@ rem_node(node *n) } /** - * replace_node - replace a node in a list with another one - * @old: node to be removed - * @new: node to be inserted + * update_node - update node after calling realloc on it + * @n: node to be updated * - * Replaces node @old in the list it's linked in with node @new. Node - * @old may be a copy of the original node, which is not accessed - * through the list. The function could be called with @old == @new, - * which just fixes neighbors' pointers in the case that the node - * was reallocated. + * Fixes neighbor pointers. */ LIST_INLINE void -replace_node(node *old, node *new) +update_node(node *n) { - old->next->prev = new; - old->prev->next = new; + ASSUME(n->next->prev == n->prev->next); - new->prev = old->prev; - new->next = old->next; + n->next->prev = n; + n->prev->next = n; + + EXPENSIVE_CHECK(check_list(NULL, n)); } /** @@ -149,6 +195,9 @@ init_list(list *l) LIST_INLINE void add_tail_list(list *to, list *l) { + EXPENSIVE_CHECK(check_list(to, NULL)); + EXPENSIVE_CHECK(check_list(l, NULL)); + node *p = to->tail; node *q = l->head; @@ -157,6 +206,8 @@ add_tail_list(list *to, list *l) q = l->tail; q->next = &to->tail_node; to->tail = q; + + EXPENSIVE_CHECK(check_list(to, NULL)); } LIST_INLINE uint @@ -165,6 +216,8 @@ list_length(list *l) uint len = 0; node *n; + EXPENSIVE_CHECK(check_list(l, NULL)); + WALK_LIST(n, *l) len++; diff --git a/lib/lists_test.c b/lib/lists_test.c index f26a88e2..cf0021fe 100644 --- a/lib/lists_test.c +++ b/lib/lists_test.c @@ -222,26 +222,29 @@ t_remove_node(void) } static int -t_replace_node(void) +t_update_node(void) { node head, inside, tail; init_list_(); fill_list(); - replace_node(&nodes[0], &head); + head = nodes[0]; + update_node(&head); bt_assert(l.head == &head); bt_assert(head.prev == NODE &l.head); bt_assert(head.next == &nodes[1]); bt_assert(nodes[1].prev == &head); - replace_node(&nodes[MAX_NUM/2], &inside); + inside = nodes[MAX_NUM/2]; + update_node(&inside); bt_assert(nodes[MAX_NUM/2-1].next == &inside); bt_assert(nodes[MAX_NUM/2+1].prev == &inside); bt_assert(inside.prev == &nodes[MAX_NUM/2-1]); bt_assert(inside.next == &nodes[MAX_NUM/2+1]); - replace_node(&nodes[MAX_NUM-1], &tail); + tail = nodes[MAX_NUM-1]; + update_node(&tail); bt_assert(l.tail == &tail); bt_assert(tail.prev == &nodes[MAX_NUM-2]); bt_assert(tail.next == NODE &l.null); @@ -280,7 +283,7 @@ main(int argc, char *argv[]) bt_test_suite(t_add_head, "Adding nodes to head of list"); bt_test_suite(t_insert_node, "Inserting nodes to list"); bt_test_suite(t_remove_node, "Removing nodes from list"); - bt_test_suite(t_replace_node, "Replacing nodes in list"); + bt_test_suite(t_update_node, "Updating nodes in list"); bt_test_suite(t_add_tail_list, "At the tail of a list adding the another list"); return bt_exit_value(); diff --git a/lib/resource.c b/lib/resource.c index ab8c800f..5589373e 100644 --- a/lib/resource.c +++ b/lib/resource.c @@ -340,6 +340,7 @@ mb_alloc(pool *p, unsigned size) struct mblock *b = xmalloc(sizeof(struct mblock) + size); b->r.class = &mb_class; + b->r.n = (node) {}; add_tail(&p->inside, &b->r.n); b->size = size; return b->data; @@ -387,7 +388,7 @@ mb_realloc(void *m, unsigned size) struct mblock *b = SKIP_BACK(struct mblock, data, m); b = xrealloc(b, sizeof(struct mblock) + size); - replace_node(&b->r.n, &b->r.n); + update_node(&b->r.n); b->size = size; return b->data; } @@ -216,8 +216,11 @@ sl_new_head(slab *s) struct sl_obj *no; uint n = s->objs_per_slab; - h->first_free = o; - h->num_full = 0; + *h = (struct sl_head) { + .first_free = o, + .num_full = 0, + }; + while (n--) { o->slab = h; diff --git a/lib/string.h b/lib/string.h index d6ae5ef7..0f650178 100644 --- a/lib/string.h +++ b/lib/string.h @@ -72,6 +72,15 @@ bstrcmp(const char *s1, const char *s2) return !s2 - !s1; } +static inline void * +bmemcpy(void *dest, const void *src, size_t n) +{ + if (n) + return memcpy(dest, src, n); + else + return dest; +} + #define ROUTER_ID_64_LENGTH 23 #endif diff --git a/lib/timer.c b/lib/timer.c index be695114..a5abbcc4 100644 --- a/lib/timer.c +++ b/lib/timer.c @@ -255,7 +255,7 @@ timer_init(void) btime tm_parse_time(const char *x) { - struct tm tm; + struct tm tm = {}; int usec, n1, n2, n3, r; r = sscanf(x, "%d-%d-%d%n %d:%d:%d%n.%d%n", |