Fix segfault during failed allocatino of locked evdns base.

We need to comb the rest of the code to make sure that we don't blindly wrap
functions in LOCK(x), UNLOCK(x) when those functions might contain a FREE(x)
in the middle.

Rocco Carbone found and reported this bug.

svn:r1384
This commit is contained in:
Nick Mathewson 2009-07-28 17:11:03 +00:00
parent f8b527e6a1
commit 12199fa7a5
2 changed files with 17 additions and 7 deletions

View File

@ -1,6 +1,7 @@
Changes in 2.0.3-alpha:
o Add a new code to support SSL/TLS on bufferevents, using the OpenSSL library (where available).
o Fix a bug where we didn't allocate enough memory in event_get_supported_methods().
o Avoid segfault during failed allocation of locked evdns_base. (Found by Rocco Carbone.)
Changes in 2.0.2-alpha:
o Add a new flag to bufferevents to make all callbacks automatically deferred.

23
evdns.c
View File

@ -386,6 +386,7 @@ static void server_port_ready_callback(evutil_socket_t fd, short events, void *a
static int evdns_base_resolv_conf_parse_impl(struct evdns_base *base, int flags, const char *const filename);
static int evdns_base_set_option_impl(struct evdns_base *base,
const char *option, const char *val, int flags);
static void evdns_base_free_and_unlock(struct evdns_base *base, int fail_requests);
static int strtoint(const char *const str);
@ -3608,8 +3609,8 @@ evdns_base_new(struct event_base *event_base, int initialize_nameservers)
r = evdns_base_resolv_conf_parse(base, DNS_OPTIONS_ALL, "/etc/resolv.conf");
#endif
if (r == -1) {
evdns_base_free(base, 0);
base = NULL;
evdns_base_free_and_unlock(base, 0);
return NULL;
}
}
EVDNS_UNLOCK(base);
@ -3648,16 +3649,16 @@ evdns_err_to_string(int err)
}
}
void
evdns_base_free(struct evdns_base *base, int fail_requests)
static void
evdns_base_free_and_unlock(struct evdns_base *base, int fail_requests)
{
struct nameserver *server, *server_next;
struct search_domain *dom, *dom_next;
int i;
/* TODO(nickm) we might need to refcount here. */
/* Requires that we hold the lock. */
EVDNS_LOCK(base);
/* TODO(nickm) we might need to refcount here. */
for (i = 0; i < base->n_req_heads; ++i) {
while (base->req_heads[i]) {
@ -3701,12 +3702,20 @@ evdns_base_free(struct evdns_base *base, int fail_requests)
mm_free(base);
}
void
evdns_base_free(struct evdns_base *base, int fail_requests)
{
EVDNS_LOCK(base);
evdns_base_free_and_unlock(base, fail_requests);
}
void
evdns_shutdown(int fail_requests)
{
if (current_base) {
evdns_base_free(current_base, fail_requests);
struct evdns_base *b = current_base;
current_base = NULL;
evdns_base_free(b, fail_requests);
}
evdns_log_fn = NULL;
}