(root)/
glibc-2.38/
string/
test-memmem.c
       1  /* Test and measure memmem functions.
       2     Copyright (C) 2008-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #define TEST_MAIN
      20  #define TEST_NAME "memmem"
      21  #define BUF1PAGES 20
      22  #define ITERATIONS 500
      23  #include "test-string.h"
      24  
      25  typedef char *(*proto_t) (const void *, size_t, const void *, size_t);
      26  
      27  IMPL (memmem, 1)
      28  
      29  /* Naive implementation to verify results.  */
      30  void *
      31  simple_memmem (const void *haystack, size_t haystack_len, const void *needle,
      32  	       size_t needle_len)
      33  {
      34    const char *begin;
      35    const char *const last_possible
      36      = (const char *) haystack + haystack_len - needle_len;
      37  
      38    if (needle_len == 0)
      39      /* The first occurrence of the empty string is deemed to occur at
      40         the beginning of the string.  */
      41      return (void *) haystack;
      42  
      43    /* Sanity check, otherwise the loop might search through the whole
      44       memory.  */
      45    if (__glibc_unlikely (haystack_len < needle_len))
      46      return NULL;
      47  
      48    for (begin = (const char *) haystack; begin <= last_possible; ++begin)
      49      if (begin[0] == ((const char *) needle)[0]
      50          && !memcmp ((const void *) &begin[1],
      51  		    (const void *) ((const char *) needle + 1),
      52  		    needle_len - 1))
      53        return (void *) begin;
      54  
      55    return NULL;
      56  }
      57  
      58  static int
      59  check_result (impl_t *impl, const void *haystack, size_t haystack_len,
      60  	     const void *needle, size_t needle_len, const void *expected)
      61  {
      62    void *res;
      63  
      64    res = CALL (impl, haystack, haystack_len, needle, needle_len);
      65    if (res != expected)
      66      {
      67        error (0, 0, "Wrong result in function %s %p %p", impl->name,
      68  	     res, expected);
      69        ret = 1;
      70        return -1;
      71      }
      72  
      73    return 0;
      74  }
      75  
      76  static void
      77  do_one_test (impl_t *impl, const void *haystack, size_t haystack_len,
      78  	     const void *needle, size_t needle_len, const void *expected)
      79  {
      80    if (check_result (impl, haystack, haystack_len, needle, needle_len,
      81  		    expected) < 0)
      82      return;
      83  }
      84  
      85  static void
      86  do_test (const char *str, size_t len, size_t idx)
      87  {
      88    char tmpbuf[len];
      89  
      90    memcpy (tmpbuf, buf1 + idx, len);
      91    memcpy (buf1 + idx, str, len);
      92  
      93    FOR_EACH_IMPL (impl, 0)
      94      do_one_test (impl, buf1, BUF1PAGES * page_size, str, len, buf1 + idx);
      95  
      96    memcpy (buf1 + idx, tmpbuf, len);
      97  }
      98  
      99  static void
     100  do_random_tests (void)
     101  {
     102    for (size_t n = 0; n < ITERATIONS; ++n)
     103      {
     104        char tmpbuf[32];
     105  
     106        size_t shift = random () % 11;
     107        size_t rel = random () % ((2 << (shift + 1)) * 64);
     108        size_t idx = MIN ((2 << shift) * 64 + rel, BUF1PAGES * page_size - 2);
     109        size_t len = random () % (sizeof (tmpbuf) - 1) + 1;
     110        len = MIN (len, BUF1PAGES * page_size - idx - 1);
     111        memcpy (tmpbuf, buf1 + idx, len);
     112        for (size_t i = random () % len / 2 + 1; i > 0; --i)
     113  	{
     114  	  size_t off = random () % len;
     115  	  char ch = '0' + random () % 10;
     116  
     117  	  buf1[idx + off] = ch;
     118  	}
     119  
     120        FOR_EACH_IMPL (impl, 0)
     121  	do_one_test (impl, buf1, BUF1PAGES * page_size, buf1 + idx, len,
     122  		     buf1 + idx);
     123  
     124        memcpy (buf1 + idx, tmpbuf, len);
     125      }
     126  }
     127  
     128  static void
     129  check1 (void)
     130  {
     131  
     132    const char search_buf_data[5] = { 0x56, 0x34, 0x12, 0x78, 0x78 };
     133    const char pattern[2] = { 0x78, 0x56 };
     134    void *search_buf = (void *) buf1 + page_size - sizeof search_buf_data;
     135    void *exp_result;
     136  
     137    memcpy (search_buf, search_buf_data, sizeof search_buf_data);
     138    exp_result = simple_memmem (search_buf, sizeof search_buf_data,
     139  			      pattern, sizeof pattern);
     140    FOR_EACH_IMPL (impl, 0)
     141      check_result (impl, search_buf, sizeof search_buf_data,
     142  		  pattern, sizeof pattern, exp_result);
     143  }
     144  
     145  static const char *const strs[] =
     146    {
     147      "00000", "00112233", "0123456789", "0000111100001111",
     148      "00000111110000022222", "012345678901234567890",
     149      "abc0", "aaaa0", "abcabc0"
     150    };
     151  
     152  
     153  int
     154  test_main (void)
     155  {
     156    size_t i;
     157  
     158    test_init ();
     159  
     160    check1 ();
     161  
     162    printf ("%23s", "");
     163    FOR_EACH_IMPL (impl, 0)
     164      printf ("\t%s", impl->name);
     165    putchar ('\n');
     166  
     167    for (i = 0; i < BUF1PAGES * page_size; ++i)
     168      buf1[i] = 60 + random () % 32;
     169  
     170    for (i = 0; i < sizeof (strs) / sizeof (strs[0]); ++i)
     171      for (size_t j = 0; j < 120; j += 7)
     172        {
     173  	size_t len = strlen (strs[i]);
     174  
     175  	do_test (strs[i], len, j);
     176        }
     177  
     178    do_random_tests ();
     179    return ret;
     180  }
     181  
     182  #include <support/test-driver.c>