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