| 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 | }
|
|---|