]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - string/tester.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / string / tester.c
index 5f0a85110411059a807f22a94841653f972ebc6a..7c36591d8d362bc0819b984340c72a7a5e3b4921 100644 (file)
@@ -1,5 +1,5 @@
 /* Tester for string functions.
-   Copyright (C) 1995-2000, 2001, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1995-2016 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -13,9 +13,8 @@
    Lesser General Public License for more details.
 
    You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
 
 #ifndef _GNU_SOURCE
 #define _GNU_SOURCE
 #include <string.h>
 #include <strings.h>
 #include <fcntl.h>
+#include <libc-internal.h>
 
-#ifndef HAVE_GNU_LD
-#define _sys_nerr      sys_nerr
-#define _sys_errlist   sys_errlist
-#endif
 
 #define        STREQ(a, b)     (strcmp((a), (b)) == 0)
 
@@ -50,7 +46,7 @@ check (int thing, int number)
 {
   if (!thing)
     {
-      printf("%s flunked test %d\n", it, number);
+      printf ("%s flunked test %d\n", it, number);
       ++errors;
     }
 }
@@ -59,7 +55,7 @@ check (int thing, int number)
 static void
 equal (const char *a, const char *b, int number)
 {
-  check(a != NULL && b != NULL && STREQ (a, b), number);
+  check (a != NULL && b != NULL && STREQ (a, b), number);
 }
 
 char one[50];
@@ -306,6 +302,48 @@ test_strcat (void)
   (void) strcpy (one, "");
   (void) strcat (one, "cd");
   equal (one, "cd", 9);
+
+  int ntest = 10;
+  char buf1[80] __attribute__ ((aligned (16)));
+  char buf2[32] __attribute__ ((aligned (16)));
+  for (size_t n1 = 0; n1 < 16; ++n1)
+    for (size_t n2 = 0; n2 < 16; ++n2)
+      for (size_t n3 = 0; n3 < 32; ++n3)
+       {
+         size_t olderrors = errors;
+
+         memset (buf1, 'b', sizeof (buf1));
+
+         memset (buf1 + n2, 'a', n3);
+         buf1[n2 + n3] = '\0';
+         strcpy (buf2 + n1, "123");
+
+         check (strcat (buf1 + n2, buf2 + n1) == buf1 + n2, ntest);
+         if (errors == olderrors)
+           for (size_t i = 0; i < sizeof (buf1); ++i)
+             {
+               if (i < n2)
+                 check (buf1[i] == 'b', ntest);
+               else if (i < n2 + n3)
+                 check (buf1[i] == 'a', ntest);
+               else if (i < n2 + n3 + 3)
+                 check (buf1[i] == "123"[i - (n2 + n3)], ntest);
+               else if (i == n2 + n3 + 3)
+                 check (buf1[i] == '\0', ntest);
+               else
+                 check (buf1[i] == 'b', ntest);
+
+               if (errors != olderrors)
+                 {
+                   printf ("n1=%zu, n2=%zu, n3=%zu, buf1=%02hhx",
+                           n1, n2, n3, buf1[0]);
+                   for (size_t j = 1; j < sizeof (buf1); ++j)
+                     printf (",%02hhx", buf1[j]);
+                   putchar_unlocked ('\n');
+                   break;
+                 }
+             }
+       }
 }
 
 static void
@@ -348,6 +386,53 @@ test_strncat (void)
 
   (void) strncat (one, "gh", 2);
   equal (one, "abcdgh", 12);           /* Count and length equal. */
