(root)/
glibc-2.38/
string/
test-memchr.c
       1  /* Test memchr functions.
       2     Copyright (C) 1999-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  #ifndef WIDE
      21  # define TEST_NAME "memchr"
      22  #else
      23  # define TEST_NAME "wmemchr"
      24  #endif /* WIDE */
      25  
      26  #include "test-string.h"
      27  #include <stdint.h>
      28  
      29  #ifndef WIDE
      30  # define MEMCHR memchr
      31  # define CHAR char
      32  # define UCHAR unsigned char
      33  # define BIG_CHAR CHAR_MAX
      34  # define SMALL_CHAR 127
      35  #else
      36  # include <wchar.h>
      37  # define MEMCHR wmemchr
      38  # define CHAR wchar_t
      39  # define UCHAR wchar_t
      40  # define BIG_CHAR WCHAR_MAX
      41  # define SMALL_CHAR 1273
      42  #endif /* WIDE */
      43  
      44  typedef CHAR *(*proto_t) (const CHAR *, int, size_t);
      45  
      46  IMPL (MEMCHR, 1)
      47  
      48  /* Also check the generic implementation.  */
      49  #undef MEMCHR
      50  #undef weak_alias
      51  #define weak_alias(a, b)
      52  #undef libc_hidden_builtin_def
      53  #define libc_hidden_builtin_def(a)
      54  #undef libc_hidden_def
      55  #define libc_hidden_def(a)
      56  #undef libc_hidden_weak
      57  #define libc_hidden_weak(a)
      58  #ifndef WIDE
      59  # define MEMCHR __memchr_default
      60  # include "string/memchr.c"
      61  # define MEMCHR_DEFAULT MEMCHR
      62  #else
      63  # define WMEMCHR __wmemchr_default
      64  # include "wcsmbs/wmemchr.c"
      65  # define MEMCHR_DEFAULT WMEMCHR
      66  #endif
      67  IMPL (MEMCHR_DEFAULT, 1)
      68  
      69  static void
      70  do_one_test (impl_t *impl, const CHAR *s, int c, size_t n, CHAR *exp_res)
      71  {
      72    CHAR *res = CALL (impl, s, c, n);
      73    if (res != exp_res)
      74      {
      75        error (0, 0, "Wrong result in function %s (%p, %d, %zu) -> %p != %p",
      76               impl->name, s, c, n, res, exp_res);
      77        ret = 1;
      78        return;
      79      }
      80  }
      81  
      82  static void
      83  do_test (size_t align, size_t pos, size_t len, size_t n, int seek_char)
      84  {
      85    size_t i;
      86    CHAR *result;
      87  
      88    if ((align + len) * sizeof (CHAR) >= page_size)
      89      return;
      90  
      91    CHAR *buf = (CHAR *) (buf1);
      92  
      93    for (i = 0; i < len; ++i)
      94      {
      95        buf[align + i] = 1 + 23 * i % SMALL_CHAR;
      96        if (buf[align + i] == seek_char)
      97  	buf[align + i] = seek_char + 1;
      98      }
      99    buf[align + len] = 0;
     100  
     101    if (pos < MIN(n, len))
     102      {
     103        buf[align + pos] = seek_char;
     104        buf[align + len] = -seek_char;
     105        result = (CHAR *) (buf + align + pos);
     106      }
     107    else
     108      {
     109        result = NULL;
     110        buf[align + len] = seek_char;
     111      }
     112  
     113    FOR_EACH_IMPL (impl, 0)
     114      do_one_test (impl, (CHAR *) (buf + align), seek_char, n, result);
     115  }
     116  
     117  static void
     118  do_overflow_tests (void)
     119  {
     120    size_t i, j, len;
     121    const size_t one = 1;
     122    uintptr_t buf_addr = (uintptr_t) buf1;
     123  
     124    for (i = 0; i < 750; ++i)
     125      {
     126          do_test (0, i, 751, SIZE_MAX - i, BIG_CHAR);
     127          do_test (0, i, 751, i - buf_addr, BIG_CHAR);
     128          do_test (0, i, 751, -buf_addr - i, BIG_CHAR);
     129          do_test (0, i, 751, SIZE_MAX - buf_addr - i, BIG_CHAR);
     130          do_test (0, i, 751, SIZE_MAX - buf_addr + i, BIG_CHAR);
     131  
     132        len = 0;
     133        for (j = 8 * sizeof(size_t) - 1; j ; --j)
     134          {
     135            len |= one << j;
     136            do_test (0, i, 751, len - i, BIG_CHAR);
     137            do_test (0, i, 751, len + i, BIG_CHAR);
     138            do_test (0, i, 751, len - buf_addr - i, BIG_CHAR);
     139            do_test (0, i, 751, len - buf_addr + i, BIG_CHAR);
     140  
     141            do_test (0, i, 751, ~len - i, BIG_CHAR);
     142            do_test (0, i, 751, ~len + i, BIG_CHAR);
     143            do_test (0, i, 751, ~len - buf_addr - i, BIG_CHAR);
     144            do_test (0, i, 751, ~len - buf_addr + i, BIG_CHAR);
     145          }
     146      }
     147  }
     148  
     149  static void
     150  do_random_tests (void)
     151  {
     152    size_t i, j, n, align, pos, len;
     153    int seek_char;
     154    CHAR *result;
     155    UCHAR *p = (UCHAR *) (buf1 + page_size) - 512;
     156  
     157    for (n = 0; n < ITERATIONS; n++)
     158      {
     159        align = random () & 15;
     160        pos = random () & 511;
     161        if (pos + align >= 512)
     162  	pos = 511 - align - (random () & 7);
     163        len = random () & 511;
     164        if (pos >= len)
     165  	len = pos + (random () & 7);
     166        if (len + align >= 512)
     167  	len = 512 - align - (random () & 7);
     168        seek_char = random () & BIG_CHAR;
     169        j = len + align + 64;
     170        if (j > 512)
     171  	j = 512;
     172  
     173        for (i = 0; i < j; i++)
     174  	{
     175  	  if (i == pos + align)
     176  	    p[i] = seek_char;
     177  	  else
     178  	    {
     179  	      p[i] = random () & BIG_CHAR;
     180  	      if (i < pos + align && p[i] == seek_char)
     181  		p[i] = seek_char + 13;
     182  	    }
     183  	}
     184  
     185        if (pos < len)
     186  	{
     187  	  size_t r = random ();
     188  	  if ((r & 31) == 0)
     189  	    len = ~(uintptr_t) (p + align) - ((r >> 5) & 31);
     190  	  result = (CHAR *) (p + pos + align);
     191  	}
     192        else
     193  	result = NULL;
     194  
     195        FOR_EACH_IMPL (impl, 1)
     196  	if (CALL (impl, (CHAR *) (p + align), seek_char, len) != result)
     197  	  {
     198  	    error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %d, %zd, %zd) %p != %p, p %p",
     199  		   n, impl->name, align, seek_char, len, pos,
     200  		   CALL (impl, (CHAR *) (p + align), seek_char, len),
     201  		   result, p);
     202  	    ret = 1;
     203  	  }
     204      }
     205  }
     206  
     207  int
     208  test_main (void)
     209  {
     210    size_t i, j;
     211  
     212    test_init ();
     213  
     214    printf ("%20s", "");
     215    FOR_EACH_IMPL (impl, 0)
     216      printf ("\t%s", impl->name);
     217    putchar ('\n');
     218  
     219    for (i = 1; i < 8; ++i)
     220      {
     221        /* Test n == 0.  */
     222        do_test (i, i, 0, 0, 23);
     223        do_test (i, i, 0, 0, 0);
     224  
     225        do_test (0, 16 << i, 2048, 2048, 23);
     226        do_test (i, 64, 256, 256, 23);
     227        do_test (0, 16 << i, 2048, 2048, 0);
     228        do_test (i, 64, 256, 256, 0);
     229  
     230        /* Check for large input sizes and for these cases we need to
     231  	 make sure the byte is within the size range (that's why
     232  	 7 << i must be smaller than 2048).  */
     233        do_test (0, 7 << i, 2048, SIZE_MAX, 23);
     234        do_test (0, 2048 - i, 2048, SIZE_MAX, 23);
     235        do_test (i, 64, 256, SIZE_MAX, 23);
     236        do_test (0, 7 << i, 2048, SIZE_MAX, 0);
     237        do_test (0, 2048 - i, 2048, SIZE_MAX, 0);
     238        do_test (i, 64, 256, SIZE_MAX, 0);
     239      }
     240  
     241    for (i = 1; i < 64; ++i)
     242      {
     243        for (j = 1; j < 64; j++)
     244          {
     245  	  do_test (0, 64 - j, 64, SIZE_MAX, 23);
     246  	  do_test (i, 64 - j, 64, SIZE_MAX, 23);
     247          }
     248      }
     249  
     250    for (i = 1; i < 32; ++i)
     251      {
     252        do_test (0, i, i + 1, i + 1, 23);
     253        do_test (0, i, i + 1, i + 1, 0);
     254      }
     255  
     256    /* BZ#21182 - wrong overflow calculation for i686 implementation
     257       with address near end of the page.  */
     258    for (i = 2; i < 16; ++i)
     259      {
     260        /* page_size is in fact getpagesize() * 2.  */
     261        do_test (page_size / 2 - i, i, i, 1, 0x9B);
     262        do_test (page_size / 2 - i, i - 1, i - 1, 1, 0x9B);
     263        do_test (page_size / 2 - (i * 4), i + 128, i + 128, i, 0x9B);
     264      }
     265  
     266    do_random_tests ();
     267    do_overflow_tests ();
     268    return ret;
     269  }
     270  
     271  #include <support/test-driver.c>