Path: blob/main/lib/libc/tests/string/strrchr_test.c
283097 views
/*1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2023, 2026 Robert Clausecker <[email protected]>4*5* Adapted from memrchr_test.c.6*/78#include <sys/cdefs.h>910#include <dlfcn.h>11#include <limits.h>12#include <stdio.h>13#include <string.h>1415#include <atf-c.h>1617static char *(*strrchr_fn)(const char *, int);1819/*20* Check that when looking for the character NUL, we find the21* string terminator, and not some NUL character after it.22*/23ATF_TC_WITHOUT_HEAD(nul);24ATF_TC_BODY(nul, tc)25{26size_t i, j, k;27char buf[1+15+64]; /* offset [0+15] + 64 buffer bytes + sentinels */2829buf[0] = '\0';30memset(buf + 1, '-', sizeof(buf) - 1);3132for (i = 0; i < 16; i++)33for (j = 0; j < 64; j++)34for (k = j; k < 64; k++) {35buf[i + j + 1] = '\0';36buf[i + k + 1] = '\0';37ATF_CHECK_EQ(strrchr_fn(buf + i + 1, '\0'), buf + i + j + 1);38buf[i + j + 1] = '-';39buf[i + k + 1] = '-';40}41}4243/*44* Check that if the character 'X' does not occur in the string45* (but occurs before and after it), we correctly return NULL.46*/47ATF_TC_WITHOUT_HEAD(not_found);48ATF_TC_BODY(not_found, tc)49{50size_t i, j;51char buf[1+15+64+2]; /* offset [0..15] + 64 buffer bytes + sentinels */5253buf[0] = 'X';54memset(buf + 1, '-', sizeof(buf) - 1);5556for (i = 0; i < 16; i++)57for (j = 0; j < 64; j++) {58buf[i + j + 1] = '\0';59buf[i + j + 2] = 'X';60ATF_CHECK_EQ(strrchr_fn(buf + i + 1, 'X'), NULL);61buf[i + j + 1] = '-';62buf[i + j + 2] = '-';63}64}6566static void67do_found_test(char buf[], size_t first, size_t second)68{69/* invariant: first <= second */7071buf[first] = 'X';72buf[second] = 'X';73ATF_CHECK_EQ(strrchr_fn(buf, 'X'), buf + second);74buf[first] = '-';75buf[second] = '-';76}7778/*79* Check that if the character 'X' occurs in the string multiple80* times (i. e. twice), its last encounter is returned.81*/82ATF_TC_WITHOUT_HEAD(found);83ATF_TC_BODY(found, tc)84{85size_t i, j, k, l;86char buf[1+15+64+2];8788buf[0] = 'X';89memset(buf + 1, '-', sizeof(buf) - 1);9091for (i = 0; i < 16; i++)92for (j = 0; j < 64; j++)93for (k = 0; k < j; k++)94for (l = 0; l <= k; l++) {95buf[i + j + 1] = '\0';96buf[i + j + 2] = 'X';97do_found_test(buf + i + 1, l, k);98buf[i + j + 1] = '-';99buf[i + j + 2] = '-';100}101}102103static void104do_values_test(char buf[], size_t len, size_t i, int c)105{106/* sentinels */107buf[-1] = c;108buf[len] = '\0';109buf[len + 1] = 'c';110111/* fill the string with some other character, but not with NUL */112memset(buf, c == UCHAR_MAX ? c - 1 : c + 1, len);113114if (i < len) {115buf[i] = c;116ATF_CHECK_EQ(strrchr_fn(buf, c), buf + i);117} else118ATF_CHECK_EQ(strrchr_fn(buf, c), c == 0 ? buf + len : NULL);119}120121/*122* Check that the character is found regardless of its value.123* This catches arithmetic (overflow) errors in incorrect SWAR124* implementations of byte-parallel character matching.125*/126ATF_TC_WITHOUT_HEAD(values);127ATF_TC_BODY(values, tc)128{129size_t i, j, k;130int c;131char buf[1+15+64+2];132133for (i = 0; i < 16; i++)134for (j = 0; j < 64; j++)135for (k = 0; k <= j; k++)136for (c = 0; c <= UCHAR_MAX; c++)137do_values_test(buf + i + 1, j, k, c);138}139140ATF_TP_ADD_TCS(tp)141{142void *dl_handle;143144dl_handle = dlopen(NULL, RTLD_LAZY);145strrchr_fn = dlsym(dl_handle, "test_strrchr");146if (strrchr_fn == NULL)147strrchr_fn = strrchr;148149ATF_TP_ADD_TC(tp, nul);150ATF_TP_ADD_TC(tp, not_found);151ATF_TP_ADD_TC(tp, found);152ATF_TP_ADD_TC(tp, values);153154return (atf_no_error());155}156157158