(root)/
glibc-2.38/
string/
test-memcmp.c
       1  /* Test and measure memcmp 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  #ifdef TEST_MEMCMPEQ
      21  # define TEST_NAME "__memcmpeq"
      22  #elif defined WIDE
      23  # define TEST_NAME "wmemcmp"
      24  #else
      25  # define TEST_NAME "memcmp"
      26  #endif
      27  
      28  #include "test-string.h"
      29  #ifdef WIDE
      30  # include <inttypes.h>
      31  # include <wchar.h>
      32  
      33  # define MEMCMP wmemcmp
      34  # define MEMCPY wmemcpy
      35  # define SIMPLE_MEMCMP simple_wmemcmp
      36  # define CHAR wchar_t
      37  # define UCHAR wchar_t
      38  # define CHARBYTES 4
      39  # define CHAR__MIN WCHAR_MIN
      40  # define CHAR__MAX WCHAR_MAX
      41  
      42  int
      43  SIMPLE_MEMCMP (const wchar_t *s1, const wchar_t *s2, size_t n)
      44  {
      45    int ret = 0;
      46    /* Warning!
      47  	wmemcmp has to use SIGNED comparison for elements.
      48  	memcmp has to use UNSIGNED comparison for elements.
      49    */
      50    while (n-- && (ret = *s1 < *s2 ? -1 : *s1 == *s2 ? 0 : 1) == 0) {s1++; s2++;}
      51    return ret;
      52  }
      53  #else
      54  # include <limits.h>
      55  # ifdef TEST_MEMCMPEQ
      56  #  define MEMCMP __memcmpeq
      57  #  define SIMPLE_MEMCMP simple_memcmpeq
      58  # else
      59  #  define MEMCMP memcmp
      60  #  define SIMPLE_MEMCMP simple_memcmp
      61  # endif
      62  # define MEMCPY memcpy
      63  # define CHAR char
      64  # define MAX_CHAR 255
      65  # define UCHAR unsigned char
      66  # define CHARBYTES 1
      67  # define CHAR__MIN CHAR_MIN
      68  # define CHAR__MAX CHAR_MAX
      69  
      70  int
      71  SIMPLE_MEMCMP (const char *s1, const char *s2, size_t n)
      72  {
      73    int ret = 0;
      74  
      75    while (n-- && (ret = *(unsigned char *) s1++ - *(unsigned char *) s2++) == 0);
      76    return ret;
      77  }
      78  #endif
      79  
      80  #ifndef BAD_RESULT
      81  # define BAD_RESULT(result, expec)                                      \
      82      (((result) == 0 && (expec)) || ((result) < 0 && (expec) >= 0) ||    \
      83       ((result) > 0 && (expec) <= 0))
      84  # endif
      85  
      86  typedef int (*proto_t) (const CHAR *, const CHAR *, size_t);
      87  
      88  IMPL (MEMCMP, 1)
      89  
      90  static int
      91  check_result (impl_t *impl, const CHAR *s1, const CHAR *s2, size_t len,
      92  	      int exp_result)
      93  {
      94    int result = CALL (impl, s1, s2, len);
      95    if (BAD_RESULT(result, exp_result))
      96      {
      97        error (0, 0, "Wrong result in function %s %d %d", impl->name,
      98  	     result, exp_result);
      99        ret = 1;
     100        return -1;
     101      }
     102  
     103    return 0;
     104  }
     105  
     106  static void
     107  do_one_test (impl_t *impl, const CHAR *s1, const CHAR *s2, size_t len,
     108  	     int exp_result)
     109  {
     110    if (check_result (impl, s1, s2, len, exp_result) < 0)
     111      return;
     112  }
     113  
     114  static void
     115  do_test (size_t align1, size_t align2, size_t len, int exp_result)
     116  {
     117    size_t i;
     118    CHAR *s1, *s2;
     119  
     120    align1 &= (4096 - CHARBYTES);
     121    if (align1 + (len + 1) * CHARBYTES >= page_size)
     122      return;
     123  
     124    align2 &= (4096 - CHARBYTES);
     125    if (align2 + (len + 1) * CHARBYTES >= page_size)
     126      return;
     127  
     128    s1 = (CHAR *) (buf1 + align1);
     129    s2 = (CHAR *) (buf2 + align2);
     130  
     131    for (i = 0; i < len; i++)
     132      s1[i] = s2[i] = 1 + (23 << ((CHARBYTES - 1) * 8)) * i % CHAR__MAX;
     133  
     134    if (len)
     135      {
     136        s1[len] = align1;
     137        s2[len] = align2;
     138        s2[len - 1] -= exp_result;
     139      }
     140    else
     141      {
     142        exp_result = 0;
     143      }
     144  
     145    FOR_EACH_IMPL (impl, 0)
     146      do_one_test (impl, s1, s2, len, exp_result);
     147  }
     148  
     149  static void
     150  do_random_tests (void)
     151  {
     152    size_t i, j, n, align1, align2, pos, len;
     153    int result;
     154    long r;
     155    UCHAR *p1 =  (UCHAR *) (buf1 + page_size - 512 * CHARBYTES);
     156    UCHAR *p2 =  (UCHAR *) (buf2 + page_size - 512 * CHARBYTES);
     157  
     158    for (n = 0; n < ITERATIONS; n++)
     159      {
     160     align1 = random () & 31;
     161        if (random () & 1)
     162  	align2 = random () & 31;
     163        else
     164  	align2 = align1 + (random () & 24);
     165        pos = random () & 511;
     166        j = align1;
     167        if (align2 > j)
     168  	j = align2;
     169        if (pos + j >= 512)
     170  	pos = 511 - j - (random () & 7);
     171        len = random () & 511;
     172        if (len + j >= 512)
     173  	len = 511 - j - (random () & 7);
     174        j = len + align1 + 64;
     175        if (j > 512) j = 512;
     176        for (i = 0; i < j; ++i)
     177  	p1[i] = random () & 255;
     178        for (i = 0; i < j; ++i)
     179  	p2[i] = random () & 255;
     180  
     181        result = 0;
     182        if (pos >= len)
     183  	MEMCPY ((CHAR *) p2 + align2, (const CHAR *) p1 + align1, len);
     184        else
     185  	{
     186  	  MEMCPY ((CHAR *) p2 + align2, (const CHAR *) p1 + align1, pos);
     187  	  if (p2[align2 + pos] == p1[align1 + pos])
     188  	    {
     189  	      p2[align2 + pos] = random () & 255;
     190  	      if (p2[align2 + pos] == p1[align1 + pos])
     191  		p2[align2 + pos] = p1[align1 + pos] + 3 + (random () & 127);
     192  	    }
     193  
     194  	  if (p1[align1 + pos] < p2[align2 + pos])
     195  	    result = -1;
     196  	  else
     197  	    result = 1;
     198  	}
     199  
     200        FOR_EACH_IMPL (impl, 1)
     201  	{
     202  	  r = CALL (impl, (CHAR *) p1 + align1, (const CHAR *) p2 + align2,
     203  		    len);
     204  	  if (BAD_RESULT(r, result))
     205  	    {
     206  	      error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd, %zd) %ld != %d, p1 %p p2 %p",
     207  		     n, impl->name, align1 * CHARBYTES & 63,  align2 * CHARBYTES & 63, len, pos, r, result, p1, p2);
     208  	      ret = 1;
     209  	    }
     210  	}
     211      }
     212  }
     213  
     214  static void
     215  check1 (void)
     216  {
     217    CHAR s1[116], s2[116];
     218    int n, exp_result;
     219  
     220    s1[0] = -108;
     221    s2[0] = -108;
     222    s1[1] = 99;
     223    s2[1] = 99;
     224    s1[2] = -113;
     225    s2[2] = -113;
     226    s1[3] = 1;
     227    s2[3] = 1;
     228    s1[4] = 116;
     229    s2[4] = 116;
     230    s1[5] = 99;
     231    s2[5] = 99;
     232    s1[6] = -113;
     233    s2[6] = -113;
     234    s1[7] = 1;
     235    s2[7] = 1;
     236    s1[8] = 84;
     237    s2[8] = 84;
     238    s1[9] = 99;
     239    s2[9] = 99;
     240    s1[10] = -113;
     241    s2[10] = -113;
     242    s1[11] = 1;
     243    s2[11] = 1;
     244    s1[12] = 52;
     245    s2[12] = 52;
     246    s1[13] = 99;
     247    s2[13] = 99;
     248    s1[14] = -113;
     249    s2[14] = -113;
     250    s1[15] = 1;
     251    s2[15] = 1;
     252    s1[16] = -76;
     253    s2[16] = -76;
     254    s1[17] = -14;
     255    s2[17] = -14;
     256    s1[18] = -109;
     257    s2[18] = -109;
     258    s1[19] = 1;
     259    s2[19] = 1;
     260    s1[20] = -108;
     261    s2[20] = -108;
     262    s1[21] = -14;
     263    s2[21] = -14;
     264    s1[22] = -109;
     265    s2[22] = -109;
     266    s1[23] = 1;
     267    s2[23] = 1;
     268    s1[24] = 84;
     269    s2[24] = 84;
     270    s1[25] = -15;
     271    s2[25] = -15;
     272    s1[26] = -109;
     273    s2[26] = -109;
     274    s1[27] = 1;
     275    s2[27] = 1;
     276    s1[28] = 52;
     277    s2[28] = 52;
     278    s1[29] = -15;
     279    s2[29] = -15;
     280    s1[30] = -109;
     281    s2[30] = -109;
     282    s1[31] = 1;
     283    s2[31] = 1;
     284    s1[32] = 20;
     285    s2[32] = 20;
     286    s1[33] = -15;
     287    s2[33] = -15;
     288    s1[34] = -109;
     289    s2[34] = -109;
     290    s1[35] = 1;
     291    s2[35] = 1;
     292    s1[36] = 20;
     293    s2[36] = 20;
     294    s1[37] = -14;
     295    s2[37] = -14;
     296    s1[38] = -109;
     297    s2[38] = -109;
     298    s1[39] = 1;
     299    s2[39] = 1;
     300    s1[40] = 52;
     301    s2[40] = 52;
     302    s1[41] = -14;
     303    s2[41] = -14;
     304    s1[42] = -109;
     305    s2[42] = -109;
     306    s1[43] = 1;
     307    s2[43] = 1;
     308    s1[44] = 84;
     309    s2[44] = 84;
     310    s1[45] = -14;
     311    s2[45] = -14;
     312    s1[46] = -109;
     313    s2[46] = -109;
     314    s1[47] = 1;
     315    s2[47] = 1;
     316    s1[48] = 116;
     317    s2[48] = 116;
     318    s1[49] = -14;
     319    s2[49] = -14;
     320    s1[50] = -109;
     321    s2[50] = -109;
     322    s1[51] = 1;
     323    s2[51] = 1;
     324    s1[52] = 116;
     325    s2[52] = 116;
     326    s1[53] = -15;
     327    s2[53] = -15;
     328    s1[54] = -109;
     329    s2[54] = -109;
     330    s1[55] = 1;
     331    s2[55] = 1;
     332    s1[56] = -44;
     333    s2[56] = -44;
     334    s1[57] = -14;
     335    s2[57] = -14;
     336    s1[58] = -109;
     337    s2[58] = -109;
     338    s1[59] = 1;
     339    s2[59] = 1;
     340    s1[60] = -108;
     341    s2[60] = -108;
     342    s1[61] = -15;
     343    s2[61] = -15;
     344    s1[62] = -109;
     345    s2[62] = -109;
     346    s1[63] = 1;
     347    s2[63] = 1;
     348    s1[64] = -76;
     349    s2[64] = -76;
     350    s1[65] = -15;
     351    s2[65] = -15;
     352    s1[66] = -109;
     353    s2[66] = -109;
     354    s1[67] = 1;
     355    s2[67] = 1;
     356    s1[68] = -44;
     357    s2[68] = -44;
     358    s1[69] = -15;
     359    s2[69] = -15;
     360    s1[70] = -109;
     361    s2[70] = -109;
     362    s1[71] = 1;
     363    s2[71] = 1;
     364    s1[72] = -12;
     365    s2[72] = -12;
     366    s1[73] = -15;
     367    s2[73] = -15;
     368    s1[74] = -109;
     369    s2[74] = -109;
     370    s1[75] = 1;
     371    s2[75] = 1;
     372    s1[76] = -12;
     373    s2[76] = -12;
     374    s1[77] = -14;
     375    s2[77] = -14;
     376    s1[78] = -109;
     377    s2[78] = -109;
     378    s1[79] = 1;
     379    s2[79] = 1;
     380    s1[80] = 20;
     381    s2[80] = -68;
     382    s1[81] = -12;
     383    s2[81] = 64;
     384    s1[82] = -109;
     385    s2[82] = -106;
     386    s1[83] = 1;
     387    s2[83] = 1;
     388    s1[84] = -12;
     389    s2[84] = -12;
     390    s1[85] = -13;
     391    s2[85] = -13;
     392    s1[86] = -109;
     393    s2[86] = -109;
     394    s1[87] = 1;
     395    s2[87] = 1;
     396    s1[88] = -44;
     397    s2[88] = -44;
     398    s1[89] = -13;
     399    s2[89] = -13;
     400    s1[90] = -109;
     401    s2[90] = -109;
     402    s1[91] = 1;
     403    s2[91] = 1;
     404    s1[92] = -76;
     405    s2[92] = -76;
     406    s1[93] = -13;
     407    s2[93] = -13;
     408    s1[94] = -109;
     409    s2[94] = -109;
     410    s1[95] = 1;
     411    s2[95] = 1;
     412    s1[96] = -108;
     413    s2[96] = -108;
     414    s1[97] = -13;
     415    s2[97] = -13;
     416    s1[98] = -109;
     417    s2[98] = -109;
     418    s1[99] = 1;
     419    s2[99] = 1;
     420    s1[100] = 116;
     421    s2[100] = 116;
     422    s1[101] = CHAR__MIN;
     423    s2[101] = CHAR__MAX;
     424    s1[102] = -109;
     425    s2[102] = -109;
     426    s1[103] = 1;
     427    s2[103] = 1;
     428    s1[104] = 84;
     429    s2[104] = 84;
     430    s1[105] = -13;
     431    s2[105] = -13;
     432    s1[106] = -109;
     433    s2[106] = -109;
     434    s1[107] = 1;
     435    s2[107] = 1;
     436    s1[108] = 52;
     437    s2[108] = 52;
     438    s1[109] = -13;
     439    s2[109] = -13;
     440    s1[110] = -109;
     441    s2[110] = -109;
     442    s1[111] = 1;
     443    s2[111] = 1;
     444    s1[112] = CHAR__MAX;
     445    s2[112] = CHAR__MIN;
     446    s1[113] = -13;
     447    s2[113] = -13;
     448    s1[114] = -109;
     449    s2[114] = -109;
     450    s1[115] = 1;
     451    s2[115] = 1;
     452  
     453    n = 116;
     454    for (size_t i = 0; i < n; i++)
     455      for (size_t len = 0; len <= n - i; ++len)
     456        {
     457  	exp_result = SIMPLE_MEMCMP (s1 + i, s2 + i, len);
     458  	FOR_EACH_IMPL (impl, 0)
     459  	  check_result (impl, s1 + i, s2 + i, len, exp_result);
     460        }
     461  }
     462  
     463  /* This test checks that memcmp doesn't overrun buffers.  */
     464  static void
     465  check2 (void)
     466  {
     467    size_t max_length = page_size / sizeof (CHAR);
     468  
     469    /* Initialize buf2 to the same values as buf1.  The bug requires the
     470       last compared byte to be different.  */
     471    memcpy (buf2, buf1, page_size);
     472    ((char *) buf2)[page_size - 1] ^= 0x11;
     473  
     474    for (size_t length = 1; length < max_length; length++)
     475      {
     476        CHAR *s1 = (CHAR *) buf1 + max_length - length;
     477        CHAR *s2 = (CHAR *) buf2 + max_length - length;
     478  
     479        const int exp_result = SIMPLE_MEMCMP (s1, s2, length);
     480  
     481        FOR_EACH_IMPL (impl, 0)
     482  	check_result (impl, s1, s2, length, exp_result);
     483      }
     484  }
     485  
     486  int
     487  test_main (void)
     488  {
     489    size_t i;
     490  
     491    test_init ();
     492  
     493    check1 ();
     494    check2 ();
     495  
     496    printf ("%23s", "");
     497    FOR_EACH_IMPL (impl, 0)
     498      printf ("\t%s", impl->name);
     499    putchar ('\n');
     500  
     501    for (i = 1; i < 32; ++i)
     502      {
     503        do_test (i * CHARBYTES, i * CHARBYTES, i, 0);
     504        do_test (i * CHARBYTES, i * CHARBYTES, i, 1);
     505        do_test (i * CHARBYTES, i * CHARBYTES, i, -1);
     506      }
     507  
     508    for (i = 0; i < 32; ++i)
     509      {
     510        do_test (0, 0, i, 0);
     511        do_test (0, 0, i, 1);
     512        do_test (0, 0, i, -1);
     513        do_test (4096 - i, 0, i, 0);
     514        do_test (4096 - i, 0, i, 1);
     515        do_test (4096 - i, 0, i, -1);
     516        do_test (4095, 0, i, 0);
     517        do_test (4095, 0, i, 1);
     518        do_test (4095, 0, i, -1);
     519        do_test (4095, 4095, i, 0);
     520        do_test (4095, 4095, i, 1);
     521        do_test (4095, 4095, i, -1);
     522        do_test (4000, 95, i, 0);
     523        do_test (4000, 95, i, 1);
     524        do_test (4000, 95, i, -1);
     525      }
     526  
     527    for (i = 33; i < 385; i += 32)
     528      {
     529        do_test (0, 0, i, 0);
     530        do_test (0, 0, i, 1);
     531        do_test (0, 0, i, -1);
     532        do_test (i, 0, i, 0);
     533        do_test (0, i, i, 1);
     534        do_test (i, i, i, -1);
     535      }
     536  
     537    for (i = 1; i < 10; ++i)
     538      {
     539        do_test (0, 0, 2 << i, 0);
     540        do_test (0, 0, 2 << i, 1);
     541        do_test (0, 0, 2 << i, -1);
     542        do_test ((8 - i) * CHARBYTES, (2 * i) * CHARBYTES, 16 << i, 0);
     543        do_test (0, 0, 16 << i, 0);
     544        do_test (0, 0, 16 << i, 1);
     545        do_test (0, 0, 16 << i, -1);
     546        do_test (i, 0, 2 << i, 0);
     547        do_test (0, i, 2 << i, 1);
     548        do_test (i, i, 2 << i, -1);
     549        do_test (i, 0, 16 << i, 0);
     550        do_test (0, i, 16 << i, 1);
     551        do_test (i, i, 16 << i, -1);
     552      }
     553  
     554    for (i = 1; i < 10; ++i)
     555      {
     556        do_test (i * CHARBYTES, 2 * (i * CHARBYTES), 8 << i, 0);
     557        do_test (i * CHARBYTES, 2 * (i * CHARBYTES), 8 << i, 1);
     558        do_test (i * CHARBYTES, 2 * (i * CHARBYTES), 8 << i, -1);
     559      }
     560  
     561    do_random_tests ();
     562    return ret;
     563  }
     564  
     565  #include <support/test-driver.c>