X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=tests%2Ftest-strerror_r.c;h=9e1f0bef5132d7484f34150aa29bc035463a12c7;hb=a2d14e0a98bd1ccaed9f860c4988e59581293a0b;hp=7aad3c7365199e318dc7eef511fb2fc3d5cbd782;hpb=d1187148b5871737463ac53328e6d20ec711afd7;p=gnulib.git diff --git a/tests/test-strerror_r.c b/tests/test-strerror_r.c index 7aad3c736..9e1f0bef5 100644 --- a/tests/test-strerror_r.c +++ b/tests/test-strerror_r.c @@ -1,5 +1,5 @@ /* Test of strerror_r() function. - Copyright (C) 2007-2011 Free Software Foundation, Inc. + Copyright (C) 2007-2014 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -12,8 +12,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + along with this program; if not, see . */ #include @@ -34,65 +33,149 @@ main (void) /* Test results with valid errnum and enough room. */ + errno = 0; buf[0] = '\0'; - ASSERT (strerror_r (EACCES, buf, sizeof (buf)) == 0); + ASSERT (strerror_r (EACCES, buf, sizeof buf) == 0); ASSERT (buf[0] != '\0'); + ASSERT (errno == 0); + ASSERT (strlen (buf) < sizeof buf); + errno = 0; buf[0] = '\0'; - ASSERT (strerror_r (ETIMEDOUT, buf, sizeof (buf)) == 0); + ASSERT (strerror_r (ETIMEDOUT, buf, sizeof buf) == 0); ASSERT (buf[0] != '\0'); + ASSERT (errno == 0); + ASSERT (strlen (buf) < sizeof buf); + errno = 0; buf[0] = '\0'; - ASSERT (strerror_r (EOVERFLOW, buf, sizeof (buf)) == 0); + ASSERT (strerror_r (EOVERFLOW, buf, sizeof buf) == 0); ASSERT (buf[0] != '\0'); + ASSERT (errno == 0); + ASSERT (strlen (buf) < sizeof buf); /* POSIX requires strerror (0) to succeed. Reject use of "Unknown error", but allow "Success", "No error", or even Solaris' "Error 0" which are distinct patterns from true out-of-range strings. http://austingroupbugs.net/view.php?id=382 */ + errno = 0; buf[0] = '\0'; - ret = strerror_r (0, buf, sizeof (buf)); + ret = strerror_r (0, buf, sizeof buf); ASSERT (ret == 0); ASSERT (buf[0]); + ASSERT (errno == 0); ASSERT (strstr (buf, "nknown") == NULL); + ASSERT (strstr (buf, "ndefined") == NULL); - /* Test results with out-of-range errnum and enough room. */ - + /* Test results with out-of-range errnum and enough room. POSIX + allows an empty string on success, and allows an unchanged buf on + error, but these are not useful, so we guarantee contents. */ + errno = 0; buf[0] = '^'; - ret = strerror_r (-3, buf, sizeof (buf)); + ret = strerror_r (-3, buf, sizeof buf); ASSERT (ret == 0 || ret == EINVAL); - if (ret == 0) - ASSERT (buf[0] != '^'); - - /* Test results with a too small buffer. */ - - ASSERT (strerror_r (EACCES, buf, sizeof (buf)) == 0); + ASSERT (buf[0] != '^'); + ASSERT (*buf); + ASSERT (errno == 0); + ASSERT (strlen (buf) < sizeof buf); + + /* Test results with a too small buffer. POSIX requires an error; + only ERANGE for 0 and valid errors, and a choice of ERANGE or + EINVAL for out-of-range values. On error, POSIX permits buf to + be empty, unchanged, or unterminated, but these are not useful, + so we guarantee NUL-terminated truncated contents for all but + size 0. http://austingroupbugs.net/view.php?id=398. Also ensure + that no out-of-bounds writes occur. */ { - size_t len = strlen (buf); - size_t i; + int errs[] = { EACCES, 0, -3, }; + int j; - for (i = 0; i <= len; i++) + buf[sizeof buf - 1] = '\0'; + for (j = 0; j < SIZEOF (errs); j++) { - strcpy (buf, "BADFACE"); - ret = strerror_r (EACCES, buf, i); - if (ret == 0) - { - /* Truncated result. POSIX allows this, and it actually - happens on AIX 6.1 and Cygwin. */ - ASSERT ((strcmp (buf, "BADFACE") == 0) == (i == 0)); - } - else + int err = errs[j]; + char buf2[sizeof buf] = ""; + size_t len; + size_t i; + + strerror_r (err, buf2, sizeof buf2); + len = strlen (buf2); + ASSERT (len < sizeof buf); + + for (i = 0; i <= len; i++) { - /* Failure. */ - ASSERT (ret == ERANGE); - /* buf is clobbered nevertheless, on FreeBSD and MacOS X. */ + memset (buf, '^', sizeof buf - 1); + errno = 0; + ret = strerror_r (err, buf, i); + ASSERT (errno == 0); + if (err < 0) + ASSERT (ret == ERANGE || ret == EINVAL); + else + ASSERT (ret == ERANGE); + if (i) + { + ASSERT (strncmp (buf, buf2, i - 1) == 0); + ASSERT (buf[i - 1] == '\0'); + } + ASSERT (strspn (buf + i, "^") == sizeof buf - 1 - i); } + + strcpy (buf, "BADFACE"); + errno = 0; + ret = strerror_r (err, buf, len + 1); + ASSERT (ret != ERANGE); + ASSERT (errno == 0); + ASSERT (strcmp (buf, buf2) == 0); } + } - strcpy (buf, "BADFACE"); - ret = strerror_r (EACCES, buf, len + 1); - ASSERT (ret == 0); +#if GNULIB_STRERROR + /* Test that strerror_r does not clobber strerror buffer. On some + platforms, this test can only succeed if gnulib also replaces + strerror. */ + { + const char *msg1; + const char *msg2; + const char *msg3; + const char *msg4; + char *str1; + char *str2; + char *str3; + char *str4; + + msg1 = strerror (ENOENT); + ASSERT (msg1); + str1 = strdup (msg1); + ASSERT (str1); + + msg2 = strerror (ERANGE); + ASSERT (msg2); + str2 = strdup (msg2); + ASSERT (str2); + + msg3 = strerror (-4); + ASSERT (msg3); + str3 = strdup (msg3); + ASSERT (str3); + + msg4 = strerror (1729576); + ASSERT (msg4); + str4 = strdup (msg4); + ASSERT (str4); + + strerror_r (EACCES, buf, sizeof buf); + strerror_r (-5, buf, sizeof buf); + ASSERT (msg1 == msg2 || msg1 == msg4 || STREQ (msg1, str1)); + ASSERT (msg2 == msg4 || STREQ (msg2, str2)); + ASSERT (msg3 == msg4 || STREQ (msg3, str3)); + ASSERT (STREQ (msg4, str4)); + + free (str1); + free (str2); + free (str3); + free (str4); } +#endif return 0; }