1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2023 Robert Clausecker
5 */
6
7 #include <sys/cdefs.h>
8
9 #include <dlfcn.h>
10 #include <limits.h>
11 #include <string.h>
12
13 #include <atf-c.h>
14
15 static void *(*memrchr_fn)(const void *, int, size_t);
16
17 ATF_TC_WITHOUT_HEAD(null);
ATF_TC_BODY(null,tc)18 ATF_TC_BODY(null, tc)
19 {
20 ATF_CHECK_EQ(memrchr_fn(NULL, 42, 0), NULL);
21 }
22
23 ATF_TC_WITHOUT_HEAD(not_found);
ATF_TC_BODY(not_found,tc)24 ATF_TC_BODY(not_found, tc)
25 {
26 size_t i, j;
27 char buf[1+15+64+1]; /* offset [0..15] + 64 buffer bytes + sentinels */
28
29 buf[0] = 'X';
30 memset(buf + 1, '-', sizeof(buf) - 1);
31
32 for (i = 0; i < 16; i++)
33 for (j = 0; j < 64; j++) {
34 buf[i + j + 1] = 'X';
35 ATF_CHECK_EQ(memrchr_fn(buf + i + 1, 'X', j), NULL);
36 buf[i + j + 1] = '-';
37 }
38 }
39
40 static void
do_found_test(char buf[],size_t len,size_t first,size_t second)41 do_found_test(char buf[], size_t len, size_t first, size_t second)
42 {
43 /* invariant: first <= second */
44
45 buf[first] = 'X';
46 buf[second] = 'X';
47 ATF_CHECK_EQ(memrchr_fn(buf, 'X', len), buf + second);
48 buf[first] = '-';
49 buf[second] = '-';
50 }
51
52 ATF_TC_WITHOUT_HEAD(found);
ATF_TC_BODY(found,tc)53 ATF_TC_BODY(found, tc)
54 {
55 size_t i, j, k, l;
56 char buf[1+15+64+1];
57
58 buf[0] = 'X';
59 memset(buf + 1, '-', sizeof(buf) - 1);
60
61 for (i = 0; i < 16; i++)
62 for (j = 0; j < 64; j++)
63 for (k = 0; k < j; k++)
64 for (l = 0; l <= k; l++) {
65 buf[i + j + 1] = 'X';
66 do_found_test(buf + i + 1, j, l, k);
67 buf[i + j + 1] = '-';
68 }
69 }
70
71 /* check that the right character is found */
72 static void
do_values_test(unsigned char buf[],size_t len,size_t i,int c)73 do_values_test(unsigned char buf[], size_t len, size_t i, int c)
74 {
75 /* sentinels */
76 buf[-1] = c;
77 buf[len] = c;
78 memset(buf, c + 1, len);
79
80 if (i < len) {
81 buf[i] = c;
82 ATF_CHECK_EQ(memrchr_fn(buf, c, len), buf + i);
83 } else
84 ATF_CHECK_EQ(memrchr_fn(buf, c, len), NULL);
85 }
86
87 ATF_TC_WITHOUT_HEAD(values);
ATF_TC_BODY(values,tc)88 ATF_TC_BODY(values, tc)
89 {
90 size_t i, j, k;
91 int c;
92 unsigned char buf[1+15+64+1];
93
94 for (i = 0; i < 16; i++)
95 for (j = 0; j < 64; j++)
96 for (k = 0; k <= j; k++)
97 for (c = 0; c <= UCHAR_MAX; c++)
98 do_values_test(buf + i + 1, j, k, c);
99 }
100
ATF_TP_ADD_TCS(tp)101 ATF_TP_ADD_TCS(tp)
102 {
103 void *dl_handle;
104
105 dl_handle = dlopen(NULL, RTLD_LAZY);
106 memrchr_fn = dlsym(dl_handle, "test_memrchr");
107 if (memrchr_fn == NULL)
108 memrchr_fn = memrchr;
109
110 ATF_TP_ADD_TC(tp, null);
111 ATF_TP_ADD_TC(tp, not_found);
112 ATF_TP_ADD_TC(tp, found);
113 ATF_TP_ADD_TC(tp, values);
114
115 return (atf_no_error());
116 }
117