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