Module Name:    src
Committed By:   riastradh
Date:           Fri Apr  5 00:43:42 UTC 2024

Modified Files:
        src/usr.bin/config: defs.h files.c mkioconf.c mkmakefile.c pack.c

Log Message:
config(1): Make sort order deterministic.

Ensure we break ties in every case.  This way, even though we use the
unstable qsort(3) library routine, the output is reproducible, no
matter what algorithm is behind qsort(3).

It would be nice if we could just use a stable sort function here,
but mergesort(3) is nonstandard, so we'd have to add it to
tools/compat, which is a big pain.

Instead, put a tie-breaking rule in every comparison function we use
with qsort, and abort() in the event of ties -- that way, we noisily
refuse to rely on unstable sort order.

While here, dispense with any question of integer overflow, and
sprinkle comments.

PR bin/58115


To generate a diff of this commit:
cvs rdiff -u -r1.108 -r1.109 src/usr.bin/config/defs.h
cvs rdiff -u -r1.37 -r1.38 src/usr.bin/config/files.c
cvs rdiff -u -r1.35 -r1.36 src/usr.bin/config/mkioconf.c
cvs rdiff -u -r1.72 -r1.73 src/usr.bin/config/mkmakefile.c
cvs rdiff -u -r1.10 -r1.11 src/usr.bin/config/pack.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/config/defs.h
diff -u src/usr.bin/config/defs.h:1.108 src/usr.bin/config/defs.h:1.109
--- src/usr.bin/config/defs.h:1.108	Thu Jan 18 05:41:38 2024
+++ src/usr.bin/config/defs.h	Fri Apr  5 00:43:42 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: defs.h,v 1.108 2024/01/18 05:41:38 thorpej Exp $	*/
+/*	$NetBSD: defs.h,v 1.109 2024/04/05 00:43:42 riastradh Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -207,6 +207,8 @@ struct attr {
 	/* "device class" */
 	const char *a_devclass;		/* device class described */
 	struct where a_where;
+
+	size_t	a_idx;			/* index to break sorting ties */
 };
 
 /*

Index: src/usr.bin/config/files.c
diff -u src/usr.bin/config/files.c:1.37 src/usr.bin/config/files.c:1.38
--- src/usr.bin/config/files.c:1.37	Sat Mar  7 19:26:13 2020
+++ src/usr.bin/config/files.c	Fri Apr  5 00:43:42 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: files.c,v 1.37 2020/03/07 19:26:13 christos Exp $	*/
+/*	$NetBSD: files.c,v 1.38 2024/04/05 00:43:42 riastradh Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -45,7 +45,7 @@
 #endif
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: files.c,v 1.37 2020/03/07 19:26:13 christos Exp $");
+__RCSID("$NetBSD: files.c,v 1.38 2024/04/05 00:43:42 riastradh Exp $");
 
 #include <sys/param.h>
 #include <assert.h>
@@ -281,9 +281,9 @@ cmpfiles(const void *a, const void *b)
 	if (sa < sb)
 		return -1;
 	else if (sa > sb)
-		return 1;
+		return +1;
 	else
-		return 0;
+		abort();	/* no ties possible */
 }
 
 /*

Index: src/usr.bin/config/mkioconf.c
diff -u src/usr.bin/config/mkioconf.c:1.35 src/usr.bin/config/mkioconf.c:1.36
--- src/usr.bin/config/mkioconf.c:1.35	Sun Nov 19 01:46:29 2017
+++ src/usr.bin/config/mkioconf.c	Fri Apr  5 00:43:42 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: mkioconf.c,v 1.35 2017/11/19 01:46:29 christos Exp $	*/
+/*	$NetBSD: mkioconf.c,v 1.36 2024/04/05 00:43:42 riastradh Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -45,7 +45,7 @@
 #endif
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: mkioconf.c,v 1.35 2017/11/19 01:46:29 christos Exp $");
+__RCSID("$NetBSD: mkioconf.c,v 1.36 2024/04/05 00:43:42 riastradh Exp $");
 
 #include <sys/param.h>
 #include <err.h>
@@ -136,7 +136,12 @@ cforder(const void *a, const void *b)
 
 	n1 = (*(const struct devi * const *)a)->i_cfindex;
 	n2 = (*(const struct devi * const *)b)->i_cfindex;
-	return (n1 - n2);
+	if (n1 < n2)
+		return -1;
+	else if (n1 > n2)
+		return +1;
+	else
+		abort();	/* no ties possible */
 }
 
 static void

