about summary refs log tree commit diff
path: root/resolv/resolv_conf.c
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2017-07-04 14:47:29 +0200
committerFlorian Weimer <fweimer@redhat.com>2017-07-04 15:26:05 +0200
commit4446a885f3aeb3a33b95c72bae1f115bed77f0cb (patch)
treecb00db2c2f0dddc2898640dd46331876e72b6171 /resolv/resolv_conf.c
parentf0107724c92eefbc0637e2a7e142adf57e87e30b (diff)
downloadglibc-4446a885f3aeb3a33b95c72bae1f115bed77f0cb.tar.gz
glibc-4446a885f3aeb3a33b95c72bae1f115bed77f0cb.tar.xz
glibc-4446a885f3aeb3a33b95c72bae1f115bed77f0cb.zip
resolv: Fix resolv_conf _res matching
A dot-less host name without an /etc/resolv.conf file caused an
assertion failure in update_from_conf because the function would not
deal correctly with the empty search list case.

Thanks to Andreas Schwab for debugging assistence.
Diffstat (limited to 'resolv/resolv_conf.c')
-rw-r--r--resolv/resolv_conf.c24
1 files changed, 21 insertions, 3 deletions
diff --git a/resolv/resolv_conf.c b/resolv/resolv_conf.c
index 0ed36cde02..f391d30c27 100644
--- a/resolv/resolv_conf.c
+++ b/resolv/resolv_conf.c
@@ -272,7 +272,7 @@ resolv_conf_matches (const struct __res_state *resp,
       nserv = MAXNS;
     /* _ext.nscount is 0 until initialized by res_send.c.  */
     if (resp->nscount != nserv
-        && (resp->_u._ext.nscount != 0 && resp->_u._ext.nscount != nserv))
+        || (resp->_u._ext.nscount != 0 && resp->_u._ext.nscount != nserv))
       return false;
     for (size_t i = 0; i < nserv; ++i)
       {
@@ -295,9 +295,25 @@ resolv_conf_matches (const struct __res_state *resp,
   /* Check that the search list in *RESP has not been modified by the
      application.  */
   {
-    if (!(resp->dnsrch[0] == resp->defdname
-          && resp->dnsrch[MAXDNSRCH] == NULL))
+    if (resp->dnsrch[0] == NULL)
+      {
+        /* Empty search list.  No default domain name.  */
+        return conf->search_list_size == 0 && resp->defdname[0] == '\0';
+      }
+
+    if (resp->dnsrch[0] != resp->defdname)
+      /* If the search list is not empty, it must start with the
+         default domain name.  */
+      return false;
+
+    size_t nsearch;
+    for (nsearch = 0; nsearch < MAXDNSRCH; ++nsearch)
+      if (resp->dnsrch[nsearch] == NULL)
+        break;
+    if (nsearch > MAXDNSRCH)
+      /* Search list is not null-terminated.  */
       return false;
+
     size_t search_list_size = 0;
     for (size_t i = 0; i < conf->search_list_size; ++i)
       {
@@ -326,6 +342,8 @@ resolv_conf_matches (const struct __res_state *resp,
     size_t nsort = conf->sort_list_size;
     if (nsort > MAXRESOLVSORT)
       nsort = MAXRESOLVSORT;
+    if (resp->nsort != nsort)
+      return false;
     for (size_t i = 0; i < nsort; ++i)
       if (resp->sort_list[i].addr.s_addr != conf->sort_list[i].addr.s_addr
           || resp->sort_list[i].mask != conf->sort_list[i].mask)