157718be8SEnji Cooper /* $NetBSD: t_strlen.c,v 1.6 2017/01/14 20:49:24 christos Exp $ */
257718be8SEnji Cooper 
357718be8SEnji Cooper /*
457718be8SEnji Cooper  * Written by J.T. Conklin <jtc@acorntoolworks.com>
557718be8SEnji Cooper  * Public domain.
657718be8SEnji Cooper  */
757718be8SEnji Cooper 
857718be8SEnji Cooper #include <atf-c.h>
957718be8SEnji Cooper #include <string.h>
1057718be8SEnji Cooper #include <unistd.h>
1157718be8SEnji Cooper #include <stdio.h>
1257718be8SEnji Cooper #include <stdlib.h>
1357718be8SEnji Cooper #include <dlfcn.h>
1457718be8SEnji Cooper #include <unistd.h>
1557718be8SEnji Cooper 
1657718be8SEnji Cooper static void	write_num(int);
1757718be8SEnji Cooper 
1857718be8SEnji Cooper static void
write_num(int val)1957718be8SEnji Cooper write_num(int val)
2057718be8SEnji Cooper {
2157718be8SEnji Cooper 	char buf[20];
2257718be8SEnji Cooper 	int i;
2357718be8SEnji Cooper 
2457718be8SEnji Cooper 	for (i = sizeof buf; --i >= 0;) {
2557718be8SEnji Cooper 		buf[i] = '0' + val % 10;
2657718be8SEnji Cooper 		val /= 10;
2757718be8SEnji Cooper 		if (val == 0) {
2857718be8SEnji Cooper 			write(2, buf + i, sizeof buf - i);
2957718be8SEnji Cooper 			return;
3057718be8SEnji Cooper 		}
3157718be8SEnji Cooper 	}
3257718be8SEnji Cooper 	write(2, "overflow", 8);
3357718be8SEnji Cooper }
3457718be8SEnji Cooper 
3557718be8SEnji Cooper ATF_TC(strlen_basic);
ATF_TC_HEAD(strlen_basic,tc)3657718be8SEnji Cooper ATF_TC_HEAD(strlen_basic, tc)
3757718be8SEnji Cooper {
3857718be8SEnji Cooper         atf_tc_set_md_var(tc, "descr", "Test strlen(3) results");
3957718be8SEnji Cooper }
4057718be8SEnji Cooper 
ATF_TC_BODY(strlen_basic,tc)4157718be8SEnji Cooper ATF_TC_BODY(strlen_basic, tc)
4257718be8SEnji Cooper {
4383e8b13fSEnji Cooper 	void *dl_handle;
4483e8b13fSEnji Cooper 	/* try to trick the compiler */
4583e8b13fSEnji Cooper 	size_t (*strlen_fn)(const char *);
4657718be8SEnji Cooper 
4757718be8SEnji Cooper 	unsigned int a, t;
4857718be8SEnji Cooper 	size_t len;
4957718be8SEnji Cooper 	char buf[64];
5057718be8SEnji Cooper 
5157718be8SEnji Cooper 	struct tab {
5257718be8SEnji Cooper 		const char*	val;
5357718be8SEnji Cooper 		size_t		len;
5457718be8SEnji Cooper 	};
5557718be8SEnji Cooper 
5657718be8SEnji Cooper 	const struct tab tab[] = {
5757718be8SEnji Cooper 		/*
5857718be8SEnji Cooper 		 * patterns that check for all combinations of leading and
5957718be8SEnji Cooper 		 * trailing unaligned characters (on a 64 bit processor)
6057718be8SEnji Cooper 		 */
6157718be8SEnji Cooper 
6257718be8SEnji Cooper 		{ "",				0 },
6357718be8SEnji Cooper 		{ "a",				1 },
6457718be8SEnji Cooper 		{ "ab",				2 },
6557718be8SEnji Cooper 		{ "abc",			3 },
6657718be8SEnji Cooper 		{ "abcd",			4 },
6757718be8SEnji Cooper 		{ "abcde",			5 },
6857718be8SEnji Cooper 		{ "abcdef",			6 },
6957718be8SEnji Cooper 		{ "abcdefg",			7 },
7057718be8SEnji Cooper 		{ "abcdefgh",			8 },
7157718be8SEnji Cooper 		{ "abcdefghi",			9 },
7257718be8SEnji Cooper 		{ "abcdefghij",			10 },
7357718be8SEnji Cooper 		{ "abcdefghijk",		11 },
7457718be8SEnji Cooper 		{ "abcdefghijkl",		12 },
7557718be8SEnji Cooper 		{ "abcdefghijklm",		13 },
7657718be8SEnji Cooper 		{ "abcdefghijklmn",		14 },
7757718be8SEnji Cooper 		{ "abcdefghijklmno",		15 },
7857718be8SEnji Cooper 		{ "abcdefghijklmnop",		16 },
7957718be8SEnji Cooper 		{ "abcdefghijklmnopq",		17 },
8057718be8SEnji Cooper 		{ "abcdefghijklmnopqr",		18 },
8157718be8SEnji Cooper 		{ "abcdefghijklmnopqrs",	19 },
8257718be8SEnji Cooper 		{ "abcdefghijklmnopqrst",	20 },
8357718be8SEnji Cooper 		{ "abcdefghijklmnopqrstu",	21 },
8457718be8SEnji Cooper 		{ "abcdefghijklmnopqrstuv",	22 },
8557718be8SEnji Cooper 		{ "abcdefghijklmnopqrstuvw",	23 },
8657718be8SEnji Cooper 
8757718be8SEnji Cooper 		/*
8857718be8SEnji Cooper 		 * patterns that check for the cases where the expression:
8957718be8SEnji Cooper 		 *
9057718be8SEnji Cooper 		 *	((word - 0x7f7f..7f) & 0x8080..80)
9157718be8SEnji Cooper 		 *
9257718be8SEnji Cooper 		 * returns non-zero even though there are no zero bytes in
9357718be8SEnji Cooper 		 * the word.
9457718be8SEnji Cooper 		 */
9557718be8SEnji Cooper 
9657718be8SEnji Cooper 		{ "" "\xff\xff\xff\xff\xff\xff\xff\xff" "abcdefgh",	16 },
9757718be8SEnji Cooper 		{ "a" "\xff\xff\xff\xff\xff\xff\xff\xff" "bcdefgh",	16 },
9857718be8SEnji Cooper 		{ "ab" "\xff\xff\xff\xff\xff\xff\xff\xff" "cdefgh",	16 },
9957718be8SEnji Cooper 		{ "abc" "\xff\xff\xff\xff\xff\xff\xff\xff" "defgh",	16 },
10057718be8SEnji Cooper 		{ "abcd" "\xff\xff\xff\xff\xff\xff\xff\xff" "efgh",	16 },
10157718be8SEnji Cooper 		{ "abcde" "\xff\xff\xff\xff\xff\xff\xff\xff" "fgh",	16 },
10257718be8SEnji Cooper 		{ "abcdef" "\xff\xff\xff\xff\xff\xff\xff\xff" "gh",	16 },
10357718be8SEnji Cooper 		{ "abcdefg" "\xff\xff\xff\xff\xff\xff\xff\xff" "h",	16 },
10457718be8SEnji Cooper 		{ "abcdefgh" "\xff\xff\xff\xff\xff\xff\xff\xff" "",	16 },
10557718be8SEnji Cooper 	};
10657718be8SEnji Cooper 
10757718be8SEnji Cooper 	/*
10857718be8SEnji Cooper 	 * During testing it is useful have the rest of the program
10957718be8SEnji Cooper 	 * use a known good version!
11057718be8SEnji Cooper 	 */
11157718be8SEnji Cooper 	dl_handle = dlopen(NULL, RTLD_LAZY);
11257718be8SEnji Cooper 	strlen_fn = dlsym(dl_handle, "test_strlen");
11383e8b13fSEnji Cooper 	if (!strlen_fn)
11483e8b13fSEnji Cooper 		strlen_fn = strlen;
11583e8b13fSEnji Cooper 
11683e8b13fSEnji Cooper 	for (a = 0; a < sizeof(long); ++a) {
11757718be8SEnji Cooper 		for (t = 0; t < (sizeof(tab) / sizeof(tab[0])); ++t) {
11883e8b13fSEnji Cooper 
11957718be8SEnji Cooper 			memcpy(&buf[a], tab[t].val, tab[t].len + 1);
12057718be8SEnji Cooper 			len = strlen_fn(&buf[a]);
12157718be8SEnji Cooper 
12257718be8SEnji Cooper 			if (len != tab[t].len) {
12357718be8SEnji Cooper 				/* Write error without using printf / strlen */
12457718be8SEnji Cooper 				write(2, "alignment ", 10);
12557718be8SEnji Cooper 				write_num(a);
12657718be8SEnji Cooper 				write(2, ", test ", 7);
12757718be8SEnji Cooper 				write_num(t);
12857718be8SEnji Cooper 				write(2, ", got len ", 10);
12957718be8SEnji Cooper 				write_num(len);
13057718be8SEnji Cooper 				write(2, ", not ", 6);
13157718be8SEnji Cooper 				write_num(tab[t].len);
13257718be8SEnji Cooper 				write(2, ", for '", 7);
13357718be8SEnji Cooper 				write(2, tab[t].val, tab[t].len);
13457718be8SEnji Cooper 				write(2, "'\n", 2);
13557718be8SEnji Cooper 				atf_tc_fail("See stderr for details");
13657718be8SEnji Cooper 			}
13757718be8SEnji Cooper 		}
13857718be8SEnji Cooper 	}
13957718be8SEnji Cooper 	(void)dlclose(dl_handle);
14057718be8SEnji Cooper }
14157718be8SEnji Cooper 
14257718be8SEnji Cooper ATF_TC(strlen_huge);
ATF_TC_HEAD(strlen_huge,tc)14357718be8SEnji Cooper ATF_TC_HEAD(strlen_huge, tc)
14457718be8SEnji Cooper {
14583e8b13fSEnji Cooper         atf_tc_set_md_var(tc, "descr", "Test strlen(3) with huge strings");
14683e8b13fSEnji Cooper }
14783e8b13fSEnji Cooper 
ATF_TC_BODY(strlen_huge,tc)14857718be8SEnji Cooper ATF_TC_BODY(strlen_huge, tc)
14957718be8SEnji Cooper {
15057718be8SEnji Cooper 	long page;
15157718be8SEnji Cooper 	char *str;
15257718be8SEnji Cooper 	size_t i;
15357718be8SEnji Cooper 
15457718be8SEnji Cooper 	page = sysconf(_SC_PAGESIZE);
15557718be8SEnji Cooper 	ATF_REQUIRE(page >= 0);
15657718be8SEnji Cooper 
15757718be8SEnji Cooper 	for (i = 1; i < 1000; i = i + 100) {
15857718be8SEnji Cooper 
15957718be8SEnji Cooper 		str = malloc(i * page + 1);
16057718be8SEnji Cooper 
16157718be8SEnji Cooper 		if (str == NULL)
16257718be8SEnji Cooper 			continue;
16357718be8SEnji Cooper 
16457718be8SEnji Cooper 		(void)memset(str, 'x', i * page);
16557718be8SEnji Cooper 		str[i * page] = '\0';
16657718be8SEnji Cooper 
16757718be8SEnji Cooper 		ATF_REQUIRE(strlen(str) == i * page);
16857718be8SEnji Cooper 		free(str);
16957718be8SEnji Cooper 	}
17057718be8SEnji Cooper }
17157718be8SEnji Cooper 
17257718be8SEnji Cooper ATF_TC(strnlen_basic);
ATF_TC_HEAD(strnlen_basic,tc)17357718be8SEnji Cooper ATF_TC_HEAD(strnlen_basic, tc)
17457718be8SEnji Cooper {
17557718be8SEnji Cooper         atf_tc_set_md_var(tc, "descr", "A naive test of strnlen(3)");
17657718be8SEnji Cooper }
17757718be8SEnji Cooper 
ATF_TC_BODY(strnlen_basic,tc)17857718be8SEnji Cooper ATF_TC_BODY(strnlen_basic, tc)
17957718be8SEnji Cooper {
18057718be8SEnji Cooper 	char buf[1];
18157718be8SEnji Cooper 
18257718be8SEnji Cooper 	buf[0] = '\0';
18357718be8SEnji Cooper 
18457718be8SEnji Cooper 	ATF_CHECK(strnlen(buf, 000) == 0);
18557718be8SEnji Cooper 	ATF_CHECK(strnlen(buf, 111) == 0);
18657718be8SEnji Cooper 
18757718be8SEnji Cooper 	ATF_CHECK(strnlen("xxx", 0) == 0);
18857718be8SEnji Cooper 	ATF_CHECK(strnlen("xxx", 1) == 1);
18957718be8SEnji Cooper 	ATF_CHECK(strnlen("xxx", 2) == 2);
19057718be8SEnji Cooper 	ATF_CHECK(strnlen("xxx", 3) == 3);
19157718be8SEnji Cooper 	ATF_CHECK(strnlen("xxx", 9) == 3);
19257718be8SEnji Cooper }
19357718be8SEnji Cooper 
ATF_TP_ADD_TCS(tp)19457718be8SEnji Cooper ATF_TP_ADD_TCS(tp)
19557718be8SEnji Cooper {
19657718be8SEnji Cooper 
19757718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, strlen_basic);
19857718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, strlen_huge);
19957718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, strnlen_basic);
20057718be8SEnji Cooper 
20157718be8SEnji Cooper 	return atf_no_error();
20257718be8SEnji Cooper }
20357718be8SEnji Cooper