Index: src/usr.bin/config/mkmakefile.c
diff -u src/usr.bin/config/mkmakefile.c:1.72 src/usr.bin/config/mkmakefile.c:1.73
--- src/usr.bin/config/mkmakefile.c:1.72	Thu Jan 18 04:41:37 2024
+++ src/usr.bin/config/mkmakefile.c	Fri Apr  5 00:43:42 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: mkmakefile.c,v 1.72 2024/01/18 04:41:37 thorpej Exp $	*/
+/*	$NetBSD: mkmakefile.c,v 1.73 2024/04/05 00:43:42 riastradh Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -45,7 +45,7 @@
 #endif
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: mkmakefile.c,v 1.72 2024/01/18 04:41:37 thorpej Exp $");
+__RCSID("$NetBSD: mkmakefile.c,v 1.73 2024/04/05 00:43:42 riastradh Exp $");
 
 #include <sys/param.h>
 #include <ctype.h>
@@ -413,6 +413,7 @@ emitallkobjscb(const char *name, void *v
 		return 0;
 	if (TAILQ_EMPTY(&a->a_files))
 		return 0;
+	a->a_idx = attridx;
 	attrbuf[attridx++] = a;
 	/* XXX nattrs tracking is not exact yet */
 	if (attridx == nattrs) {
@@ -447,7 +448,21 @@ attrcmp(const void *l, const void *r)
 {
 	const struct attr * const *a = l, * const *b = r;
 	const int wa = (*a)->a_weight, wb = (*b)->a_weight;
-	return (wa > wb) ? -1 : (wa < wb) ? 1 : 0;
+
+	/*
+	 * Higher-weight first; then, among equal weights, earlier
+	 * index first.
+	 */
+	if (wa > wb)
+		return -1;
+	else if (wa < wb)
+		return +1;
+	else if ((*a)->a_idx < (*b)->a_idx)
+		return -1;
+	else if ((*a)->a_idx > (*b)->a_idx)
+		return +1;
+	else
+		abort();	/* no ties possible */
 }
 
 static void

Index: src/usr.bin/config/pack.c
diff -u src/usr.bin/config/pack.c:1.10 src/usr.bin/config/pack.c:1.11
--- src/usr.bin/config/pack.c:1.10	Sat Sep 12 19:11:13 2015
+++ src/usr.bin/config/pack.c	Fri Apr  5 00:43:42 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: pack.c,v 1.10 2015/09/12 19:11:13 joerg Exp $	*/
+/*	$NetBSD: pack.c,v 1.11 2024/04/05 00:43:42 riastradh Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -45,7 +45,7 @@
 #endif
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: pack.c,v 1.10 2015/09/12 19:11:13 joerg Exp $");
+__RCSID("$NetBSD: pack.c,v 1.11 2024/04/05 00:43:42 riastradh Exp $");
 
 #include <sys/param.h>
 #include <stdlib.h>
@@ -319,21 +319,38 @@ addlocs(const char **locs, int len)
 
 /*
  * Comparison function for qsort-by-locator-length, longest first.
- * We rashly assume that subtraction of these lengths does not overflow.
+ *
+ * In the event of equality, break ties by i_cfindex, which should be
+ * unique, obviating the need for a stable sort.
  */
 static int
 loclencmp(const void *a, const void *b)
 {
+	const struct devi *const *d1p = a, *d1 = *d1p;
+	const struct devi *const *d2p = b, *d2 = *d2p;
 	const struct pspec *p1, *p2;
 	int l1, l2;
 
-	p1 = (*(const struct devi * const *)a)->i_pspec;
+	p1 = d1->i_pspec;
 	l1 = p1 != NULL ? p1->p_iattr->a_loclen : 0;
 
-	p2 = (*(const struct devi * const *)b)->i_pspec;
+	p2 = d2->i_pspec;
 	l2 = p2 != NULL ? p2->p_iattr->a_loclen : 0;
 
-	return (l2 - l1);
+	/*
+	 * Longer locators first; among equal locator lengths, earliest
+	 * index first.
+	 */
+	if (l2 < l1)
+		return -1;
+	else if (l2 > l1)
+		return +1;
+	else if (d2->i_cfindex > d1->i_cfindex)
+		return -1;
+	else if (d2->i_cfindex < d1->i_cfindex)
+		return +1;
+	else
+		abort();	/* no ties possible */
 }
 
 static void

Reply via email to