+
+  (void) strncat (one, "ij", (size_t)-1);      /* set sign bit in count */
+  equal (one, "abcdghij", 13);
+
+  int ntest = 14;
+  char buf1[80] __attribute__ ((aligned (16)));
+  char buf2[32] __attribute__ ((aligned (16)));
+  for (size_t n1 = 0; n1 < 16; ++n1)
+    for (size_t n2 = 0; n2 < 16; ++n2)
+      for (size_t n3 = 0; n3 < 32; ++n3)
+       for (size_t n4 = 0; n4 < 16; ++n4)
+         {
+           size_t olderrors = errors;
+
+           memset (buf1, 'b', sizeof (buf1));
+
+           memset (buf1 + n2, 'a', n3);
+           buf1[n2 + n3] = '\0';
+           strcpy (buf2 + n1, "123");
+
+           check (strncat (buf1 + n2, buf2 + n1, ~((size_t) 0) - n4)
+                  == buf1 + n2, ntest);
+           if (errors == olderrors)
+             for (size_t i = 0; i < sizeof (buf1); ++i)
+               {
+                 if (i < n2)
+                   check (buf1[i] == 'b', ntest);
+                 else if (i < n2 + n3)
+                   check (buf1[i] == 'a', ntest);
+                 else if (i < n2 + n3 + 3)
+                   check (buf1[i] == "123"[i - (n2 + n3)], ntest);
+                 else if (i == n2 + n3 + 3)
+                   check (buf1[i] == '\0', ntest);
+                 else
+                   check (buf1[i] == 'b', ntest);
+
+                 if (errors != olderrors)
+                   {
+                     printf ("n1=%zu, n2=%zu, n3=%zu, n4=%zu, buf1=%02hhx",
+                             n1, n2, n3, n4, buf1[0]);
+                     for (size_t j = 1; j < sizeof (buf1); ++j)
+                       printf (",%02hhx", buf1[j]);
+                     putchar_unlocked ('\n');
+                     break;
+                   }
+               }
+         }
 }
 
 static void
@@ -368,6 +453,8 @@ test_strncmp (void)
   check (strncmp ("abce", "abc", 3) == 0, 11); /* Count == length. */
   check (strncmp ("abcd", "abce", 4) < 0, 12); /* Nudging limit. */
   check (strncmp ("abc", "def", 0) == 0, 13);  /* Zero count. */
+  check (strncmp ("abc", "", (size_t)-1) > 0, 14);     /* set sign bit in count */
+  check (strncmp ("abc", "abc", (size_t)-2) == 0, 15);
 }
 
 static void
@@ -433,6 +520,30 @@ test_strlen (void)
    }
 }
 
+static void
+test_strnlen (void)
+{
+  it = "strnlen";
+  check (strnlen ("", 10) == 0, 1);            /* Empty. */
+  check (strnlen ("a", 10) == 1, 2);           /* Single char. */
+  check (strnlen ("abcd", 10) == 4, 3);                /* Multiple chars. */
+  check (strnlen ("foo", (size_t) -1) == 3, 4);        /* limits of n. */
+  check (strnlen ("abcd", 0) == 0, 5);         /* Restricted. */
+  check (strnlen ("abcd", 1) == 1, 6);         /* Restricted. */
+  check (strnlen ("abcd", 2) == 2, 7);         /* Restricted. */
+  check (strnlen ("abcd", 3) == 3, 8);         /* Restricted. */
+  check (strnlen ("abcd", 4) == 4, 9);         /* Restricted. */
+
+  char buf[4096];
+  for (int i = 0; i < 0x100; ++i)
+    {
+      char *p = (char *) ((unsigned long int)(buf + 0xff) & ~0xff) + i;
+      strcpy (p, "OK");
+      strcpy (p + 3, "BAD/WRONG");
+      check (strnlen (p, 100) == 2, 10 + i);
+    }
+}
+
 static void
 test_strchr (void)
 {
@@ -594,7 +705,7 @@ test_memrchr (void)
      more than 128 byte chunks: */
   {
     char buf[128 + sizeof(long)];
-    long align, len, i, pos;
+    long align, len, i, pos, n = 9;
 
     for (align = 0; align < (long) sizeof(long); ++align) {
       for (len = 0; len < (long) (sizeof(buf) - align); ++len) {
@@ -605,9 +716,9 @@ test_memrchr (void)
 #if 0
          printf("align %d, len %d, pos %d\n", align, len, pos);
 #endif
-         check(memrchr(buf + align, 'x', len) == buf + align + pos, 9);
+         check(memrchr(buf + align, 'x', len) == buf + align + pos, n++);
          check(memrchr(buf + align + pos + 1, 'x', len - (pos + 1)) == NULL,
-               10);
+               n++);
          buf[align + pos] = '-';
        }
       }
@@ -816,9 +927,13 @@ test_strtok_r (void)
   equal(strtok_r((char *)NULL, ",", &cp), "c", 29);
   check(strtok_r((char *)NULL, ",", &cp) == NULL, 30);
   equal(one+6, "gh", 31);                      /* Stomped past end? */
-  equal(one, "a", 32);                 /* Stomped old tokens? */
+  equal(one, "a", 32);                         /* Stomped old tokens? */
   equal(one+2, "b", 33);
   equal(one+4, "c", 34);
+  strcpy (one, ":::");
+  cp = NULL;
+  check (strtok_r (one, ":", &cp) == NULL, 35);        /* Must store pointer in cp. */
+  check (strtok_r (NULL, ":", &cp) == NULL, 36);
 }
 
 static void
