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