1*cd517fb0Schristos /* $NetBSD: t_strlen.c,v 1.6 2017/01/14 20:49:24 christos Exp $ */
254bb1074Sjruoho
354bb1074Sjruoho /*
454bb1074Sjruoho * Written by J.T. Conklin <jtc@acorntoolworks.com>
554bb1074Sjruoho * Public domain.
654bb1074Sjruoho */
754bb1074Sjruoho
854bb1074Sjruoho #include <atf-c.h>
954bb1074Sjruoho #include <string.h>
1054bb1074Sjruoho #include <unistd.h>
1154bb1074Sjruoho #include <stdio.h>
1254bb1074Sjruoho #include <stdlib.h>
1354bb1074Sjruoho #include <dlfcn.h>
14b34acef4Sjruoho #include <unistd.h>
1554bb1074Sjruoho
1654bb1074Sjruoho static void write_num(int);
1754bb1074Sjruoho
1854bb1074Sjruoho static void
write_num(int val)1954bb1074Sjruoho write_num(int val)
2054bb1074Sjruoho {
2154bb1074Sjruoho char buf[20];
2254bb1074Sjruoho int i;
2354bb1074Sjruoho
2454bb1074Sjruoho for (i = sizeof buf; --i >= 0;) {
2554bb1074Sjruoho buf[i] = '0' + val % 10;
2654bb1074Sjruoho val /= 10;
2754bb1074Sjruoho if (val == 0) {
2854bb1074Sjruoho write(2, buf + i, sizeof buf - i);
2954bb1074Sjruoho return;
3054bb1074Sjruoho }
3154bb1074Sjruoho }
3254bb1074Sjruoho write(2, "overflow", 8);
3354bb1074Sjruoho }
3454bb1074Sjruoho
3554bb1074Sjruoho ATF_TC(strlen_basic);
ATF_TC_HEAD(strlen_basic,tc)3654bb1074Sjruoho ATF_TC_HEAD(strlen_basic, tc)
3754bb1074Sjruoho {
3854bb1074Sjruoho atf_tc_set_md_var(tc, "descr", "Test strlen(3) results");
3954bb1074Sjruoho }
4054bb1074Sjruoho
ATF_TC_BODY(strlen_basic,tc)4154bb1074Sjruoho ATF_TC_BODY(strlen_basic, tc)
4254bb1074Sjruoho {
43*cd517fb0Schristos void *dl_handle;
4454bb1074Sjruoho /* try to trick the compiler */
4554bb1074Sjruoho size_t (*strlen_fn)(const char *);
4654bb1074Sjruoho
4754bb1074Sjruoho unsigned int a, t;
4854bb1074Sjruoho size_t len;
4954bb1074Sjruoho char buf[64];
5054bb1074Sjruoho
5154bb1074Sjruoho struct tab {
5254bb1074Sjruoho const char* val;
5354bb1074Sjruoho size_t len;
5454bb1074Sjruoho };
5554bb1074Sjruoho
5654bb1074Sjruoho const struct tab tab[] = {
5754bb1074Sjruoho /*
5854bb1074Sjruoho * patterns that check for all combinations of leading and
5954bb1074Sjruoho * trailing unaligned characters (on a 64 bit processor)
6054bb1074Sjruoho */
6154bb1074Sjruoho
6254bb1074Sjruoho { "", 0 },
6354bb1074Sjruoho { "a", 1 },
6454bb1074Sjruoho { "ab", 2 },
6554bb1074Sjruoho { "abc", 3 },
6654bb1074Sjruoho { "abcd", 4 },
6754bb1074Sjruoho { "abcde", 5 },
6854bb1074Sjruoho { "abcdef", 6 },
6954bb1074Sjruoho { "abcdefg", 7 },
7054bb1074Sjruoho { "abcdefgh", 8 },
7154bb1074Sjruoho { "abcdefghi", 9 },
7254bb1074Sjruoho { "abcdefghij", 10 },
7354bb1074Sjruoho { "abcdefghijk", 11 },
7454bb1074Sjruoho { "abcdefghijkl", 12 },
7554bb1074Sjruoho { "abcdefghijklm", 13 },
7654bb1074Sjruoho { "abcdefghijklmn", 14 },
7754bb1074Sjruoho { "abcdefghijklmno", 15 },
7854bb1074Sjruoho { "abcdefghijklmnop", 16 },
7954bb1074Sjruoho { "abcdefghijklmnopq", 17 },
8054bb1074Sjruoho { "abcdefghijklmnopqr", 18 },
8154bb1074Sjruoho { "abcdefghijklmnopqrs", 19 },
8254bb1074Sjruoho { "abcdefghijklmnopqrst", 20 },
8354bb1074Sjruoho { "abcdefghijklmnopqrstu", 21 },
8454bb1074Sjruoho { "abcdefghijklmnopqrstuv", 22 },
8554bb1074Sjruoho { "abcdefghijklmnopqrstuvw", 23 },
8654bb1074Sjruoho
8754bb1074Sjruoho /*
8854bb1074Sjruoho * patterns that check for the cases where the expression:
8954bb1074Sjruoho *
9054bb1074Sjruoho * ((word - 0x7f7f..7f) & 0x8080..80)
9154bb1074Sjruoho *
9254bb1074Sjruoho * returns non-zero even though there are no zero bytes in
9354bb1074Sjruoho * the word.
9454bb1074Sjruoho */
9554bb1074Sjruoho
9654bb1074Sjruoho { "" "\xff\xff\xff\xff\xff\xff\xff\xff" "abcdefgh", 16 },
9754bb1074Sjruoho { "a" "\xff\xff\xff\xff\xff\xff\xff\xff" "bcdefgh", 16 },
9854bb1074Sjruoho { "ab" "\xff\xff\xff\xff\xff\xff\xff\xff" "cdefgh", 16 },
9954bb1074Sjruoho { "abc" "\xff\xff\xff\xff\xff\xff\xff\xff" "defgh", 16 },
10054bb1074Sjruoho { "abcd" "\xff\xff\xff\xff\xff\xff\xff\xff" "efgh", 16 },
10154bb1074Sjruoho { "abcde" "\xff\xff\xff\xff\xff\xff\xff\xff" "fgh", 16 },
10254bb1074Sjruoho { "abcdef" "\xff\xff\xff\xff\xff\xff\xff\xff" "gh", 16 },
10354bb1074Sjruoho { "abcdefg" "\xff\xff\xff\xff\xff\xff\xff\xff" "h", 16 },
10454bb1074Sjruoho { "abcdefgh" "\xff\xff\xff\xff\xff\xff\xff\xff" "", 16 },
10554bb1074Sjruoho };
10654bb1074Sjruoho
10754bb1074Sjruoho /*
10854bb1074Sjruoho * During testing it is useful have the rest of the program
10954bb1074Sjruoho * use a known good version!
11054bb1074Sjruoho */
111*cd517fb0Schristos dl_handle = dlopen(NULL, RTLD_LAZY);
112*cd517fb0Schristos strlen_fn = dlsym(dl_handle, "test_strlen");
11354bb1074Sjruoho if (!strlen_fn)
11454bb1074Sjruoho strlen_fn = strlen;
11554bb1074Sjruoho
11654bb1074Sjruoho for (a = 0; a < sizeof(long); ++a) {
11754bb1074Sjruoho for (t = 0; t < (sizeof(tab) / sizeof(tab[0])); ++t) {
11854bb1074Sjruoho
11954bb1074Sjruoho memcpy(&buf[a], tab[t].val, tab[t].len + 1);
12054bb1074Sjruoho len = strlen_fn(&buf[a]);
12154bb1074Sjruoho
12254bb1074Sjruoho if (len != tab[t].len) {
12354bb1074Sjruoho /* Write error without using printf / strlen */
12454bb1074Sjruoho write(2, "alignment ", 10);
12554bb1074Sjruoho write_num(a);
12654bb1074Sjruoho write(2, ", test ", 7);
12754bb1074Sjruoho write_num(t);
12854bb1074Sjruoho write(2, ", got len ", 10);
12954bb1074Sjruoho write_num(len);
13054bb1074Sjruoho write(2, ", not ", 6);
13154bb1074Sjruoho write_num(tab[t].len);
13254bb1074Sjruoho write(2, ", for '", 7);
13354bb1074Sjruoho write(2, tab[t].val, tab[t].len);
13454bb1074Sjruoho write(2, "'\n", 2);
13554bb1074Sjruoho atf_tc_fail("See stderr for details");
13654bb1074Sjruoho }
13754bb1074Sjruoho }
13854bb1074Sjruoho }
139*cd517fb0Schristos (void)dlclose(dl_handle);
14054bb1074Sjruoho }
14154bb1074Sjruoho
142b34acef4Sjruoho ATF_TC(strlen_huge);
ATF_TC_HEAD(strlen_huge,tc)143b34acef4Sjruoho ATF_TC_HEAD(strlen_huge, tc)
144b34acef4Sjruoho {
145b34acef4Sjruoho atf_tc_set_md_var(tc, "descr", "Test strlen(3) with huge strings");
146b34acef4Sjruoho }
147b34acef4Sjruoho
ATF_TC_BODY(strlen_huge,tc)148b34acef4Sjruoho ATF_TC_BODY(strlen_huge, tc)
149b34acef4Sjruoho {
150b34acef4Sjruoho long page;
151b34acef4Sjruoho char *str;
152b34acef4Sjruoho size_t i;
153b34acef4Sjruoho
154b34acef4Sjruoho page = sysconf(_SC_PAGESIZE);
155b34acef4Sjruoho ATF_REQUIRE(page >= 0);
156b34acef4Sjruoho
157b34acef4Sjruoho for (i = 1; i < 1000; i = i + 100) {
158b34acef4Sjruoho
159b34acef4Sjruoho str = malloc(i * page + 1);
160b34acef4Sjruoho
161b34acef4Sjruoho if (str == NULL)
162b34acef4Sjruoho continue;
163b34acef4Sjruoho
164b34acef4Sjruoho (void)memset(str, 'x', i * page);
165247e3a69Snjoly str[i * page] = '\0';
166b34acef4Sjruoho
167b34acef4Sjruoho ATF_REQUIRE(strlen(str) == i * page);
168b34acef4Sjruoho free(str);
169b34acef4Sjruoho }
170b34acef4Sjruoho }
171b34acef4Sjruoho
1722b91d03eSjruoho ATF_TC(strnlen_basic);
ATF_TC_HEAD(strnlen_basic,tc)1732b91d03eSjruoho ATF_TC_HEAD(strnlen_basic, tc)
1742b91d03eSjruoho {
1752b91d03eSjruoho atf_tc_set_md_var(tc, "descr", "A naive test of strnlen(3)");
1762b91d03eSjruoho }
1772b91d03eSjruoho
ATF_TC_BODY(strnlen_basic,tc)1782b91d03eSjruoho ATF_TC_BODY(strnlen_basic, tc)
1792b91d03eSjruoho {
1802b91d03eSjruoho char buf[1];
1812b91d03eSjruoho
1822b91d03eSjruoho buf[0] = '\0';
1832b91d03eSjruoho
18499db6ea6Sjruoho ATF_CHECK(strnlen(buf, 000) == 0);
18599db6ea6Sjruoho ATF_CHECK(strnlen(buf, 111) == 0);
1862b91d03eSjruoho
18799db6ea6Sjruoho ATF_CHECK(strnlen("xxx", 0) == 0);
18899db6ea6Sjruoho ATF_CHECK(strnlen("xxx", 1) == 1);
18999db6ea6Sjruoho ATF_CHECK(strnlen("xxx", 2) == 2);
19099db6ea6Sjruoho ATF_CHECK(strnlen("xxx", 3) == 3);
19199db6ea6Sjruoho ATF_CHECK(strnlen("xxx", 9) == 3);
1922b91d03eSjruoho }
1932b91d03eSjruoho
ATF_TP_ADD_TCS(tp)19454bb1074Sjruoho ATF_TP_ADD_TCS(tp)
19554bb1074Sjruoho {
19654bb1074Sjruoho
19754bb1074Sjruoho ATF_TP_ADD_TC(tp, strlen_basic);
198b34acef4Sjruoho ATF_TP_ADD_TC(tp, strlen_huge);
1992b91d03eSjruoho ATF_TP_ADD_TC(tp, strnlen_basic);
20054bb1074Sjruoho
20154bb1074Sjruoho return atf_no_error();
20254bb1074Sjruoho }
203