@@ -957,15 +1072,33 @@ test_strsep (void)
 static void
 test_memcmp (void)
 {
+  int cnt = 1;
+  char one[21];
+  char two[21];
+
   it = "memcmp";
-  check(memcmp("a", "a", 1) == 0, 1);          /* Identity. */
-  check(memcmp("abc", "abc", 3) == 0, 2);      /* Multicharacter. */
-  check(memcmp("abcd", "abce", 4) < 0, 3);     /* Honestly unequal. */
-  check(memcmp("abce", "abcd", 4) > 0, 4);
-  check(memcmp("alph", "beta", 4) < 0, 5);
-  check(memcmp("a\203", "a\003", 2) > 0, 6);
-  check(memcmp("abce", "abcd", 3) == 0, 7);    /* Count limited. */
-  check(memcmp("abc", "def", 0) == 0, 8);      /* Zero count. */
+  check(memcmp("a", "a", 1) == 0, cnt++);      /* Identity. */
+  check(memcmp("abc", "abc", 3) == 0, cnt++);  /* Multicharacter. */
+  check(memcmp("abcd", "abcf", 4) < 0, cnt++); /* Honestly unequal. */
+  check(memcmp("abcf", "abcd", 4) > 0, cnt++);
+  check(memcmp("alph", "cold", 4) < 0, cnt++);
+  check(memcmp("a\203", "a\003", 2) > 0, cnt++);
+  check(memcmp("a\003", "a\203", 2) < 0, cnt++);
+  check(memcmp("a\003bc", "a\203bc", 2) < 0, cnt++);
+  check(memcmp("abc\203", "abc\003", 4) > 0, cnt++);
+  check(memcmp("abc\003", "abc\203", 4) < 0, cnt++);
+  check(memcmp("abcf", "abcd", 3) == 0, cnt++);        /* Count limited. */
+  check(memcmp("abc", "def", 0) == 0, cnt++);  /* Zero count. */
+  /* Comparisons with shifting 4-byte boundaries. */
+  for (int i = 0; i < 4; ++i)
+    {
+      char *a = one + i;
+      char *b = two + i;
+      strncpy(a, "--------11112222", 16);
+      strncpy(b, "--------33334444", 16);
+      check(memcmp(b, a, 16) > 0, cnt++);
+      check(memcmp(a, b, 16) < 0, cnt++);
+    }
 }
 
 static void
@@ -1171,8 +1304,15 @@ test_memset (void)
   check(memset(one+1, 'x', 3) == one+1, 1);    /* Return value. */
   equal(one, "axxxefgh", 2);           /* Basic test. */
 
+  DIAG_PUSH_NEEDS_COMMENT;
+#if __GNUC_PREREQ (5, 0)
+  /* GCC 5.0 warns about a zero-length memset because the arguments to memset
+     may be in the wrong order.  But we really want to test this.  */
+  DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Wmemset-transposed-args")
+#endif
   (void) memset(one+2, 'y', 0);
   equal(one, "axxxefgh", 3);           /* Zero-length set. */
+  DIAG_POP_NEEDS_COMMENT;
 
   (void) memset(one+5, 0, 1);
   equal(one, "axxxe", 4);                      /* Zero fill. */
@@ -1386,6 +1526,9 @@ main (void)
   /* strlen.  */
   test_strlen ();
 
+  /* strnlen.  */
+  test_strnlen ();
+
   /* strchr.  */
   test_strchr ();