Sat Aug 12 01:10:04 2017 UTC ()
PR lib/50316: Gracefully handle a zero number of members argument.

Taken from FreeBSD (which fixed this same issue long ago).

XXX: pullup-8
XXX: pullup-7
XXX: pullup-6


(ginsbach)
diff -r1.14 -r1.15 src/lib/libc/stdlib/merge.c

cvs diff -r1.14 -r1.15 src/lib/libc/stdlib/merge.c (expand / switch to unified diff)

--- src/lib/libc/stdlib/merge.c 2012/03/13 21:13:48 1.14
+++ src/lib/libc/stdlib/merge.c 2017/08/12 01:10:04 1.15
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: merge.c,v 1.14 2012/03/13 21:13:48 christos Exp $ */ 1/* $NetBSD: merge.c,v 1.15 2017/08/12 01:10:04 ginsbach Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1992, 1993 4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Peter McIlroy. 8 * Peter McIlroy.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -27,27 +27,27 @@ @@ -27,27 +27,27 @@
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 */ 33 */
34 34
35#include <sys/cdefs.h> 35#include <sys/cdefs.h>
36#if defined(LIBC_SCCS) && !defined(lint) 36#if defined(LIBC_SCCS) && !defined(lint)
37#if 0 37#if 0
38static char sccsid[] = "from: @(#)merge.c 8.2 (Berkeley) 2/14/94"; 38static char sccsid[] = "from: @(#)merge.c 8.2 (Berkeley) 2/14/94";
39#else 39#else
40__RCSID("$NetBSD: merge.c,v 1.14 2012/03/13 21:13:48 christos Exp $"); 40__RCSID("$NetBSD: merge.c,v 1.15 2017/08/12 01:10:04 ginsbach Exp $");
41#endif 41#endif
42#endif /* LIBC_SCCS and not lint */ 42#endif /* LIBC_SCCS and not lint */
43 43
44/* 44/*
45 * Hybrid exponential search/linear search merge sort with hybrid 45 * Hybrid exponential search/linear search merge sort with hybrid
46 * natural/pairwise first pass. Requires about .3% more comparisons 46 * natural/pairwise first pass. Requires about .3% more comparisons
47 * for random data than LSMS with pairwise first pass alone. 47 * for random data than LSMS with pairwise first pass alone.
48 * It works for objects as small as two bytes. 48 * It works for objects as small as two bytes.
49 */ 49 */
50 50
51#define NATURAL 51#define NATURAL
52#define THRESHOLD 16 /* Best choice for natural merge cut-off. */ 52#define THRESHOLD 16 /* Best choice for natural merge cut-off. */
53 53
@@ -115,26 +115,29 @@ mergesort(void *base, size_t nmemb, size @@ -115,26 +115,29 @@ mergesort(void *base, size_t nmemb, size
115 int sense; 115 int sense;
116 int big, iflag; 116 int big, iflag;
117 u_char *f1, *f2, *t, *b, *tp2, *q, *l1, *l2; 117 u_char *f1, *f2, *t, *b, *tp2, *q, *l1, *l2;
118 u_char *list2, *list1, *p2, *p, *last, **p1; 118 u_char *list2, *list1, *p2, *p, *last, **p1;
119 119
120 _DIAGASSERT(base != NULL); 120 _DIAGASSERT(base != NULL);
121 _DIAGASSERT(cmp != NULL); 121 _DIAGASSERT(cmp != NULL);
122 122
123 if (size < PSIZE / 2) { /* Pointers must fit into 2 * size. */ 123 if (size < PSIZE / 2) { /* Pointers must fit into 2 * size. */
124 errno = EINVAL; 124 errno = EINVAL;
125 return (-1); 125 return (-1);
126 } 126 }
127 127
 128 if (nmemb == 0)
 129 return (0);
 130
128 /* 131 /*
129 * XXX 132 * XXX
130 * Stupid subtraction for the Cray. 133 * Stupid subtraction for the Cray.
131 */ 134 */
132 iflag = 0; 135 iflag = 0;
133 if (!(size % ISIZE) && !(((char *)base - (char *)0) % ISIZE)) 136 if (!(size % ISIZE) && !(((char *)base - (char *)0) % ISIZE))
134 iflag = 1; 137 iflag = 1;
135 138
136 if ((list2 = malloc(nmemb * size + PSIZE)) == NULL) 139 if ((list2 = malloc(nmemb * size + PSIZE)) == NULL)
137 return (-1); 140 return (-1);
138 141
139 list1 = base; 142 list1 = base;
140 setup(list1, list2, nmemb, size, cmp); 143 setup(list1, list2, nmemb, size, cmp);