(root)/
m4-1.4.19/
tests/
test-strerror_r.c
       1  /* Test of strerror_r() function.
       2     Copyright (C) 2007-2021 Free Software Foundation, Inc.
       3  
       4     This program is free software; you can redistribute it and/or modify
       5     it under the terms of the GNU General Public License as published by
       6     the Free Software Foundation; either version 3, or (at your option)
       7     any later version.
       8  
       9     This program is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12     GNU General Public License for more details.
      13  
      14     You should have received a copy of the GNU General Public License
      15     along with this program; if not, see <https://www.gnu.org/licenses/>.  */
      16  
      17  #include <config.h>
      18  
      19  #include <string.h>
      20  
      21  #include "signature.h"
      22  SIGNATURE_CHECK (strerror_r, int, (int, char *, size_t));
      23  
      24  #include <errno.h>
      25  
      26  #include "macros.h"
      27  
      28  int
      29  main (void)
      30  {
      31    char buf[100];
      32    int ret;
      33  
      34    /* Test results with valid errnum and enough room.  */
      35  
      36    errno = 0;
      37    buf[0] = '\0';
      38    ASSERT (strerror_r (EACCES, buf, sizeof buf) == 0);
      39    ASSERT (buf[0] != '\0');
      40    ASSERT (errno == 0);
      41    ASSERT (strlen (buf) < sizeof buf);
      42  
      43    errno = 0;
      44    buf[0] = '\0';
      45    ASSERT (strerror_r (ETIMEDOUT, buf, sizeof buf) == 0);
      46    ASSERT (buf[0] != '\0');
      47    ASSERT (errno == 0);
      48    ASSERT (strlen (buf) < sizeof buf);
      49  
      50    errno = 0;
      51    buf[0] = '\0';
      52    ASSERT (strerror_r (EOVERFLOW, buf, sizeof buf) == 0);
      53    ASSERT (buf[0] != '\0');
      54    ASSERT (errno == 0);
      55    ASSERT (strlen (buf) < sizeof buf);
      56  
      57    /* POSIX requires strerror (0) to succeed.  Reject use of "Unknown
      58       error", but allow "Success", "No error", or even Solaris' "Error
      59       0" which are distinct patterns from true out-of-range strings.
      60       http://austingroupbugs.net/view.php?id=382  */
      61    errno = 0;
      62    buf[0] = '\0';
      63    ret = strerror_r (0, buf, sizeof buf);
      64    ASSERT (ret == 0);
      65    ASSERT (buf[0]);
      66    ASSERT (errno == 0);
      67    ASSERT (strstr (buf, "nknown") == NULL);
      68    ASSERT (strstr (buf, "ndefined") == NULL);
      69  
      70    /* Test results with out-of-range errnum and enough room.  POSIX
      71       allows an empty string on success, and allows an unchanged buf on
      72       error, but these are not useful, so we guarantee contents.  */
      73    errno = 0;
      74    buf[0] = '^';
      75    ret = strerror_r (-3, buf, sizeof buf);
      76    ASSERT (ret == 0 || ret == EINVAL);
      77    ASSERT (buf[0] != '^');
      78    ASSERT (*buf);
      79    ASSERT (errno == 0);
      80    ASSERT (strlen (buf) < sizeof buf);
      81  
      82    /* Test results with a too small buffer.  POSIX requires an error;
      83       only ERANGE for 0 and valid errors, and a choice of ERANGE or
      84       EINVAL for out-of-range values.  On error, POSIX permits buf to
      85       be empty, unchanged, or unterminated, but these are not useful,
      86       so we guarantee NUL-terminated truncated contents for all but
      87       size 0.  http://austingroupbugs.net/view.php?id=398.  Also ensure
      88       that no out-of-bounds writes occur.  */
      89    {
      90      int errs[] = { EACCES, 0, -3, };
      91      int j;
      92  
      93      buf[sizeof buf - 1] = '\0';
      94      for (j = 0; j < SIZEOF (errs); j++)
      95        {
      96          int err = errs[j];
      97          char buf2[sizeof buf] = "";
      98          size_t len;
      99          size_t i;
     100  
     101          strerror_r (err, buf2, sizeof buf2);
     102          len = strlen (buf2);
     103          ASSERT (len < sizeof buf);
     104  
     105          for (i = 0; i <= len; i++)
     106            {
     107              memset (buf, '^', sizeof buf - 1);
     108              errno = 0;
     109              ret = strerror_r (err, buf, i);
     110              ASSERT (errno == 0);
     111              if (j == 2)
     112                ASSERT (ret == ERANGE || ret == EINVAL);
     113              else
     114                ASSERT (ret == ERANGE);
     115              if (i)
     116                {
     117                  ASSERT (strncmp (buf, buf2, i - 1) == 0);
     118                  ASSERT (buf[i - 1] == '\0');
     119                }
     120              ASSERT (strspn (buf + i, "^") == sizeof buf - 1 - i);
     121            }
     122  
     123          strcpy (buf, "BADFACE");
     124          errno = 0;
     125          ret = strerror_r (err, buf, len + 1);
     126          ASSERT (ret != ERANGE);
     127          ASSERT (errno == 0);
     128          ASSERT (strcmp (buf, buf2) == 0);
     129        }
     130    }
     131  
     132  #if GNULIB_STRERROR
     133    /* Test that strerror_r does not clobber strerror buffer.  On some
     134       platforms, this test can only succeed if gnulib also replaces
     135       strerror.  */
     136    {
     137      const char *msg1;
     138      const char *msg2;
     139      const char *msg3;
     140      const char *msg4;
     141      char *str1;
     142      char *str2;
     143      char *str3;
     144      char *str4;
     145  
     146      msg1 = strerror (ENOENT);
     147      ASSERT (msg1);
     148      str1 = strdup (msg1);
     149      ASSERT (str1);
     150  
     151      msg2 = strerror (ERANGE);
     152      ASSERT (msg2);
     153      str2 = strdup (msg2);
     154      ASSERT (str2);
     155  
     156      msg3 = strerror (-4);
     157      ASSERT (msg3);
     158      str3 = strdup (msg3);
     159      ASSERT (str3);
     160  
     161      msg4 = strerror (1729576);
     162      ASSERT (msg4);
     163      str4 = strdup (msg4);
     164      ASSERT (str4);
     165  
     166      strerror_r (EACCES, buf, sizeof buf);
     167      strerror_r (-5, buf, sizeof buf);
     168      ASSERT (STREQ (msg4, str4));
     169  
     170      free (str1);
     171      free (str2);
     172      free (str3);
     173      free (str4);
     174    }
     175  #endif
     176  
     177    return 0;
     178  }