(root)/
glibc-2.38/
string/
test-strncasecmp.c
       1  /* Test and measure strncasecmp 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  #include <locale.h>
      20  #include <ctype.h>
      21  
      22  #define TEST_LEN (getpagesize () * 3)
      23  #define MIN_PAGE_SIZE (TEST_LEN + 2 * getpagesize ())
      24  
      25  #define TEST_MAIN
      26  #define TEST_NAME "strncasecmp"
      27  #define TIMEOUT (5 * 60)
      28  #include "test-string.h"
      29  
      30  typedef int (*proto_t) (const char *, const char *, size_t);
      31  static int simple_strncasecmp (const char *, const char *, size_t);
      32  
      33  IMPL (strncasecmp, 1)
      34  
      35  /* Naive implementation to verify results.  */
      36  static int
      37  simple_strncasecmp (const char *s1, const char *s2, size_t n)
      38  {
      39    int ret;
      40  
      41    if (n == 0)
      42      return 0;
      43  
      44    while ((ret = ((unsigned char) tolower (*s1)
      45  		 - (unsigned char) tolower (*s2))) == 0
      46  	 && *s1++)
      47      {
      48        if (--n == 0)
      49  	return 0;
      50        ++s2;
      51      }
      52    return ret;
      53  }
      54  
      55  static int
      56  check_result (impl_t *impl, const char *s1, const char *s2, size_t n,
      57  	      int exp_result)
      58  {
      59    int result = CALL (impl, s1, s2, n);
      60    if ((exp_result == 0 && result != 0)
      61        || (exp_result < 0 && result >= 0)
      62        || (exp_result > 0 && result <= 0))
      63      {
      64        error (0, 0, "Wrong result in function %s %d %d", impl->name,
      65  	     result, exp_result);
      66        ret = 1;
      67        return -1;
      68      }
      69  
      70    return 0;
      71  }
      72  
      73  static void
      74  do_one_test (impl_t *impl, const char *s1, const char *s2, size_t n,
      75  	     int exp_result)
      76  {
      77    if (check_result (impl, s1, s2, n, exp_result) < 0)
      78      return;
      79  }
      80  
      81  static void
      82  do_test (size_t align1, size_t align2, size_t n, size_t len, int max_char,
      83  	 int exp_result)
      84  {
      85    size_t i;
      86    char *s1, *s2;
      87  
      88    if (len == 0)
      89      return;
      90  
      91    align1 &= getpagesize () - 1;
      92    if (align1 + (len + 2) >= page_size)
      93      return;
      94  
      95    align2 &= getpagesize () - 1;
      96    if (align2 + (len + 2) >= page_size)
      97      return;
      98  
      99  
     100    s1 = (char *) (buf1 + align1);
     101    s2 = (char *) (buf2 + align2);
     102  
     103    for (i = 0; i < len; i++)
     104      {
     105        s1[i] = toupper (1 + 23 * i % max_char);
     106        s2[i] = tolower (s1[i]);
     107      }
     108  
     109    s1[len] = s2[len] = 0;
     110    s1[len + 1] = 23;
     111    s2[len + 1] = 24 + exp_result;
     112  
     113    if ((s2[len - 1] == 'z' && exp_result == -1)
     114        || (s2[len - 1] == 'a' && exp_result == 1))
     115      s1[len - 1] += exp_result;
     116    else if ((s1[len - 1] == 'Z' + 1 && exp_result == 1)
     117             || (s1[len - 1] == 'A' - 1 && exp_result == -1))
     118      s1[len - 1] = tolower (s2[len - 1]) + exp_result;
     119    else
     120      s2[len - 1] -= exp_result;
     121  
     122    /* For some locals this is not guaranteed yet.  */
     123    if (tolower (s1[len - 1]) - tolower (s2[len - 1]) != exp_result)
     124      {
     125        if (exp_result == -1)
     126          {
     127            s1[len - 1] = tolower ('a');
     128            s2[len - 1] = toupper (tolower ('a') - 1);
     129          }
     130        else if (exp_result == 0)
     131          s1[len - 1] = toupper (s2[len - 1]);
     132        else
     133          {
     134            s1[len - 1] = tolower ('a');
     135            s2[len - 1] = toupper (tolower ('a') + 1);
     136          }
     137      }
     138  
     139    FOR_EACH_IMPL (impl, 0)
     140      do_one_test (impl, s1, s2, n, exp_result);
     141  }
     142  
     143  static void
     144  do_page_tests (void)
     145  {
     146    char *s1, *s2;
     147    int exp_result;
     148    const size_t maxoffset = 64;
     149  
     150    s1 = (char *) buf1 + BUF1PAGES * page_size - maxoffset;
     151    memset (s1, 'a', maxoffset - 1);
     152    s1[maxoffset - 1] = '\0';
     153  
     154    s2 = (char *) buf2 + page_size - maxoffset;
     155    memset (s2, 'a', maxoffset - 1);
     156    s2[maxoffset - 1] = '\0';
     157  
     158    /* At this point s1 and s2 point to distinct memory regions containing
     159       "aa..." with size of 63 plus '\0'.  Also, both strings are bounded to a
     160       page with read/write access and the next page is protected with PROT_NONE
     161       (meaning that any access outside of the page regions will trigger an
     162       invalid memory access).
     163  
     164       The loop checks for all possible offsets up to maxoffset for both
     165       inputs with a size larger than the string (so memory access outside
     166       the expected memory regions might trigger invalid access).  */
     167  
     168    for (size_t off1 = 0; off1 < maxoffset; off1++)
     169      {
     170        for (size_t off2 = 0; off2 < maxoffset; off2++)
     171  	{
     172  	  exp_result = (off1 == off2)
     173  			? 0
     174  			: off1 < off2
     175  			  ? 'a'
     176  			  : -'a';
     177  
     178  	  FOR_EACH_IMPL (impl, 0)
     179  	    check_result (impl, s1 + off1, s2 + off2, maxoffset + 1,
     180  			  exp_result);
     181  	}
     182      }
     183  }
     184  
     185  static void
     186  do_random_tests (void)
     187  {
     188    size_t i, j, n, align1, align2, pos, len1, len2;
     189    int result;
     190    long r;
     191    unsigned char *p1 = buf1 + page_size - 512;
     192    unsigned char *p2 = buf2 + page_size - 512;
     193  
     194    for (n = 0; n < ITERATIONS; n++)
     195      {
     196        align1 = random () & 31;
     197        if (random () & 1)
     198  	align2 = random () & 31;
     199        else
     200  	align2 = align1 + (random () & 24);
     201        pos = random () & 511;
     202        j = align1 > align2 ? align1 : align2;
     203        if (pos + j >= 511)
     204  	pos = 510 - j - (random () & 7);
     205        len1 = random () & 511;
     206        if (pos >= len1 && (random () & 1))
     207  	len1 = pos + (random () & 7);
     208        if (len1 + j >= 512)
     209  	len1 = 511 - j - (random () & 7);
     210        if (pos >= len1)
     211  	len2 = len1;
     212        else
     213  	len2 = len1 + (len1 != 511 - j ? random () % (511 - j - len1) : 0);
     214        j = (pos > len2 ? pos : len2) + align1 + 64;
     215        if (j > 512)
     216  	j = 512;
     217        for (i = 0; i < j; ++i)
     218  	{
     219  	  p1[i] = tolower (random () & 255);
     220  	  if (i < len1 + align1 && !p1[i])
     221  	    {
     222  	      p1[i] = tolower (random () & 255);
     223  	      if (!p1[i])
     224  		p1[i] = tolower (1 + (random () & 127));
     225  	    }
     226  	}
     227        for (i = 0; i < j; ++i)
     228  	{
     229  	  p2[i] = toupper (random () & 255);
     230  	  if (i < len2 + align2 && !p2[i])
     231  	    {
     232  	      p2[i] = toupper (random () & 255);
     233  	      if (!p2[i])
     234  		toupper (p2[i] = 1 + (random () & 127));
     235  	    }
     236  	}
     237  
     238        result = 0;
     239        memcpy (p2 + align2, p1 + align1, pos);
     240        if (pos < len1)
     241  	{
     242  	  if (tolower (p2[align2 + pos]) == p1[align1 + pos])
     243  	    {
     244  	      p2[align2 + pos] = toupper (random () & 255);
     245  	      if (tolower (p2[align2 + pos]) == p1[align1 + pos])
     246  		p2[align2 + pos] = toupper (p1[align1 + pos]
     247  					    + 3 + (random () & 127));
     248  	    }
     249  
     250  	  if (p1[align1 + pos] < tolower (p2[align2 + pos]))
     251  	    result = -1;
     252  	  else
     253  	    result = 1;
     254  	}
     255        p1[len1 + align1] = 0;
     256        p2[len2 + align2] = 0;
     257  
     258        FOR_EACH_IMPL (impl, 1)
     259  	{
     260  	  r = CALL (impl, (char *) (p1 + align1), (char *) (p2 + align2),
     261  		    pos + 1 + (random () & 255));
     262  	  /* Test whether on 64-bit architectures where ABI requires
     263  	     callee to promote has the promotion been done.  */
     264  	  asm ("" : "=g" (r) : "0" (r));
     265  	  if ((r == 0 && result)
     266  	      || (r < 0 && result >= 0)
     267  	      || (r > 0 && result <= 0))
     268  	    {
     269  	      error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd, %zd, %zd) %ld != %d, p1 %p p2 %p",
     270  		     n, impl->name, align1, align2, len1, len2, pos, r, result, p1, p2);
     271  	      ret = 1;
     272  	    }
     273  	}
     274      }
     275  }
     276  
     277  /* Regression test for BZ #12205 */
     278  static void
     279  bz12205 (void)
     280  {
     281    static char cp [4096+16] __attribute__ ((aligned(4096)));
     282    static char gotrel[4096] __attribute__ ((aligned(4096)));
     283    char *s1 = cp + 0xffa;
     284    char *s2 = gotrel + 0xcbe;
     285    int exp_result;
     286    size_t n = 6;
     287  
     288    strcpy (s1, "gottpoff");
     289    strcpy (s2, "GOTPLT");
     290  
     291    exp_result = simple_strncasecmp (s1, s2, n);
     292    FOR_EACH_IMPL (impl, 0)
     293      check_result (impl, s1, s2, n, exp_result);
     294  }
     295  
     296  /* Regression test for BZ #14195 */
     297  static void
     298  bz14195 (void)
     299  {
     300    const char *empty_string  = "";
     301    FOR_EACH_IMPL (impl, 0)
     302      check_result (impl, empty_string, "", 5, 0);
     303  }
     304  
     305  static void
     306  test_locale (const char *locale, int extra_tests)
     307  {
     308    size_t i, j, k;
     309    const size_t test_len = MIN(TEST_LEN, 3 * 4096);
     310    if (setlocale (LC_CTYPE, locale) == NULL)
     311      {
     312        error (0, 0, "cannot set locale \"%s\"", locale);
     313        ret = 1;
     314      }
     315  
     316    bz12205 ();
     317    bz14195 ();
     318  
     319    printf ("%23s", locale);
     320    FOR_EACH_IMPL (impl, 0)
     321      printf ("\t%s", impl->name);
     322    putchar ('\n');
     323  
     324    for (i = 1; i < 16; ++i)
     325      {
     326        do_test (i, i, i - 1, i, 127, 0);
     327  
     328        do_test (i, i, i, i, 127, 0);
     329        do_test (i, i, i, i, 127, 1);
     330        do_test (i, i, i, i, 127, -1);
     331  
     332        do_test (i, i, i + 1, i, 127, 0);
     333        do_test (i, i, i + 1, i, 127, 1);
     334        do_test (i, i, i + 1, i, 127, -1);
     335      }
     336  
     337    for (i = 1; i < 10; ++i)
     338      {
     339        do_test (0, 0, (2 << i) - 1, 2 << i, 127, 0);
     340        do_test (0, 0, 2 << i, 2 << i, 254, 0);
     341        do_test (0, 0, (2 << i) + 1, 2 << i, 127, 0);
     342  
     343        do_test (0, 0, (2 << i) + 1, 2 << i, 254, 0);
     344  
     345        do_test (0, 0, 2 << i, 2 << i, 127, 1);
     346        do_test (0, 0, (2 << i) + 10, 2 << i, 127, 1);
     347  
     348        do_test (0, 0, 2 << i, 2 << i, 254, 1);
     349        do_test (0, 0, (2 << i) + 10, 2 << i, 254, 1);
     350  
     351        do_test (0, 0, 2 << i, 2 << i, 127, -1);
     352        do_test (0, 0, (2 << i) + 10, 2 << i, 127, -1);
     353  
     354        do_test (0, 0, 2 << i, 2 << i, 254, -1);
     355        do_test (0, 0, (2 << i) + 10, 2 << i, 254, -1);
     356      }
     357  
     358    for (i = 1; i < 8; ++i)
     359      {
     360        do_test (i, 2 * i, (8 << i) - 1, 8 << i, 127, 0);
     361        do_test (i, 2 * i, 8 << i, 8 << i, 127, 0);
     362        do_test (i, 2 * i, (8 << i) + 100, 8 << i, 127, 0);
     363  
     364        do_test (2 * i, i, (8 << i) - 1, 8 << i, 254, 0);
     365        do_test (2 * i, i, 8 << i, 8 << i, 254, 0);
     366        do_test (2 * i, i, (8 << i) + 100, 8 << i, 254, 0);
     367  
     368        do_test (i, 2 * i, 8 << i, 8 << i, 127, 1);
     369        do_test (i, 2 * i, (8 << i) + 100, 8 << i, 127, 1);
     370  
     371        do_test (2 * i, i, 8 << i, 8 << i, 254, 1);
     372        do_test (2 * i, i, (8 << i) + 100, 8 << i, 254, 1);
     373  
     374        do_test (i, 2 * i, 8 << i, 8 << i, 127, -1);
     375        do_test (i, 2 * i, (8 << i) + 100, 8 << i, 127, -1);
     376  
     377        do_test (2 * i, i, 8 << i, 8 << i, 254, -1);
     378        do_test (2 * i, i, (8 << i) + 100, 8 << i, 254, -1);
     379      }
     380  
     381    for (j = 0; extra_tests && j < 160; ++j)
     382      {
     383        for (i = 0; i < test_len;)
     384          {
     385              do_test (getpagesize () - j - 1, 0, i + 1, i, 127, 0);
     386              do_test (getpagesize () - j - 1, 0, i + 1, i, 127, 1);
     387              do_test (getpagesize () - j - 1, 0, i + 1, i, 127, -1);
     388  
     389              do_test (getpagesize () - j - 1, 0, i, i, 127, 0);
     390              do_test (getpagesize () - j - 1, 0, i - 1, i, 127, 0);
     391  
     392              do_test (getpagesize () - j - 1, 0, ULONG_MAX, i, 127, 0);
     393              do_test (getpagesize () - j - 1, 0, ULONG_MAX, i, 127, 1);
     394              do_test (getpagesize () - j - 1, 0, ULONG_MAX, i, 127, -1);
     395  
     396              do_test (getpagesize () - j - 1, 0, ULONG_MAX - i, i, 127, 0);
     397              do_test (getpagesize () - j - 1, 0, ULONG_MAX - i, i, 127, 1);
     398              do_test (getpagesize () - j - 1, 0, ULONG_MAX - i, i, 127, -1);
     399  
     400              do_test (getpagesize () - j - 1, j, i + 1, i, 127, 0);
     401              do_test (getpagesize () - j - 1, j, i + 1, i, 127, 1);
     402              do_test (getpagesize () - j - 1, j, i + 1, i, 127, -1);
     403  
     404              do_test (getpagesize () - j - 1, j, i, i, 127, 0);
     405              do_test (getpagesize () - j - 1, j, i - 1, i, 127, 0);
     406  
     407              do_test (getpagesize () - j - 1, j, ULONG_MAX, i, 127, 0);
     408              do_test (getpagesize () - j - 1, j, ULONG_MAX, i, 127, 1);
     409              do_test (getpagesize () - j - 1, j, ULONG_MAX, i, 127, -1);
     410  
     411              do_test (getpagesize () - j - 1, j, ULONG_MAX - i, i, 127, 0);
     412              do_test (getpagesize () - j - 1, j, ULONG_MAX - i, i, 127, 1);
     413              do_test (getpagesize () - j - 1, j, ULONG_MAX - i, i, 127, -1);
     414  
     415              do_test (0, getpagesize () - j - 1, i + 1, i, 127, 0);
     416              do_test (0, getpagesize () - j - 1, i + 1, i, 127, 1);
     417              do_test (0, getpagesize () - j - 1, i + 1, i, 127, -1);
     418  
     419              do_test (0, getpagesize () - j - 1, i, i, 127, 0);
     420              do_test (0, getpagesize () - j - 1, i - 1, i, 127, 0);
     421  
     422              do_test (0, getpagesize () - j - 1, ULONG_MAX, i, 127, 0);
     423              do_test (0, getpagesize () - j - 1, ULONG_MAX, i, 127, 1);
     424              do_test (0, getpagesize () - j - 1, ULONG_MAX, i, 127, -1);
     425  
     426              do_test (0, getpagesize () - j - 1, ULONG_MAX - i, i, 127, 0);
     427              do_test (0, getpagesize () - j - 1, ULONG_MAX - i, i, 127, 1);
     428              do_test (0, getpagesize () - j - 1, ULONG_MAX - i, i, 127, -1);
     429  
     430              do_test (j, getpagesize () - j - 1, i + 1, i, 127, 0);
     431              do_test (j, getpagesize () - j - 1, i + 1, i, 127, 1);
     432              do_test (j, getpagesize () - j - 1, i + 1, i, 127, -1);
     433  
     434              do_test (j, getpagesize () - j - 1, i, i, 127, 0);
     435              do_test (j, getpagesize () - j - 1, i - 1, i, 127, 0);
     436  
     437              do_test (j, getpagesize () - j - 1, ULONG_MAX, i, 127, 0);
     438              do_test (j, getpagesize () - j - 1, ULONG_MAX, i, 127, 1);
     439              do_test (j, getpagesize () - j - 1, ULONG_MAX, i, 127, -1);
     440  
     441              do_test (j, getpagesize () - j - 1, ULONG_MAX - i, i, 127, 0);
     442              do_test (j, getpagesize () - j - 1, ULONG_MAX - i, i, 127, 1);
     443              do_test (j, getpagesize () - j - 1, ULONG_MAX - i, i, 127, -1);
     444  
     445            for (k = 2; k <= 128; k += k)
     446              {
     447                do_test (getpagesize () - k, getpagesize () - j - 1, i - 1, i,
     448                         127, 0);
     449                do_test (getpagesize () - k - 1, getpagesize () - j - 1, i - 1,
     450                         i, 127, 0);
     451                do_test (getpagesize () - k, getpagesize () - j - 1, i + 1, i,
     452                         127, 0);
     453                do_test (getpagesize () - k - 1, getpagesize () - j - 1, i + 1,
     454                         i, 127, 0);
     455                do_test (getpagesize () - k, getpagesize () - j - 1, i, i, 127,
     456                         0);
     457                do_test (getpagesize () - k - 1, getpagesize () - j - 1, i, i,
     458                         127, 0);
     459                do_test (getpagesize () - k, getpagesize () - j - 1, i + 1, i,
     460                         127, -1);
     461                do_test (getpagesize () - k - 1, getpagesize () - j - 1, i + 1,
     462                         i, 127, -1);
     463                do_test (getpagesize () - k, getpagesize () - j - 1, i + 1, i,
     464                         127, 1);
     465                do_test (getpagesize () - k - 1, getpagesize () - j - 1, i + 1,
     466                         i, 127, 1);
     467              }
     468            if (i < 32)
     469              {
     470                i += 1;
     471              }
     472            else if (i < 161)
     473              {
     474                i += 7;
     475              }
     476            else if (i + 161 < test_len)
     477              {
     478                i += 31;
     479                i *= 17;
     480                i /= 16;
     481                if (i + 161 > test_len)
     482                  {
     483                    i = test_len - 160;
     484                  }
     485              }
     486            else if (i + 32 < test_len)
     487              {
     488                i += 7;
     489              }
     490            else
     491              {
     492                i += 1;
     493              }
     494          }
     495      }
     496  
     497    do_random_tests ();
     498    do_page_tests ();
     499  }
     500  
     501  int
     502  test_main (void)
     503  {
     504    test_init ();
     505  
     506    test_locale ("C", 1);
     507    test_locale ("en_US.ISO-8859-1", 0);
     508    test_locale ("en_US.UTF-8", 0);
     509    test_locale ("tr_TR.ISO-8859-9", 0);
     510    test_locale ("tr_TR.UTF-8", 0);
     511  
     512    return ret;
     513  }
     514  
     515  #include <support/test-driver.c>