Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 3 Sep 2016 01:08:52 +0000 (UTC)
From:      "Andrey A. Chernov" <ache@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r305316 - stable/10/lib/libc/net
Message-ID:  <201609030108.u8318q1b093612@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ache
Date: Sat Sep  3 01:08:52 2016
New Revision: 305316
URL: https://svnweb.freebsd.org/changeset/base/305316

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

Modified:
  stable/10/lib/libc/net/name6.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/lib/libc/net/name6.c
==============================================================================
--- stable/10/lib/libc/net/name6.c	Sat Sep  3 00:50:18 2016	(r305315)
+++ stable/10/lib/libc/net/name6.c	Sat Sep  3 01:08:52 2016	(r305316)
@@ -186,6 +186,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?201609030108.u8318q1b093612>