xref: /freebsd/lib/libc/tests/string/strnlen_test.c (revision b64c5a0ace59af62eff52bfe110a521dc73c937b)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2024 Strahinja Stanisic <strajabot@FreeBSD.org>
5  */
6 
7 #include <string.h>
8 #include <unistd.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <stdalign.h>
12 #include <stdint.h>
13 
14 #include <atf-c.h>
15 
16 ATF_TC(strnlen_alignments);
17 ATF_TC_HEAD(strnlen_alignments, tc)
18 {
19     atf_tc_set_md_var(tc, "descr", "Test strnlen(3) with different alignments");
20 }
21 
22 ATF_TC_BODY(strnlen_alignments, tc)
23 {
24 	size_t (*strnlen_fn)(const char*, size_t) = strnlen;
25 	char alignas(16) buffer[1 + 16 + 64 + 1 + 1];
26 
27 	memset(buffer, '/', sizeof(buffer));
28 
29 	for (int align = 1; align < 1 + 16; align++) {
30 		char *s = buffer + align;
31 
32 		for (size_t maxlen = 0; maxlen <= 64; maxlen++) {
33 			for (size_t len = 0; len <= maxlen; len++) {
34 				/* returns length */
35 
36 				/* without sentinels */
37 				s[len] = '\0';
38 				size_t val = strnlen_fn(s, maxlen);
39 				if (val != len) {
40 					fprintf(stderr, "align =  %d, maxlen = %zu, len = %zu",
41 					    align, maxlen, len);
42 					atf_tc_fail("returned incorrect len");
43 				}
44 
45 				/* with sentinels */
46 				s[-1] = '\0';
47 				s[maxlen + 1] = '\0';
48 				val = strnlen_fn(s, maxlen);
49 				if (val != len) {
50 					fprintf(stderr, "align =  %d, maxlen = %zu, len = %zu",
51 					    align, maxlen, len);
52 					atf_tc_fail("returned incorrect len (sentinels)");
53 				}
54 
55 				/* cleanup */
56 				s[-1] = '/';
57 				s[len] = '/';
58 				s[maxlen + 1] = '/';
59 
60 			}
61 
62 			/* returns maxlen */
63 
64 			/* without sentinels */
65 			size_t val = strnlen_fn(s, maxlen);
66 			if (val != maxlen) {
67 				fprintf(stderr, "align =  %d, maxlen = %zu",
68 				     align, maxlen);
69 				atf_tc_fail("should return maxlen");
70 			}
71 
72 			/* with sentinels */
73 			s[-1] = '\0';
74 			s[maxlen + 1] = '\0';
75 			val = strnlen_fn(s, maxlen);
76 			if (val != maxlen) {
77 				fprintf(stderr, "align =  %d, maxlen = %zu",
78 				    align, maxlen);
79 				atf_tc_fail("should return maxlen (sentinels)");
80 			}
81 
82 			/* cleanup */
83 			s[-1] = '/';
84 			s[maxlen + 1] = '/';
85 		}
86 	}
87 }
88 
89 ATF_TC(strnlen_size_max);
90 ATF_TC_HEAD(strnlen_size_max, tc)
91 {
92     atf_tc_set_md_var(tc, "descr", "Test strnlen(3) with maxlen=SIZE_MAX");
93 }
94 
95 ATF_TC_BODY(strnlen_size_max, tc)
96 {
97 	size_t (*strnlen_fn)(const char*, size_t) = strnlen;
98 	char alignas(16) buffer[1 + 16 + 64 + 1 + 1];
99 
100 	memset(buffer, '/', sizeof(buffer));
101 
102 	for (int align = 1; align < 1 + 16; align++) {
103 		char* s = buffer + align;
104 
105 		for (size_t len = 0; len <= 64; len++) {
106 			/* returns length */
107 
108 			/* without sentinels */
109 			s[len] = '\0';
110 			size_t val = strnlen_fn(s, SIZE_MAX);
111 			if (val != len) {
112 				fprintf(stderr, "align =  %d, maxlen = %zu, len = %zu",
113 				    align, SIZE_MAX, len);
114 				atf_tc_fail("returned incorrect len (SIZE_MAX)");
115 			}
116 
117 			/* with sentinels */
118 			s[-1] = '\0';
119 			val = strnlen_fn(s, SIZE_MAX);
120 			if (val != len) {
121 				fprintf(stderr, "align =  %d, maxlen = %zu, len = %zu",
122 				    align, SIZE_MAX, len);
123 				atf_tc_fail("returned incorrect len (sentinels) (SIZE_MAX)");
124 			}
125 
126 			/* cleanup */
127 			s[-1] = '/';
128 			s[len] = '/';
129 		}
130 	}
131 }
132 
133 
134 
135 ATF_TP_ADD_TCS(tp)
136 {
137 	ATF_TP_ADD_TC(tp, strnlen_alignments);
138 	ATF_TP_ADD_TC(tp, strnlen_size_max);
139 
140 	return atf_no_error();
141 }
142