Fix a crash bug in tor_assert(md->held_by_node)

The fix is to turn held_by_node into a reference count.

Fixes bug 4118; bugfix on 0.2.3.1-alpha.
This commit is contained in:
Nick Mathewson 2011-09-28 13:29:01 -04:00
parent e98c9a1bf6
commit a4b7525c3c
4 changed files with 19 additions and 14 deletions

5
changes/bug4118 Normal file
View File

@ -0,0 +1,5 @@
o Major bugfixes:
- Fix a crash bug that could occur when the same microdescriptor was
referenced by two node_t objects at once. Fix for bug 4118; bugfix
on Tor 0.2.3.1-alpha.

View File

@ -522,7 +522,7 @@ microdesc_free(microdesc_t *md)
}
tor_fragile_assert();
}
if (md->held_by_node) {
if (md->held_by_nodes) {
int found=0;
const smartlist_t *nodes = nodelist_get_list();
SMARTLIST_FOREACH(nodes, node_t *, node, {
@ -533,15 +533,15 @@ microdesc_free(microdesc_t *md)
});
if (found) {
log_warn(LD_BUG, "microdesc_free() called, but md was still referenced "
"%d node(s)", found);
"%d node(s); held_by_nodes == %u", found, md->held_by_nodes);
} else {
log_warn(LD_BUG, "microdesc_free() called with held_by_node set, but "
log_warn(LD_BUG, "microdesc_free() called with held_by_nodes set, but "
"md was not refrenced by any nodes");
}
tor_fragile_assert();
}
//tor_assert(md->held_in_map == 0);
//tor_assert(md->held_by_node == 0);
//tor_assert(md->held_by_nodes == 0);
if (md->onion_pkey)
crypto_free_pk_env(md->onion_pkey);

View File

@ -160,9 +160,9 @@ nodelist_add_microdesc(microdesc_t *md)
node = node_get_mutable_by_id(rs->identity_digest);
if (node) {
if (node->md)
node->md->held_by_node = 0;
node->md->held_by_nodes--;
node->md = md;
md->held_by_node = 1;
md->held_by_nodes++;
}
return node;
}
@ -189,11 +189,11 @@ nodelist_set_consensus(networkstatus_t *ns)
if (node->md == NULL ||
tor_memneq(node->md->digest,rs->descriptor_digest,DIGEST256_LEN)) {
if (node->md)
node->md->held_by_node = 0;
node->md->held_by_nodes--;
node->md = microdesc_cache_lookup_by_digest256(NULL,
rs->descriptor_digest);
if (node->md)
node->md->held_by_node = 1;
node->md->held_by_nodes++;
}
}
@ -250,7 +250,7 @@ nodelist_remove_microdesc(const char *identity_digest, microdesc_t *md)
node_t *node = node_get_mutable_by_id(identity_digest);
if (node && node->md == md) {
node->md = NULL;
md->held_by_node = 0;
md->held_by_nodes--;
}
}
@ -299,7 +299,7 @@ node_free(node_t *node)
if (!node)
return;
if (node->md)
node->md->held_by_node = 0;
node->md->held_by_nodes--;
tor_assert(node->nodelist_idx == -1);
tor_free(node);
}
@ -319,7 +319,7 @@ nodelist_purge(void)
if (node->md && !node->rs) {
/* An md is only useful if there is an rs. */
node->md->held_by_node = 0;
node->md->held_by_nodes--;
node->md = NULL;
}
@ -394,7 +394,7 @@ nodelist_assert_ok(void)
microdesc_cache_lookup_by_digest256(NULL, rs->descriptor_digest);
tor_assert(md == node->md);
if (md)
tor_assert(md->held_by_node == 1);
tor_assert(md->held_by_nodes >= 1);
}
} SMARTLIST_FOREACH_END(rs);
}

View File

@ -1830,10 +1830,10 @@ typedef struct microdesc_t {
saved_location_t saved_location : 3;
/** If true, do not attempt to cache this microdescriptor on disk. */
unsigned int no_save : 1;
/** If true, this microdesc is attached to a node_t. */
unsigned int held_by_node : 1;
/** If true, this microdesc has an entry in the microdesc_map */
unsigned int held_in_map : 1;
/** Reference count: how many node_ts have a reference to this microdesc? */
unsigned int held_by_nodes;
/** If saved_location == SAVED_IN_CACHE, this field holds the offset of the
* microdescriptor in the cache. */