1 /* $NetBSD: t_memset.c,v 1.5 2024/11/02 02:43:48 riastradh Exp $ */ 2 3 /*- 4 * Copyright (c) 2011 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jukka Ruohonen. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 #include <sys/cdefs.h> 32 __RCSID("$NetBSD: t_memset.c,v 1.5 2024/11/02 02:43:48 riastradh Exp $"); 33 34 #include <sys/stat.h> 35 36 #include <atf-c.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <unistd.h> 40 41 static long page = 0; 42 static void fill(char *, size_t, char); 43 static bool check(char *, size_t, char); 44 45 int zero; /* always zero, but the compiler does not know */ 46 47 static const struct { 48 const char *name; 49 void *(*fn)(void *, int, size_t); 50 } memsetfn[] = { 51 { "memset", &memset }, 52 { "explicit_memset", &explicit_memset }, /* NetBSD extension */ 53 { "memset_explicit", &memset_explicit }, /* C23 adopted name */ 54 }; 55 56 ATF_TC(memset_array); 57 ATF_TC_HEAD(memset_array, tc) 58 { 59 atf_tc_set_md_var(tc, "descr", "Test memset(3) with arrays"); 60 } 61 62 ATF_TC_BODY(memset_array, tc) 63 { 64 char buf[1024]; 65 unsigned i; 66 67 for (i = 0; i < __arraycount(memsetfn); i++) { 68 (void)(*memsetfn[i].fn)(buf, 0, sizeof(buf)); 69 ATF_CHECK_MSG(check(buf, sizeof(buf), 0), 70 "%s did not fill a static buffer", 71 memsetfn[i].name); 72 73 (void)(*memsetfn[i].fn)(buf, 'x', sizeof(buf)); 74 ATF_CHECK_MSG(check(buf, sizeof(buf), 'x'), 75 "%s did not fill a static buffer", 76 memsetfn[i].name); 77 } 78 } 79 80 ATF_TC(memset_return); 81 ATF_TC_HEAD(memset_return, tc) 82 { 83 atf_tc_set_md_var(tc, "descr", "Test memset(3) return value"); 84 } 85 86 ATF_TC_BODY(memset_return, tc) 87 { 88 char *b = (char *)0x1; 89 char c[2]; 90 char *p; 91 unsigned i; 92 93 for (i = 0; i < __arraycount(memsetfn); i++) { 94 ATF_CHECK_EQ_MSG((p = (*memsetfn[i].fn)(b, 0, 0)), b, 95 "%s: returned %p, expected %p", memsetfn[i].name, p, b); 96 ATF_CHECK_EQ_MSG((p = (*memsetfn[i].fn)(c, 2, sizeof(c))), c, 97 "%s: returned %p, expected %p", memsetfn[i].name, p, c); 98 } 99 } 100 101 ATF_TC(memset_basic); 102 ATF_TC_HEAD(memset_basic, tc) 103 { 104 atf_tc_set_md_var(tc, "descr", "A basic test of memset(3)"); 105 } 106 107 ATF_TC_BODY(memset_basic, tc) 108 { 109 char *buf, *ret; 110 unsigned i; 111 112 buf = malloc(page); 113 ret = malloc(page); 114 115 ATF_REQUIRE(buf != NULL); 116 ATF_REQUIRE(ret != NULL); 117 118 for (i = 0; i < __arraycount(memsetfn); i++) { 119 fill(ret, page, 0); 120 (*memsetfn[i].fn)(buf, 0, page); 121 122 ATF_CHECK_EQ_MSG(memcmp(ret, buf, page), 0, "%s", 123 memsetfn[i].name); 124 125 fill(ret, page, 'x'); 126 (*memsetfn[i].fn)(buf, 'x', page); 127 128 ATF_CHECK_EQ_MSG(memcmp(ret, buf, page), 0, "%s", 129 memsetfn[i].name); 130 } 131 132 free(buf); 133 free(ret); 134 } 135 136 ATF_TC(memset_nonzero); 137 ATF_TC_HEAD(memset_nonzero, tc) 138 { 139 atf_tc_set_md_var(tc, "descr", "Test memset(3) with non-zero params"); 140 } 141 142 ATF_TC_BODY(memset_nonzero, tc) 143 { 144 const size_t n = 0x7f; 145 char *buf; 146 size_t i, j; 147 148 buf = malloc(page); 149 ATF_REQUIRE(buf != NULL); 150 151 for (i = 0x21; i < n; i++) { 152 for (j = 0; j < __arraycount(memsetfn); j++) { 153 (void)(*memsetfn[j].fn)(buf, i, page); 154 ATF_CHECK_MSG(check(buf, page, i), 155 "%s did not fill properly with %zu", 156 memsetfn[j].name, i); 157 } 158 } 159 160 free(buf); 161 } 162 163 ATF_TC(memset_zero_size); 164 165 ATF_TC_HEAD(memset_zero_size, tc) 166 { 167 atf_tc_set_md_var(tc, "descr", "Test memset(3) with zero size"); 168 } 169 170 ATF_TC_BODY(memset_zero_size, tc) 171 { 172 char buf[1024]; 173 unsigned i; 174 175 for (i = 0; i < __arraycount(memsetfn); i++) { 176 (void)(*memsetfn[i].fn)(buf, 'x', sizeof(buf)); 177 ATF_CHECK_MSG(check(buf, sizeof(buf), 'x'), 178 "%s did not fill a static buffer", 179 memsetfn[i].name); 180 181 (void)memset(buf+sizeof(buf)/2, 0, zero); 182 ATF_CHECK_MSG(check(buf, sizeof(buf), 'x'), 183 "%s with 0 size did change the buffer", 184 memsetfn[i].name); 185 } 186 } 187 188 ATF_TC(bzero_zero_size); 189 190 ATF_TC_HEAD(bzero_zero_size, tc) 191 { 192 atf_tc_set_md_var(tc, "descr", "Test bzero(3) with zero size"); 193 } 194 195 ATF_TC_BODY(bzero_zero_size, tc) 196 { 197 char buf[1024]; 198 199 (void)memset(buf, 'x', sizeof(buf)); 200 201 if (check(buf, sizeof(buf), 'x') != true) 202 atf_tc_fail("memset(3) did not fill a static buffer"); 203 204 (void)bzero(buf+sizeof(buf)/2, zero); 205 206 if (check(buf, sizeof(buf), 'x') != true) 207 atf_tc_fail("bzero(3) with 0 size did change the buffer"); 208 } 209 210 ATF_TC(memset_struct); 211 ATF_TC_HEAD(memset_struct, tc) 212 { 213 atf_tc_set_md_var(tc, "descr", "Test memset(3) with a structure"); 214 } 215 216 ATF_TC_BODY(memset_struct, tc) 217 { 218 struct stat st; 219 unsigned i; 220 221 for (i = 0; i < __arraycount(memsetfn); i++) { 222 st.st_dev = 0; 223 st.st_ino = 1; 224 st.st_mode = 2; 225 st.st_nlink = 3; 226 st.st_uid = 4; 227 st.st_gid = 5; 228 st.st_rdev = 6; 229 st.st_size = 7; 230 st.st_atime = 8; 231 st.st_mtime = 9; 232 233 (void)(*memsetfn[i].fn)(&st, 0, sizeof(struct stat)); 234 235 ATF_CHECK_MSG(st.st_dev == 0, "%s", memsetfn[i].name); 236 ATF_CHECK_MSG(st.st_ino == 0, "%s", memsetfn[i].name); 237 ATF_CHECK_MSG(st.st_mode == 0, "%s", memsetfn[i].name); 238 ATF_CHECK_MSG(st.st_nlink == 0, "%s", memsetfn[i].name); 239 ATF_CHECK_MSG(st.st_uid == 0, "%s", memsetfn[i].name); 240 ATF_CHECK_MSG(st.st_gid == 0, "%s", memsetfn[i].name); 241 ATF_CHECK_MSG(st.st_rdev == 0, "%s", memsetfn[i].name); 242 ATF_CHECK_MSG(st.st_size == 0, "%s", memsetfn[i].name); 243 ATF_CHECK_MSG(st.st_atime == 0, "%s", memsetfn[i].name); 244 ATF_CHECK_MSG(st.st_mtime == 0, "%s", memsetfn[i].name); 245 } 246 } 247 248 static void 249 fill(char *buf, size_t len, char x) 250 { 251 size_t i; 252 253 for (i = 0; i < len; i++) 254 buf[i] = x; 255 } 256 257 static bool 258 check(char *buf, size_t len, char x) 259 { 260 size_t i; 261 262 for (i = 0; i < len; i++) { 263 264 if (buf[i] != x) 265 return false; 266 } 267 268 return true; 269 } 270 271 ATF_TP_ADD_TCS(tp) 272 { 273 274 page = sysconf(_SC_PAGESIZE); 275 ATF_REQUIRE(page >= 0); 276 277 ATF_TP_ADD_TC(tp, memset_array); 278 ATF_TP_ADD_TC(tp, memset_basic); 279 ATF_TP_ADD_TC(tp, memset_nonzero); 280 ATF_TP_ADD_TC(tp, memset_struct); 281 ATF_TP_ADD_TC(tp, memset_return); 282 ATF_TP_ADD_TC(tp, memset_zero_size); 283 ATF_TP_ADD_TC(tp, bzero_zero_size); 284 285 return atf_no_error(); 286 } 287