Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 31 Aug 2016 15:47:59 +0000 (UTC)
From:      "Andrey A. Chernov" <ache@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r305133 - head/lib/libc/net
Message-ID:  <201608311547.u7VFlxRg086518@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ache
Date: Wed Aug 31 15:47:58 2016
New Revision: 305133
URL: https://svnweb.freebsd.org/changeset/base/305133

Log:
  Apply the same qsort() usage fix as in r304911 getaddrinfo.c
  qsort() can't be stabilized with just return(-1) alone.
  
  MFC after:      3 days

Modified:
  head/lib/libc/net/name6.c

Modified: head/lib/libc/net/name6.c
==============================================================================
--- head/lib/libc/net/name6.c	Wed Aug 31 15:32:52 2016	(r305132)
+++ head/lib/libc/net/name6.c	Wed Aug 31 15:47:58 2016	(r305133)
@@ -185,6 +185,7 @@ struct hp_order {
 #define aio_sa aio_un.aiou_sa
 	int aio_matchlen;
 	char *aio_h_addr;
+	int aio_initial_sequence;
 };
 
 static struct	 hostent *_hpcopy(struct hostent *, int *);
@@ -711,6 +712,7 @@ _hpreorder(struct hostent *hp)
 		aio[i].aio_dstscope = gai_addr2scopetype(sa);
 		aio[i].aio_dstpolicy = match_addrselectpolicy(sa, &policyhead);
 		set_source(&aio[i], &policyhead);
+		aio[i].aio_initial_sequence = i;
 	}
 
 	/* perform sorting. */
@@ -1045,6 +1047,23 @@ comp_dst(const void *arg1, const void *a
 	}
 
 	/* Rule 10: Otherwise, leave the order unchanged. */
+
+	/* 
+	 * Note that qsort is unstable; so, we can't return zero and 
+	 * expect the order to be unchanged.
+	 * That also means we can't depend on the current position of
+	 * dst2 being after dst1.  We must enforce the initial order
+	 * with an explicit compare on the original position.
+	 * The qsort specification requires that "When the same objects 
+	 * (consisting of width bytes, irrespective of their current 
+	 * positions in the array) are passed more than once to the 
+	 * comparison function, the results shall be consistent with one 
+	 * another."  
+	 * In other words, If A < B, then we must also return B > A.
+	 */
+	if (dst2->aio_initial_sequence < dst1->aio_initial_sequence)
+		return(1);
+
 	return(-1);
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201608311547.u7VFlxRg086518>