200 lines
4.2 KiB
C
200 lines
4.2 KiB
C
|
/* $NetBSD: t_strlen.c,v 1.5 2011/07/14 07:33:20 jruoho Exp $ */
|
||
|
|
||
|
/*
|
||
|
* Written by J.T. Conklin <jtc@acorntoolworks.com>
|
||
|
* Public domain.
|
||
|
*/
|
||
|
|
||
|
#include <atf-c.h>
|
||
|
#include <string.h>
|
||
|
#include <unistd.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <dlfcn.h>
|
||
|
#include <unistd.h>
|
||
|
|
||
|
static void write_num(int);
|
||
|
|
||
|
static void
|
||
|
write_num(int val)
|
||
|
{
|
||
|
char buf[20];
|
||
|
int i;
|
||
|
|
||
|
for (i = sizeof buf; --i >= 0;) {
|
||
|
buf[i] = '0' + val % 10;
|
||
|
val /= 10;
|
||
|
if (val == 0) {
|
||
|
write(2, buf + i, sizeof buf - i);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
write(2, "overflow", 8);
|
||
|
}
|
||
|
|
||
|
ATF_TC(strlen_basic);
|
||
|
ATF_TC_HEAD(strlen_basic, tc)
|
||
|
{
|
||
|
atf_tc_set_md_var(tc, "descr", "Test strlen(3) results");
|
||
|
}
|
||
|
|
||
|
ATF_TC_BODY(strlen_basic, tc)
|
||
|
{
|
||
|
/* try to trick the compiler */
|
||
|
size_t (*strlen_fn)(const char *);
|
||
|
|
||
|
unsigned int a, t;
|
||
|
size_t len;
|
||
|
char buf[64];
|
||
|
|
||
|
struct tab {
|
||
|
const char* val;
|
||
|
size_t len;
|
||
|
};
|
||
|
|
||
|
const struct tab tab[] = {
|
||
|
/*
|
||
|
* patterns that check for all combinations of leading and
|
||
|
* trailing unaligned characters (on a 64 bit processor)
|
||
|
*/
|
||
|
|
||
|
{ "", 0 },
|
||
|
{ "a", 1 },
|
||
|
{ "ab", 2 },
|
||
|
{ "abc", 3 },
|
||
|
{ "abcd", 4 },
|
||
|
{ "abcde", 5 },
|
||
|
{ "abcdef", 6 },
|
||
|
{ "abcdefg", 7 },
|
||
|
{ "abcdefgh", 8 },
|
||
|
{ "abcdefghi", 9 },
|
||
|
{ "abcdefghij", 10 },
|
||
|
{ "abcdefghijk", 11 },
|
||
|
{ "abcdefghijkl", 12 },
|
||
|
{ "abcdefghijklm", 13 },
|
||
|
{ "abcdefghijklmn", 14 },
|
||
|
{ "abcdefghijklmno", 15 },
|
||
|
{ "abcdefghijklmnop", 16 },
|
||
|
{ "abcdefghijklmnopq", 17 },
|
||
|
{ "abcdefghijklmnopqr", 18 },
|
||
|
{ "abcdefghijklmnopqrs", 19 },
|
||
|
{ "abcdefghijklmnopqrst", 20 },
|
||
|
{ "abcdefghijklmnopqrstu", 21 },
|
||
|
{ "abcdefghijklmnopqrstuv", 22 },
|
||
|
{ "abcdefghijklmnopqrstuvw", 23 },
|
||
|
|
||
|
/*
|
||
|
* patterns that check for the cases where the expression:
|
||
|
*
|
||
|
* ((word - 0x7f7f..7f) & 0x8080..80)
|
||
|
*
|
||
|
* returns non-zero even though there are no zero bytes in
|
||
|
* the word.
|
||
|
*/
|
||
|
|
||
|
{ "" "\xff\xff\xff\xff\xff\xff\xff\xff" "abcdefgh", 16 },
|
||
|
{ "a" "\xff\xff\xff\xff\xff\xff\xff\xff" "bcdefgh", 16 },
|
||
|
{ "ab" "\xff\xff\xff\xff\xff\xff\xff\xff" "cdefgh", 16 },
|
||
|
{ "abc" "\xff\xff\xff\xff\xff\xff\xff\xff" "defgh", 16 },
|
||
|
{ "abcd" "\xff\xff\xff\xff\xff\xff\xff\xff" "efgh", 16 },
|
||
|
{ "abcde" "\xff\xff\xff\xff\xff\xff\xff\xff" "fgh", 16 },
|
||
|
{ "abcdef" "\xff\xff\xff\xff\xff\xff\xff\xff" "gh", 16 },
|
||
|
{ "abcdefg" "\xff\xff\xff\xff\xff\xff\xff\xff" "h", 16 },
|
||
|
{ "abcdefgh" "\xff\xff\xff\xff\xff\xff\xff\xff" "", 16 },
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
* During testing it is useful have the rest of the program
|
||
|
* use a known good version!
|
||
|
*/
|
||
|
strlen_fn = dlsym(dlopen(NULL, RTLD_LAZY), "test_strlen");
|
||
|
if (!strlen_fn)
|
||
|
strlen_fn = strlen;
|
||
|
|
||
|
for (a = 0; a < sizeof(long); ++a) {
|
||
|
for (t = 0; t < (sizeof(tab) / sizeof(tab[0])); ++t) {
|
||
|
|
||
|
memcpy(&buf[a], tab[t].val, tab[t].len + 1);
|
||
|
len = strlen_fn(&buf[a]);
|
||
|
|
||
|
if (len != tab[t].len) {
|
||
|
/* Write error without using printf / strlen */
|
||
|
write(2, "alignment ", 10);
|
||
|
write_num(a);
|
||
|
write(2, ", test ", 7);
|
||
|
write_num(t);
|
||
|
write(2, ", got len ", 10);
|
||
|
write_num(len);
|
||
|
write(2, ", not ", 6);
|
||
|
write_num(tab[t].len);
|
||
|
write(2, ", for '", 7);
|
||
|
write(2, tab[t].val, tab[t].len);
|
||
|
write(2, "'\n", 2);
|
||
|
atf_tc_fail("See stderr for details");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ATF_TC(strlen_huge);
|
||
|
ATF_TC_HEAD(strlen_huge, tc)
|
||
|
{
|
||
|
atf_tc_set_md_var(tc, "descr", "Test strlen(3) with huge strings");
|
||
|
}
|
||
|
|
||
|
ATF_TC_BODY(strlen_huge, tc)
|
||
|
{
|
||
|
long page;
|
||
|
char *str;
|
||
|
size_t i;
|
||
|
|
||
|
page = sysconf(_SC_PAGESIZE);
|
||
|
ATF_REQUIRE(page >= 0);
|
||
|
|
||
|
for (i = 1; i < 1000; i = i + 100) {
|
||
|
|
||
|
str = malloc(i * page + 1);
|
||
|
|
||
|
if (str == NULL)
|
||
|
continue;
|
||
|
|
||
|
(void)memset(str, 'x', i * page);
|
||
|
str[i * page] = '\0';
|
||
|
|
||
|
ATF_REQUIRE(strlen(str) == i * page);
|
||
|
free(str);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ATF_TC(strnlen_basic);
|
||
|
ATF_TC_HEAD(strnlen_basic, tc)
|
||
|
{
|
||
|
atf_tc_set_md_var(tc, "descr", "A naive test of strnlen(3)");
|
||
|
}
|
||
|
|
||
|
ATF_TC_BODY(strnlen_basic, tc)
|
||
|
{
|
||
|
char buf[1];
|
||
|
|
||
|
buf[0] = '\0';
|
||
|
|
||
|
ATF_CHECK(strnlen(buf, 000) == 0);
|
||
|
ATF_CHECK(strnlen(buf, 111) == 0);
|
||
|
|
||
|
ATF_CHECK(strnlen("xxx", 0) == 0);
|
||
|
ATF_CHECK(strnlen("xxx", 1) == 1);
|
||
|
ATF_CHECK(strnlen("xxx", 2) == 2);
|
||
|
ATF_CHECK(strnlen("xxx", 3) == 3);
|
||
|
ATF_CHECK(strnlen("xxx", 9) == 3);
|
||
|
}
|
||
|
|
||
|
ATF_TP_ADD_TCS(tp)
|
||
|
{
|
||
|
|
||
|
ATF_TP_ADD_TC(tp, strlen_basic);
|
||
|
ATF_TP_ADD_TC(tp, strlen_huge);
|
||
|
ATF_TP_ADD_TC(tp, strnlen_basic);
|
||
|
|
||
|
return atf_no_error();
|
||
|
}
|