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