1 /*- 2 * Copyright (C) 2020 Edward Tomasz Napierala <trasz@FreeBSD.org> 3 * Copyright (c) 2017 Juniper Networks. All rights reserved. 4 * Copyright (C) 2004 Maxim Sobolev <sobomax@FreeBSD.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 /* 30 * Test for qsort_s(3) routine. 31 */ 32 33 #include <sys/cdefs.h> 34 __FBSDID("$FreeBSD$"); 35 36 #include <stdint.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 40 #define THUNK 42 41 42 #include "test-sort.h" 43 44 static errno_t e; 45 46 static int 47 sorthelp_s(const void *a, const void *b, void *thunk) 48 { 49 const int *oa, *ob; 50 51 ATF_REQUIRE_EQ(*(int *)thunk, THUNK); 52 53 oa = a; 54 ob = b; 55 /* Don't use "return *oa - *ob" since it's easy to cause overflow! */ 56 if (*oa > *ob) 57 return (1); 58 if (*oa < *ob) 59 return (-1); 60 return (0); 61 } 62 63 void 64 h(const char * restrict msg __unused, void * restrict ptr __unused, errno_t error) 65 { 66 e = error; 67 } 68 69 /* nmemb < 0 */ 70 ATF_TC_WITHOUT_HEAD(qsort_s_nmemb_lt_zero); 71 ATF_TC_BODY(qsort_s_nmemb_lt_zero, tc) 72 { 73 int thunk = THUNK; 74 int b; 75 76 ATF_CHECK(qsort_s(&b, -1, sizeof(int), sorthelp_s, &thunk) != 0); 77 } 78 79 /* nmemb > rmax */ 80 ATF_TC_WITHOUT_HEAD(qsort_s_nmemb_gt_rmax); 81 ATF_TC_BODY(qsort_s_nmemb_gt_rmax, tc) 82 { 83 int thunk = THUNK; 84 int b; 85 86 ATF_CHECK(qsort_s(&b, RSIZE_MAX + 1, sizeof(int), sorthelp_s, &thunk) != 0); 87 } 88 89 /* size < 0 */ 90 ATF_TC_WITHOUT_HEAD(qsort_s_size_lt_zero); 91 ATF_TC_BODY(qsort_s_size_lt_zero, tc) 92 { 93 int thunk = THUNK; 94 int b; 95 96 ATF_CHECK(qsort_s(&b, 1, -1, sorthelp_s, &thunk) != 0); 97 } 98 99 /* size > rmax */ 100 ATF_TC_WITHOUT_HEAD(qsort_s_size_gt_rmax); 101 ATF_TC_BODY(qsort_s_size_gt_rmax, tc) 102 { 103 int thunk = THUNK; 104 int b; 105 106 ATF_CHECK(qsort_s(&b, 1, RSIZE_MAX + 1, sorthelp_s, &thunk) != 0); 107 } 108 109 /* NULL compar */ 110 ATF_TC_WITHOUT_HEAD(qsort_s_null_compar); 111 ATF_TC_BODY(qsort_s_null_compar, tc) 112 { 113 int thunk = THUNK; 114 int b; 115 116 ATF_CHECK(qsort_s(&b, 1, sizeof(int), NULL, &thunk) != 0); 117 } 118 119 /* nmemb < 0, handler */ 120 ATF_TC_WITHOUT_HEAD(qsort_s_nmemb_lt_zero_h); 121 ATF_TC_BODY(qsort_s_nmemb_lt_zero_h, tc) 122 { 123 int thunk = THUNK; 124 int b[] = {81, 4, 7}; 125 126 e = 0; 127 set_constraint_handler_s(h); 128 ATF_CHECK(qsort_s(&b, -1, sizeof(int), sorthelp_s, &thunk) != 0); 129 ATF_CHECK(e > 0); 130 ATF_CHECK_EQ(b[0], 81); 131 ATF_CHECK_EQ(b[1], 4); 132 ATF_CHECK_EQ(b[2], 7); 133 } 134 135 /* nmemb > rmax, handler */ 136 ATF_TC_WITHOUT_HEAD(qsort_s_nmemb_gt_rmax_h); 137 ATF_TC_BODY(qsort_s_nmemb_gt_rmax_h, tc) 138 { 139 int thunk = THUNK; 140 int b[] = {81, 4, 7}; 141 142 e = 0; 143 set_constraint_handler_s(h); 144 ATF_CHECK(qsort_s(&b, RSIZE_MAX + 1, sizeof(int), sorthelp_s, &thunk) != 0); 145 ATF_CHECK(e > 0); 146 ATF_CHECK_EQ(b[0], 81); 147 ATF_CHECK_EQ(b[1], 4); 148 ATF_CHECK_EQ(b[2], 7); 149 } 150 151 /* size < 0, handler */ 152 ATF_TC_WITHOUT_HEAD(qsort_s_size_lt_zero_h); 153 ATF_TC_BODY(qsort_s_size_lt_zero_h, tc) 154 { 155 int thunk = THUNK; 156 int b[] = {81, 4, 7}; 157 158 e = 0; 159 set_constraint_handler_s(h); 160 ATF_CHECK(qsort_s(&b, nitems(b), -1, sorthelp_s, &thunk) != 0); 161 ATF_CHECK(e > 0); 162 ATF_CHECK_EQ(b[0], 81); 163 ATF_CHECK_EQ(b[1], 4); 164 ATF_CHECK_EQ(b[2], 7); 165 } 166 167 /* size > rmax, handler */ 168 ATF_TC_WITHOUT_HEAD(qsort_s_size_gt_rmax_h); 169 ATF_TC_BODY(qsort_s_size_gt_rmax_h, tc) 170 { 171 int thunk = THUNK; 172 int b[] = {81, 4, 7}; 173 174 e = 0; 175 set_constraint_handler_s(h); 176 ATF_CHECK(qsort_s(&b, nitems(b), RSIZE_MAX + 1, sorthelp_s, &thunk) != 0); 177 ATF_CHECK(e > 0); 178 ATF_CHECK_EQ(b[0], 81); 179 ATF_CHECK_EQ(b[1], 4); 180 ATF_CHECK_EQ(b[2], 7); 181 } 182 183 /* NULL compar, handler */ 184 ATF_TC_WITHOUT_HEAD(qsort_s_null_compar_h); 185 ATF_TC_BODY(qsort_s_null_compar_h, tc) 186 { 187 int thunk = THUNK; 188 int b[] = {81, 4, 7}; 189 190 e = 0; 191 set_constraint_handler_s(h); 192 ATF_CHECK(qsort_s(&b, nitems(b), sizeof(int), NULL, &thunk) != 0); 193 ATF_CHECK(e > 0); 194 ATF_CHECK_EQ(b[0], 81); 195 ATF_CHECK_EQ(b[1], 4); 196 ATF_CHECK_EQ(b[2], 7); 197 } 198 199 ATF_TC_WITHOUT_HEAD(qsort_s_h); 200 ATF_TC_BODY(qsort_s_h, tc) 201 { 202 int thunk = THUNK; 203 int b[] = {81, 4, 7}; 204 205 e = 0; 206 set_constraint_handler_s(h); 207 ATF_CHECK(qsort_s(&b, nitems(b), sizeof(int), sorthelp_s, &thunk) == 0); 208 ATF_CHECK(e == 0); 209 ATF_CHECK_EQ(b[0], 4); 210 ATF_CHECK_EQ(b[1], 7); 211 ATF_CHECK_EQ(b[2], 81); 212 } 213 214 ATF_TC_WITHOUT_HEAD(qsort_s_test); 215 ATF_TC_BODY(qsort_s_test, tc) 216 { 217 int testvector[IVEC_LEN]; 218 int sresvector[IVEC_LEN]; 219 int i, j; 220 int thunk = THUNK; 221 222 for (j = 2; j < IVEC_LEN; j++) { 223 /* Populate test vectors */ 224 for (i = 0; i < j; i++) 225 testvector[i] = sresvector[i] = initvector[i]; 226 227 /* Sort using qsort_s(3) */ 228 qsort_s(testvector, j, sizeof(testvector[0]), 229 sorthelp_s, &thunk); 230 /* Sort using reference slow sorting routine */ 231 ssort(sresvector, j); 232 233 /* Compare results */ 234 for (i = 0; i < j; i++) 235 ATF_CHECK_MSG(testvector[i] == sresvector[i], 236 "item at index %d didn't match: %d != %d", 237 i, testvector[i], sresvector[i]); 238 } 239 } 240 241 ATF_TP_ADD_TCS(tp) 242 { 243 ATF_TP_ADD_TC(tp, qsort_s_nmemb_lt_zero); 244 ATF_TP_ADD_TC(tp, qsort_s_nmemb_gt_rmax); 245 ATF_TP_ADD_TC(tp, qsort_s_size_lt_zero); 246 ATF_TP_ADD_TC(tp, qsort_s_size_gt_rmax); 247 ATF_TP_ADD_TC(tp, qsort_s_null_compar); 248 ATF_TP_ADD_TC(tp, qsort_s_nmemb_lt_zero_h); 249 ATF_TP_ADD_TC(tp, qsort_s_nmemb_gt_rmax_h); 250 ATF_TP_ADD_TC(tp, qsort_s_size_lt_zero_h); 251 ATF_TP_ADD_TC(tp, qsort_s_size_gt_rmax_h); 252 ATF_TP_ADD_TC(tp, qsort_s_null_compar_h); 253 ATF_TP_ADD_TC(tp, qsort_s_h); 254 ATF_TP_ADD_TC(tp, qsort_s_test); 255 256 return (atf_no_error()); 257 } 258