1 /* $NetBSD: t_strlen.c,v 1.5 2011/07/14 07:33:20 jruoho Exp $ */ 2 3 /* 4 * Written by J.T. Conklin <jtc@acorntoolworks.com> 5 * Public domain. 6 */ 7 8 #include <atf-c.h> 9 #include <string.h> 10 #include <unistd.h> 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include <dlfcn.h> 14 #include <unistd.h> 15 16 static void write_num(int); 17 18 static void 19 write_num(int val) 20 { 21 char buf[20]; 22 int i; 23 24 for (i = sizeof buf; --i >= 0;) { 25 buf[i] = '0' + val % 10; 26 val /= 10; 27 if (val == 0) { 28 write(2, buf + i, sizeof buf - i); 29 return; 30 } 31 } 32 write(2, "overflow", 8); 33 } 34 35 ATF_TC(strlen_basic); 36 ATF_TC_HEAD(strlen_basic, tc) 37 { 38 atf_tc_set_md_var(tc, "descr", "Test strlen(3) results"); 39 } 40 41 ATF_TC_BODY(strlen_basic, tc) 42 { 43 #ifdef __FreeBSD__ 44 void *dl_handle; 45 #endif 46 /* try to trick the compiler */ 47 size_t (*strlen_fn)(const char *); 48 49 unsigned int a, t; 50 size_t len; 51 char buf[64]; 52 53 struct tab { 54 const char* val; 55 size_t len; 56 }; 57 58 const struct tab tab[] = { 59 /* 60 * patterns that check for all combinations of leading and 61 * trailing unaligned characters (on a 64 bit processor) 62 */ 63 64 { "", 0 }, 65 { "a", 1 }, 66 { "ab", 2 }, 67 { "abc", 3 }, 68 { "abcd", 4 }, 69 { "abcde", 5 }, 70 { "abcdef", 6 }, 71 { "abcdefg", 7 }, 72 { "abcdefgh", 8 }, 73 { "abcdefghi", 9 }, 74 { "abcdefghij", 10 }, 75 { "abcdefghijk", 11 }, 76 { "abcdefghijkl", 12 }, 77 { "abcdefghijklm", 13 }, 78 { "abcdefghijklmn", 14 }, 79 { "abcdefghijklmno", 15 }, 80 { "abcdefghijklmnop", 16 }, 81 { "abcdefghijklmnopq", 17 }, 82 { "abcdefghijklmnopqr", 18 }, 83 { "abcdefghijklmnopqrs", 19 }, 84 { "abcdefghijklmnopqrst", 20 }, 85 { "abcdefghijklmnopqrstu", 21 }, 86 { "abcdefghijklmnopqrstuv", 22 }, 87 { "abcdefghijklmnopqrstuvw", 23 }, 88 89 /* 90 * patterns that check for the cases where the expression: 91 * 92 * ((word - 0x7f7f..7f) & 0x8080..80) 93 * 94 * returns non-zero even though there are no zero bytes in 95 * the word. 96 */ 97 98 { "" "\xff\xff\xff\xff\xff\xff\xff\xff" "abcdefgh", 16 }, 99 { "a" "\xff\xff\xff\xff\xff\xff\xff\xff" "bcdefgh", 16 }, 100 { "ab" "\xff\xff\xff\xff\xff\xff\xff\xff" "cdefgh", 16 }, 101 { "abc" "\xff\xff\xff\xff\xff\xff\xff\xff" "defgh", 16 }, 102 { "abcd" "\xff\xff\xff\xff\xff\xff\xff\xff" "efgh", 16 }, 103 { "abcde" "\xff\xff\xff\xff\xff\xff\xff\xff" "fgh", 16 }, 104 { "abcdef" "\xff\xff\xff\xff\xff\xff\xff\xff" "gh", 16 }, 105 { "abcdefg" "\xff\xff\xff\xff\xff\xff\xff\xff" "h", 16 }, 106 { "abcdefgh" "\xff\xff\xff\xff\xff\xff\xff\xff" "", 16 }, 107 }; 108 109 /* 110 * During testing it is useful have the rest of the program 111 * use a known good version! 112 */ 113 #ifdef __FreeBSD__ 114 dl_handle = dlopen(NULL, RTLD_LAZY); 115 strlen_fn = dlsym(dl_handle, "test_strlen"); 116 #else 117 strlen_fn = dlsym(dlopen(NULL, RTLD_LAZY), "test_strlen"); 118 #endif 119 if (!strlen_fn) 120 strlen_fn = strlen; 121 122 for (a = 0; a < sizeof(long); ++a) { 123 for (t = 0; t < (sizeof(tab) / sizeof(tab[0])); ++t) { 124 125 memcpy(&buf[a], tab[t].val, tab[t].len + 1); 126 len = strlen_fn(&buf[a]); 127 128 if (len != tab[t].len) { 129 /* Write error without using printf / strlen */ 130 write(2, "alignment ", 10); 131 write_num(a); 132 write(2, ", test ", 7); 133 write_num(t); 134 write(2, ", got len ", 10); 135 write_num(len); 136 write(2, ", not ", 6); 137 write_num(tab[t].len); 138 write(2, ", for '", 7); 139 write(2, tab[t].val, tab[t].len); 140 write(2, "'\n", 2); 141 atf_tc_fail("See stderr for details"); 142 } 143 } 144 } 145 #ifdef __FreeBSD__ 146 (void)dlclose(dl_handle); 147 #endif 148 } 149 150 ATF_TC(strlen_huge); 151 ATF_TC_HEAD(strlen_huge, tc) 152 { 153 atf_tc_set_md_var(tc, "descr", "Test strlen(3) with huge strings"); 154 } 155 156 ATF_TC_BODY(strlen_huge, tc) 157 { 158 long page; 159 char *str; 160 size_t i; 161 162 page = sysconf(_SC_PAGESIZE); 163 ATF_REQUIRE(page >= 0); 164 165 for (i = 1; i < 1000; i = i + 100) { 166 167 str = malloc(i * page + 1); 168 169 if (str == NULL) 170 continue; 171 172 (void)memset(str, 'x', i * page); 173 str[i * page] = '\0'; 174 175 ATF_REQUIRE(strlen(str) == i * page); 176 free(str); 177 } 178 } 179 180 ATF_TC(strnlen_basic); 181 ATF_TC_HEAD(strnlen_basic, tc) 182 { 183 atf_tc_set_md_var(tc, "descr", "A naive test of strnlen(3)"); 184 } 185 186 ATF_TC_BODY(strnlen_basic, tc) 187 { 188 char buf[1]; 189 190 buf[0] = '\0'; 191 192 ATF_CHECK(strnlen(buf, 000) == 0); 193 ATF_CHECK(strnlen(buf, 111) == 0); 194 195 ATF_CHECK(strnlen("xxx", 0) == 0); 196 ATF_CHECK(strnlen("xxx", 1) == 1); 197 ATF_CHECK(strnlen("xxx", 2) == 2); 198 ATF_CHECK(strnlen("xxx", 3) == 3); 199 ATF_CHECK(strnlen("xxx", 9) == 3); 200 } 201 202 ATF_TP_ADD_TCS(tp) 203 { 204 205 ATF_TP_ADD_TC(tp, strlen_basic); 206 ATF_TP_ADD_TC(tp, strlen_huge); 207 ATF_TP_ADD_TC(tp, strnlen_basic); 208 209 return atf_no_error(); 210 } 211