# HG changeset patch # User Maxim Dounin # Date 1338804955 0 # Node ID c92289afb5bea7ab7aaa0841cc23b7da6b91028c # Parent 36b220b82f23c93cdbefdbcd03959f4a3542b882 Merge of r4611, r4620: resolver fixes. *) Fixed segmentation fault in ngx_resolver_create_name_query(). If name passed for resolution was { 0, NULL } (e.g. as a result of name server returning CNAME pointing to ".") pointer wrapped to (void *) -1 resulting in segmentation fault on an attempt to dereference it. Reported by Lanshun Zhou. *) Resolver: protection from duplicate responses. If we already had CNAME in resolver node (i.e. rn->cnlen and rn->u.cname set), and got additional response with A record, it resulted in rn->cnlen set and rn->u.cname overwritten by rn->u.addr (or rn->u.addrs), causing segmentation fault later in ngx_resolver_free_node() on an attempt to free overwritten rn->u.cname. The opposite (i.e. CNAME got after A) might cause similar problems as well. diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c --- a/src/core/ngx_resolver.c +++ b/src/core/ngx_resolver.c @@ -513,8 +513,10 @@ ngx_resolve_name_locked(ngx_resolver_t * /* lock alloc mutex */ - ngx_resolver_free_locked(r, rn->query); - rn->query = NULL; + if (rn->query) { + ngx_resolver_free_locked(r, rn->query); + rn->query = NULL; + } if (rn->cnlen) { ngx_resolver_free_locked(r, rn->u.cname); @@ -1409,6 +1411,9 @@ ngx_resolver_process_a(ngx_resolver_t *r ngx_resolver_free(r, addrs); } + ngx_resolver_free(r, rn->query); + rn->query = NULL; + return; } else if (cname) { @@ -1441,6 +1446,9 @@ ngx_resolver_process_a(ngx_resolver_t *r (void) ngx_resolve_name_locked(r, ctx); } + ngx_resolver_free(r, rn->query); + rn->query = NULL; + return; } @@ -1834,6 +1842,10 @@ ngx_resolver_create_name_query(ngx_resol p--; *p-- = '\0'; + if (ctx->name.len == 0) { + return NGX_DECLINED; + } + for (s = ctx->name.data + ctx->name.len - 1; s >= ctx->name.data; s--) { if (*s != '.') { *p = *s;