summaryrefslogtreecommitdiff
path: root/regress/lib/libc/string/strcmp/strcmp_test.c
blob: 6c8da26dca05da3ce739496bd110263f70a5cfa6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/*
 * Written by J.T. Conklin <jtc@acorntoolworks.com>
 * Public domain.
 */

/*
 * str*() regression suite
 *
 * Trivial str*() implementations can be audited by hand.  Optimized
 * versions that unroll loops, use naturally-aligned memory acesses,
 * and "magic" arithmetic sequences to detect zero-bytes, written in
 * assembler are much harder to validate.  This program attempts to
 * catch the corner cases.
 *
 * BUGS:
 *   Misssing checks for strncpy, strncat, strncmp, etc.
 *
 * TODO:
 *   Use mmap/mprotect to ensure the functions don't access memory
 *   across page boundaries.
 *
 *   Consider generating tables programmatically.  It would reduce
 *   the size, but it's also one more thing to go wrong.
 *
 *   Share tables between strlen, strcpy, and strcat?
 *   Share tables between strchr and strrchr?
 */

#include <assert.h>
#include <string.h>

void check_strcmp(void);

void
check_strcmp(void)
{
    /* try to trick the compiler */
    int (*f)(const char *, const char *s) = strcmp;
    
    int a0;
    int a1;
    int t;
    char buf0[64];
    char buf1[64];
    int ret;

    struct tab {
	const char*	val0;
	const char*	val1;
	int		ret;
    };

    const struct tab tab[] = {
	{ "",			"",			0 },

	{ "a",			"a",			0 },
	{ "a",			"b",			-1 },
	{ "b",			"a",			+1 },
	{ "",			"a",			-1 },
	{ "a",			"",			+1 },

	{ "aa",			"aa",			0 },
	{ "aa",			"ab",			-1 },
	{ "ab",			"aa",			+1 },
	{ "a",			"aa",			-1 },
	{ "aa",			"a",			+1 },

	{ "aaa",		"aaa",			0 },
	{ "aaa",		"aab",			-1 },
	{ "aab",		"aaa",			+1 },
	{ "aa",			"aaa",			-1 },
	{ "aaa",		"aa",			+1 },

	{ "aaaa",		"aaaa",			0 },
	{ "aaaa",		"aaab",			-1 },
	{ "aaab",		"aaaa",			+1 },
	{ "aaa",		"aaaa",			-1 },
	{ "aaaa",		"aaa",			+1 },

	{ "aaaaa",		"aaaaa",		0 },
	{ "aaaaa",		"aaaab",		-1 },
	{ "aaaab",		"aaaaa",		+1 },
	{ "aaaa",		"aaaaa",		-1 },
	{ "aaaaa",		"aaaa",			+1 },

	{ "aaaaaa",		"aaaaaa",		0 },
	{ "aaaaaa",		"aaaaab",		-1 },
	{ "aaaaab",		"aaaaaa",		+1 },
	{ "aaaaa",		"aaaaaa",		-1 },
	{ "aaaaaa",		"aaaaa",		+1 },
    };

    for (a0 = 0; a0 < sizeof(long); ++a0) {
	for (a1 = 0; a1 < sizeof(long); ++a1) {
	    for (t = 0; t < (sizeof(tab) / sizeof(tab[0])); ++t) {
		memcpy(&buf0[a0], tab[t].val0, strlen(tab[t].val0) + 1);
		memcpy(&buf1[a1], tab[t].val1, strlen(tab[t].val1) + 1);

		ret = f(&buf0[a0], &buf1[a1]);

		assert ((ret == 0 && tab[t].ret == 0) ||
			(ret <  0 && tab[t].ret <  0) ||
			(ret >  0 && tab[t].ret >  0));
	    }
	}
    }
}

int
main(void)
{
	check_strcmp();
	return 0;
}