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 #include <stdint.h> 35 #include <stdio.h> 36 #include <stdlib.h> 37 38 #define THUNK 42 39 40 #include "test-sort.h" 41 42 static errno_t e; 43 44 static int 45 sorthelp_s(const void *a, const void *b, void *thunk) 46 { 47 const int *oa, *ob; 48 49 ATF_REQUIRE_EQ(*(int *)thunk, THUNK); 50 51 oa = a; 52 ob = b; 53 /* Don't use "return *oa - *ob" since it's easy to cause overflow! */ 54 if (*oa > *ob) 55 return (1); 56 if (*oa < *ob) 57 return (-1); 58 return (0); 59 } 60 61 void 62 h(const char * restrict msg __unused, void * restrict ptr __unused, errno_t error) 63 { 64 e = error; 65 } 66 67 /* nmemb < 0 */ 68 ATF_TC_WITHOUT_HEAD(qsort_s_nmemb_lt_zero); 69 ATF_TC_BODY(qsort_s_nmemb_lt_zero, tc) 70 { 71 int thunk = THUNK; 72 int b; 73 74 ATF_CHECK(qsort_s(&b, -1, sizeof(int), sorthelp_s, &thunk) != 0); 75 } 76 77 /* nmemb > rmax */ 78 ATF_TC_WITHOUT_HEAD(qsort_s_nmemb_gt_rmax); 79 ATF_TC_BODY(qsort_s_nmemb_gt_rmax, tc) 80 { 81 int thunk = THUNK; 82 int b; 83 84 ATF_CHECK(qsort_s(&b, RSIZE_MAX + 1, sizeof(int), sorthelp_s, &thunk) != 0); 85 } 86 87 /* size < 0 */ 88 ATF_TC_WITHOUT_HEAD(qsort_s_size_lt_zero); 89 ATF_TC_BODY(qsort_s_size_lt_zero, tc) 90 { 91 int thunk = THUNK; 92 int b; 93 94 ATF_CHECK(qsort_s(&b, 1, -1, sorthelp_s, &thunk) != 0); 95 } 96 97 /* size > rmax */ 98 ATF_TC_WITHOUT_HEAD(qsort_s_size_gt_rmax); 99 ATF_TC_BODY(qsort_s_size_gt_rmax, tc) 100 { 101 int thunk = THUNK; 102 int b; 103 104 ATF_CHECK(qsort_s(&b, 1, RSIZE_MAX + 1, sorthelp_s, &thunk) != 0); 105 } 106 107 /* NULL compar */ 108 ATF_TC_WITHOUT_HEAD(qsort_s_null_compar); 109 ATF_TC_BODY(qsort_s_null_compar, tc) 110 { 111 int thunk = THUNK; 112 int b; 113 114 ATF_CHECK(qsort_s(&b, 1, sizeof(int), NULL, &thunk) != 0); 115 } 116 117 /* nmemb < 0, handler */ 118 ATF_TC_WITHOUT_HEAD(qsort_s_nmemb_lt_zero_h); 119 ATF_TC_BODY(qsort_s_nmemb_lt_zero_h, tc) 120 { 121 int thunk = THUNK; 122 int b[] = {81, 4, 7}; 123 124 e = 0; 125 set_constraint_handler_s(h); 126 ATF_CHECK(qsort_s(&b, -1, sizeof(int), sorthelp_s, &thunk) != 0); 127 ATF_CHECK(e > 0); 128 ATF_CHECK_EQ(b[0], 81); 129 ATF_CHECK_EQ(b[1], 4); 130 ATF_CHECK_EQ(b[2], 7); 131 } 132 133 /* nmemb > rmax, handler */ 134 ATF_TC_WITHOUT_HEAD(qsort_s_nmemb_gt_rmax_h); 135 ATF_TC_BODY(qsort_s_nmemb_gt_rmax_h, tc) 136 { 137 int thunk = THUNK; 138 int b[] = {81, 4, 7}; 139 140 e = 0; 141 set_constraint_handler_s(h); 142 ATF_CHECK(qsort_s(&b, RSIZE_MAX + 1, sizeof(int), sorthelp_s, &thunk) != 0); 143 ATF_CHECK(e > 0); 144 ATF_CHECK_EQ(b[0], 81); 145 ATF_CHECK_EQ(b[1], 4); 146 ATF_CHECK_EQ(b[2], 7); 147 } 148 149 /* size < 0, handler */ 150 ATF_TC_WITHOUT_HEAD(qsort_s_size_lt_zero_h); 151 ATF_TC_BODY(qsort_s_size_lt_zero_h, tc) 152 { 153 int thunk = THUNK; 154 int b[] = {81, 4, 7}; 155 156 e = 0; 157 set_constraint_handler_s(h); 158 ATF_CHECK(qsort_s(&b, nitems(b), -1, sorthelp_s, &thunk) != 0); 159 ATF_CHECK(e > 0); 160 ATF_CHECK_EQ(b[0], 81); 161 ATF_CHECK_EQ(b[1], 4); 162 ATF_CHECK_EQ(b[2], 7); 163 } 164 165 /* size > rmax, handler */ 166 ATF_TC_WITHOUT_HEAD(qsort_s_size_gt_rmax_h); 167 ATF_TC_BODY(qsort_s_size_gt_rmax_h, tc) 168 { 169 int thunk = THUNK; 170 int b[] = {81, 4, 7}; 171 172 e = 0; 173 set_constraint_handler_s(h); 174 ATF_CHECK(qsort_s(&b, nitems(b), RSIZE_MAX + 1, sorthelp_s, &thunk) != 0); 175 ATF_CHECK(e > 0); 176 ATF_CHECK_EQ(b[0], 81); 177 ATF_CHECK_EQ(b[1], 4); 178 ATF_CHECK_EQ(b[2], 7); 179 } 180 181 /* NULL compar, handler */ 182 ATF_TC_WITHOUT_HEAD(qsort_s_null_compar_h); 183 ATF_TC_BODY(qsort_s_null_compar_h, tc) 184 { 185 int thunk = THUNK; 186 int b[] = {81, 4, 7}; 187 188 e = 0; 189 set_constraint_handler_s(h); 190 ATF_CHECK(qsort_s(&b, nitems(b), sizeof(int), NULL, &thunk) != 0); 191 ATF_CHECK(e > 0); 192 ATF_CHECK_EQ(b[0], 81); 193 ATF_CHECK_EQ(b[1], 4); 194 ATF_CHECK_EQ(b[2], 7); 195 } 196 197 ATF_TC_WITHOUT_HEAD(qsort_s_h); 198 ATF_TC_BODY(qsort_s_h, tc) 199 { 200 int thunk = THUNK; 201 int b[] = {81, 4, 7}; 202 203 e = 0; 204 set_constraint_handler_s(h); 205 ATF_CHECK(qsort_s(&b, nitems(b), sizeof(int), sorthelp_s, &thunk) == 0); 206 ATF_CHECK(e == 0); 207 ATF_CHECK_EQ(b[0], 4); 208 ATF_CHECK_EQ(b[1], 7); 209 ATF_CHECK_EQ(b[2], 81); 210 } 211 212 ATF_TC_WITHOUT_HEAD(qsort_s_test); 213 ATF_TC_BODY(qsort_s_test, tc) 214 { 215 int testvector[IVEC_LEN]; 216 int sresvector[IVEC_LEN]; 217 int i, j; 218 int thunk = THUNK; 219 220 for (j = 2; j < IVEC_LEN; j++) { 221 /* Populate test vectors */ 222 for (i = 0; i < j; i++) 223 testvector[i] = sresvector[i] = initvector[i]; 224 225 /* Sort using qsort_s(3) */ 226 qsort_s(testvector, j, sizeof(testvector[0]), 227 sorthelp_s, &thunk); 228 /* Sort using reference slow sorting routine */ 229 ssort(sresvector, j); 230 231 /* Compare results */ 232 for (i = 0; i < j; i++) 233 ATF_CHECK_MSG(testvector[i] == sresvector[i], 234 "item at index %d didn't match: %d != %d", 235 i, testvector[i], sresvector[i]); 236 } 237 } 238 239 ATF_TP_ADD_TCS(tp) 240 { 241 ATF_TP_ADD_TC(tp, qsort_s_nmemb_lt_zero); 242 ATF_TP_ADD_TC(tp, qsort_s_nmemb_gt_rmax); 243 ATF_TP_ADD_TC(tp, qsort_s_size_lt_zero); 244 ATF_TP_ADD_TC(tp, qsort_s_size_gt_rmax); 245 ATF_TP_ADD_TC(tp, qsort_s_null_compar); 246 ATF_TP_ADD_TC(tp, qsort_s_nmemb_lt_zero_h); 247 ATF_TP_ADD_TC(tp, qsort_s_nmemb_gt_rmax_h); 248 ATF_TP_ADD_TC(tp, qsort_s_size_lt_zero_h); 249 ATF_TP_ADD_TC(tp, qsort_s_size_gt_rmax_h); 250 ATF_TP_ADD_TC(tp, qsort_s_null_compar_h); 251 ATF_TP_ADD_TC(tp, qsort_s_h); 252 ATF_TP_ADD_TC(tp, qsort_s_test); 253 254 return (atf_no_error()); 255 } 256