changeset 4658:c92289afb5be stable-1.2

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.
author Maxim Dounin <mdounin@mdounin.ru>
date Mon, 04 Jun 2012 10:15:55 +0000
parents 36b220b82f23
children f12d474f0d5e
files src/core/ngx_resolver.c
diffstat 1 files changed, 14 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- 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;