aboutsummaryrefslogtreecommitdiff
path: root/lib/libc/tests/stdio
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/tests/stdio')
-rw-r--r--lib/libc/tests/stdio/Makefile11
-rw-r--r--lib/libc/tests/stdio/fdopen_test.c1
-rw-r--r--lib/libc/tests/stdio/flushlbuf_test.c155
-rw-r--r--lib/libc/tests/stdio/fmemopen2_test.c34
-rw-r--r--lib/libc/tests/stdio/fopen_test.c1
-rw-r--r--lib/libc/tests/stdio/freopen_test.c1
-rw-r--r--lib/libc/tests/stdio/getdelim_test.c1
-rw-r--r--lib/libc/tests/stdio/gets_s_test.c1
-rw-r--r--lib/libc/tests/stdio/mkostemp_test.c1
-rw-r--r--lib/libc/tests/stdio/open_memstream2_test.c1
-rw-r--r--lib/libc/tests/stdio/open_wmemstream_test.c1
-rw-r--r--lib/libc/tests/stdio/perror_test.c1
-rw-r--r--lib/libc/tests/stdio/print_positional_test.c1
-rw-r--r--lib/libc/tests/stdio/printbasic_test.c1
-rw-r--r--lib/libc/tests/stdio/printfloat_test.c1
-rw-r--r--lib/libc/tests/stdio/scanfloat_test.c137
-rw-r--r--lib/libc/tests/stdio/snprintf_test.c87
-rw-r--r--lib/libc/tests/stdio/sscanf_test.c65
-rw-r--r--lib/libc/tests/stdio/swprintf_test.c206
-rw-r--r--lib/libc/tests/stdio/swscanf_test.c73
20 files changed, 683 insertions, 97 deletions
diff --git a/lib/libc/tests/stdio/Makefile b/lib/libc/tests/stdio/Makefile
index f7383e5b3ef4..6dca927c4fb7 100644
--- a/lib/libc/tests/stdio/Makefile
+++ b/lib/libc/tests/stdio/Makefile
@@ -1,8 +1,8 @@
-
.include <bsd.own.mk>
ATF_TESTS_C+= eintr_test
ATF_TESTS_C+= fdopen_test
+ATF_TESTS_C+= flushlbuf_test
ATF_TESTS_C+= fmemopen2_test
ATF_TESTS_C+= fopen2_test
ATF_TESTS_C+= freopen_test
@@ -18,6 +18,7 @@ ATF_TESTS_C+= printfloat_test
ATF_TESTS_C+= scanfloat_test
ATF_TESTS_C+= snprintf_test
ATF_TESTS_C+= sscanf_test
+ATF_TESTS_C+= swprintf_test
ATF_TESTS_C+= swscanf_test
SRCS.fopen2_test= fopen_test.c
@@ -37,9 +38,15 @@ LIBADD.eintr_test+= md
LIBADD.printfloat_test+= m
LIBADD.scanfloat_test+= m
+# Older toolchains won't understand C23 %b, %wN, %wfN
+PROG_OVERRIDE_VARS+= NO_WFORMAT
+NO_WFORMAT.snprintf_test=
+NO_WFORMAT.sscanf_test=
+NO_WFORMAT.swprintf_test=
+NO_WFORMAT.swscanf_test=
+
.if ${COMPILER_TYPE} == "gcc"
# 90: use of assignment suppression and length modifier together in scanf format
-PROG_OVERRIDE_VARS+= NO_WFORMAT
NO_WFORMAT.scanfloat_test=
.endif
diff --git a/lib/libc/tests/stdio/fdopen_test.c b/lib/libc/tests/stdio/fdopen_test.c
index 211e16279a3c..5abaed7375b6 100644
--- a/lib/libc/tests/stdio/fdopen_test.c
+++ b/lib/libc/tests/stdio/fdopen_test.c
@@ -24,7 +24,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
#include <errno.h>
#include <fcntl.h>
#include <paths.h>
diff --git a/lib/libc/tests/stdio/flushlbuf_test.c b/lib/libc/tests/stdio/flushlbuf_test.c
new file mode 100644
index 000000000000..11d9ea4ecc6c
--- /dev/null
+++ b/lib/libc/tests/stdio/flushlbuf_test.c
@@ -0,0 +1,155 @@
+/*-
+ * Copyright (c) 2023 Klara, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <errno.h>
+#include <stdio.h>
+
+#include <atf-c.h>
+
+#define BUFSIZE 16
+
+static const char seq[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789+/";
+
+struct stream {
+ char buf[BUFSIZE];
+ unsigned int len;
+ unsigned int pos;
+};
+
+static int writefn(void *cookie, const char *buf, int len)
+{
+ struct stream *s = cookie;
+ int written = 0;
+
+ if (len <= 0)
+ return 0;
+ while (len > 0 && s->pos < s->len) {
+ s->buf[s->pos++] = *buf++;
+ written++;
+ len--;
+ }
+ if (written > 0)
+ return written;
+ errno = EAGAIN;
+ return -1;
+}
+
+ATF_TC_WITHOUT_HEAD(flushlbuf_partial);
+ATF_TC_BODY(flushlbuf_partial, tc)
+{
+ static struct stream s;
+ static char buf[BUFSIZE + 1];
+ FILE *f;
+ unsigned int i = 0;
+ int ret = 0;
+
+ /*
+ * Create the stream and its buffer, print just enough characters
+ * to the stream to fill the buffer without triggering a flush,
+ * then check the state.
+ */
+ s.len = BUFSIZE / 2; // write will fail after this amount
+ ATF_REQUIRE((f = fwopen(&s, writefn)) != NULL);
+ ATF_REQUIRE(setvbuf(f, buf, _IOLBF, BUFSIZE) == 0);
+ while (i < BUFSIZE)
+ if ((ret = fprintf(f, "%c", seq[i++])) < 0)
+ break;
+ ATF_CHECK_EQ(BUFSIZE, i);
+ ATF_CHECK_EQ(seq[i - 1], buf[BUFSIZE - 1]);
+ ATF_CHECK_EQ(1, ret);
+ ATF_CHECK_EQ(0, s.pos);
+
+ /*
+ * At this point, the buffer is full but writefn() has not yet
+ * been called. The next fprintf() call will trigger a preemptive
+ * fflush(), and writefn() will consume s.len characters before
+ * returning EAGAIN, causing fprintf() to fail without having
+ * written anything (which is why we don't increment i here).
+ */
+ ret = fprintf(f, "%c", seq[i]);
+ ATF_CHECK_ERRNO(EAGAIN, ret < 0);
+ ATF_CHECK_EQ(s.len, s.pos);
+
+ /*
+ * We have consumed s.len characters from the buffer, so continue
+ * printing until it is full again and check that no overflow has
+ * occurred yet.
+ */
+ while (i < BUFSIZE + s.len)
+ fprintf(f, "%c", seq[i++]);
+ ATF_CHECK_EQ(BUFSIZE + s.len, i);
+ ATF_CHECK_EQ(seq[i - 1], buf[BUFSIZE - 1]);
+ ATF_CHECK_EQ(0, buf[BUFSIZE]);
+
+ /*
+ * The straw that breaks the camel's back: libc fails to recognize
+ * that the buffer is full and continues to write beyond its end.
+ */
+ fprintf(f, "%c", seq[i++]);
+ ATF_CHECK_EQ(0, buf[BUFSIZE]);
+}
+
+ATF_TC_WITHOUT_HEAD(flushlbuf_full);
+ATF_TC_BODY(flushlbuf_full, tc)
+{
+ static struct stream s;
+ static char buf[BUFSIZE];
+ FILE *f;
+ unsigned int i = 0;
+ int ret = 0;
+
+ /*
+ * Create the stream and its buffer, print just enough characters
+ * to the stream to fill the buffer without triggering a flush,
+ * then check the state.
+ */
+ s.len = 0; // any attempt to write will fail
+ ATF_REQUIRE((f = fwopen(&s, writefn)) != NULL);
+ ATF_REQUIRE(setvbuf(f, buf, _IOLBF, BUFSIZE) == 0);
+ while (i < BUFSIZE)
+ if ((ret = fprintf(f, "%c", seq[i++])) < 0)
+ break;
+ ATF_CHECK_EQ(BUFSIZE, i);
+ ATF_CHECK_EQ(seq[i - 1], buf[BUFSIZE - 1]);
+ ATF_CHECK_EQ(1, ret);
+ ATF_CHECK_EQ(0, s.pos);
+
+ /*
+ * At this point, the buffer is full but writefn() has not yet
+ * been called. The next fprintf() call will trigger a preemptive
+ * fflush(), and writefn() will immediately return EAGAIN, causing
+ * fprintf() to fail without having written anything (which is why
+ * we don't increment i here).
+ */
+ ret = fprintf(f, "%c", seq[i]);
+ ATF_CHECK_ERRNO(EAGAIN, ret < 0);
+ ATF_CHECK_EQ(s.len, s.pos);
+
+ /*
+ * Now make our stream writeable.
+ */
+ s.len = sizeof(s.buf);
+
+ /*
+ * Flush the stream again. The data we failed to write previously
+ * should still be in the buffer and will now be written to the
+ * stream.
+ */
+ ATF_CHECK_EQ(0, fflush(f));
+ ATF_CHECK_EQ(seq[0], s.buf[0]);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, flushlbuf_partial);
+ ATF_TP_ADD_TC(tp, flushlbuf_full);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/stdio/fmemopen2_test.c b/lib/libc/tests/stdio/fmemopen2_test.c
index d68150d19594..a558ff3515e9 100644
--- a/lib/libc/tests/stdio/fmemopen2_test.c
+++ b/lib/libc/tests/stdio/fmemopen2_test.c
@@ -28,7 +28,6 @@ SUCH DAMAGE.
* a FILE * retrieved using fmemopen()
*/
-#include <sys/cdefs.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
@@ -133,9 +132,11 @@ ATF_TC_BODY(test_autoalloc, tc)
/* Open a FILE * using a wrong mode */
fp = fmemopen(NULL, 512, "r");
ATF_REQUIRE(fp == NULL);
+ ATF_REQUIRE(errno == EINVAL);
fp = fmemopen(NULL, 512, "w");
ATF_REQUIRE(fp == NULL);
+ ATF_REQUIRE(errno == EINVAL);
}
ATF_TC_WITHOUT_HEAD(test_data_length);
@@ -272,6 +273,36 @@ ATF_TC_BODY(test_size_0, tc)
ATF_REQUIRE(errno == EINVAL);
}
+/*
+ * PR281953 - ensure we cannot write in read-only only mode, and cannot read in
+ * write-only mode.
+ */
+ATF_TC_WITHOUT_HEAD(test_rdonly_wronly);
+ATF_TC_BODY(test_rdonly_wronly, tc)
+{
+ FILE *fp;
+ char buf[16];
+ char buf_orig[16] = "input data";
+ char buf_write[16] = "write";
+ size_t sz;
+
+ memcpy(buf, buf_orig, sizeof(buf));
+ fp = fmemopen(buf, sizeof(buf), "r");
+ ATF_REQUIRE(fp != NULL);
+ sz = fwrite(buf_write, 1, strlen(buf_write), fp);
+ ATF_REQUIRE(sz == 0);
+ ATF_REQUIRE(errno == EBADF);
+ ATF_REQUIRE(memcmp(buf, buf_orig, sizeof(buf)) == 0);
+ fclose(fp);
+
+ fp = fmemopen(buf_orig, sizeof(buf), "w");
+ ATF_REQUIRE(fp != NULL);
+ sz = fread(buf, sizeof(buf), 1, fp);
+ ATF_REQUIRE(sz == 0);
+ ATF_REQUIRE(errno == EBADF);
+ fclose(fp);
+}
+
ATF_TP_ADD_TCS(tp)
{
@@ -281,6 +312,7 @@ ATF_TP_ADD_TCS(tp)
ATF_TP_ADD_TC(tp, test_binary);
ATF_TP_ADD_TC(tp, test_append_binary_pos);
ATF_TP_ADD_TC(tp, test_size_0);
+ ATF_TP_ADD_TC(tp, test_rdonly_wronly);
return (atf_no_error());
}
diff --git a/lib/libc/tests/stdio/fopen_test.c b/lib/libc/tests/stdio/fopen_test.c
index fdc460716ff2..4dda5cbf0e5e 100644
--- a/lib/libc/tests/stdio/fopen_test.c
+++ b/lib/libc/tests/stdio/fopen_test.c
@@ -24,7 +24,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
#include <fcntl.h>
#include <paths.h>
#include <stdio.h>
diff --git a/lib/libc/tests/stdio/freopen_test.c b/lib/libc/tests/stdio/freopen_test.c
index 7318a95df089..55fe3c580dd3 100644
--- a/lib/libc/tests/stdio/freopen_test.c
+++ b/lib/libc/tests/stdio/freopen_test.c
@@ -24,7 +24,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
#include <errno.h>
#include <paths.h>
#include <stdbool.h>
diff --git a/lib/libc/tests/stdio/getdelim_test.c b/lib/libc/tests/stdio/getdelim_test.c
index 8cb1763d9e01..01a0ab0949fe 100644
--- a/lib/libc/tests/stdio/getdelim_test.c
+++ b/lib/libc/tests/stdio/getdelim_test.c
@@ -25,7 +25,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
diff --git a/lib/libc/tests/stdio/gets_s_test.c b/lib/libc/tests/stdio/gets_s_test.c
index c6eda57c03ea..4e1a59006b60 100644
--- a/lib/libc/tests/stdio/gets_s_test.c
+++ b/lib/libc/tests/stdio/gets_s_test.c
@@ -23,7 +23,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
diff --git a/lib/libc/tests/stdio/mkostemp_test.c b/lib/libc/tests/stdio/mkostemp_test.c
index 1e3f6dc03768..b31335fed43f 100644
--- a/lib/libc/tests/stdio/mkostemp_test.c
+++ b/lib/libc/tests/stdio/mkostemp_test.c
@@ -28,7 +28,6 @@
* Test program for mkostemp().
*/
-#include <sys/cdefs.h>
#include <sys/stat.h>
#include <errno.h>
diff --git a/lib/libc/tests/stdio/open_memstream2_test.c b/lib/libc/tests/stdio/open_memstream2_test.c
index 513192965c93..c9c6528832d8 100644
--- a/lib/libc/tests/stdio/open_memstream2_test.c
+++ b/lib/libc/tests/stdio/open_memstream2_test.c
@@ -25,7 +25,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
#include <err.h>
#include <errno.h>
#include <limits.h>
diff --git a/lib/libc/tests/stdio/open_wmemstream_test.c b/lib/libc/tests/stdio/open_wmemstream_test.c
index cbe7e4776737..7ab882a4740a 100644
--- a/lib/libc/tests/stdio/open_wmemstream_test.c
+++ b/lib/libc/tests/stdio/open_wmemstream_test.c
@@ -25,7 +25,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
#include <err.h>
#include <errno.h>
#include <limits.h>
diff --git a/lib/libc/tests/stdio/perror_test.c b/lib/libc/tests/stdio/perror_test.c
index e6d2c0c130a6..f3cb646d094e 100644
--- a/lib/libc/tests/stdio/perror_test.c
+++ b/lib/libc/tests/stdio/perror_test.c
@@ -29,7 +29,6 @@
* ISO/IEC 9899:1999.
*/
-#include <sys/cdefs.h>
#include <err.h>
#include <errno.h>
#include <limits.h>
diff --git a/lib/libc/tests/stdio/print_positional_test.c b/lib/libc/tests/stdio/print_positional_test.c
index ba5a7b13135c..f896a30882f4 100644
--- a/lib/libc/tests/stdio/print_positional_test.c
+++ b/lib/libc/tests/stdio/print_positional_test.c
@@ -29,7 +29,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
#include <sys/param.h>
#include <stdio.h>
#include <stdlib.h>
diff --git a/lib/libc/tests/stdio/printbasic_test.c b/lib/libc/tests/stdio/printbasic_test.c
index 5f47979c0ff0..411dff518795 100644
--- a/lib/libc/tests/stdio/printbasic_test.c
+++ b/lib/libc/tests/stdio/printbasic_test.c
@@ -28,7 +28,6 @@
* Tests for basic and miscellaneous printf() formats.
*/
-#include <sys/cdefs.h>
#include <err.h>
#include <limits.h>
#include <locale.h>
diff --git a/lib/libc/tests/stdio/printfloat_test.c b/lib/libc/tests/stdio/printfloat_test.c
index aeb4ed43b772..031859124163 100644
--- a/lib/libc/tests/stdio/printfloat_test.c
+++ b/lib/libc/tests/stdio/printfloat_test.c
@@ -28,7 +28,6 @@
* Test for printf() floating point formats.
*/
-#include <sys/cdefs.h>
#include <err.h>
#include <fenv.h>
#include <float.h>
diff --git a/lib/libc/tests/stdio/scanfloat_test.c b/lib/libc/tests/stdio/scanfloat_test.c
index 473565b25747..635d93d560b3 100644
--- a/lib/libc/tests/stdio/scanfloat_test.c
+++ b/lib/libc/tests/stdio/scanfloat_test.c
@@ -28,7 +28,6 @@
* Test for scanf() floating point formats.
*/
-#include <sys/cdefs.h>
#include <fenv.h>
#include <float.h>
#include <locale.h>
@@ -60,88 +59,88 @@ ATF_TC_BODY(normalized_numbers, tc)
buf[0] = '\0';
ATF_REQUIRE(setlocale(LC_NUMERIC, ""));
- sscanf("3.141592", "%e", &f);
+ ATF_REQUIRE_EQ(1, sscanf("3.141592", "%e", &f));
ATF_REQUIRE(eq(FLT, f, 3.141592));
- sscanf("3.141592653589793", "%lf", &d);
+ ATF_REQUIRE_EQ(1, sscanf("3.141592653589793", "%lf", &d));
ATF_REQUIRE(eq(DBL, d, 3.141592653589793));
- sscanf("1.234568e+06", "%E", &f);
+ ATF_REQUIRE_EQ(1, sscanf("1.234568e+06", "%E", &f));
ATF_REQUIRE(eq(FLT, f, 1.234568e+06));
- sscanf("-1.234568e6", "%lF", &d);
+ ATF_REQUIRE_EQ(1, sscanf("-1.234568e6", "%lF", &d));
ATF_REQUIRE(eq(DBL, d, -1.234568e6));
- sscanf("+1.234568e-52", "%LG", &ld);
+ ATF_REQUIRE_EQ(1, sscanf("+1.234568e-52", "%LG", &ld));
ATF_REQUIRE(eq(LDBL, ld, 1.234568e-52L));
- sscanf("0.1", "%la", &d);
+ ATF_REQUIRE_EQ(1, sscanf("0.1", "%la", &d));
ATF_REQUIRE(eq(DBL, d, 0.1));
- sscanf("00.2", "%lA", &d);
+ ATF_REQUIRE_EQ(1, sscanf("00.2", "%lA", &d));
ATF_REQUIRE(eq(DBL, d, 0.2));
- sscanf("123456", "%5le%s", &d, buf);
+ ATF_REQUIRE_EQ(2, sscanf("123456", "%5le%s", &d, buf));
ATF_REQUIRE(eq(DBL, d, 12345.));
ATF_REQUIRE(strcmp(buf, "6") == 0);
- sscanf("1.0Q", "%*5le%s", buf);
+ ATF_REQUIRE_EQ(1, sscanf("1.0Q", "%*5le%s", buf));
ATF_REQUIRE(strcmp(buf, "Q") == 0);
- sscanf("-1.23e", "%e%s", &f, buf);
+ ATF_REQUIRE_EQ(2, sscanf("-1.23e", "%e%s", &f, buf));
ATF_REQUIRE(eq(FLT, f, -1.23));
ATF_REQUIRE(strcmp(buf, "e") == 0);
- sscanf("1.25e+", "%le%s", &d, buf);
+ ATF_REQUIRE_EQ(2, sscanf("1.25e+", "%le%s", &d, buf));
ATF_REQUIRE(eq(DBL, d, 1.25));
ATF_REQUIRE(strcmp(buf, "e+") == 0);
- sscanf("1.23E4E5", "%le%s", &d, buf);
+ ATF_REQUIRE_EQ(2, sscanf("1.23E4E5", "%le%s", &d, buf));
ATF_REQUIRE(eq(DBL, d, 1.23e4));
ATF_REQUIRE(strcmp(buf, "E5") == 0);
- sscanf("12e6", "%le", &d);
+ ATF_REQUIRE_EQ(1, sscanf("12e6", "%le", &d));
ATF_REQUIRE(eq(DBL, d, 12e6));
- sscanf("1.a", "%le%s", &d, buf);
+ ATF_REQUIRE_EQ(2, sscanf("1.a", "%le%s", &d, buf));
ATF_REQUIRE(eq(DBL, d, 1.0));
ATF_REQUIRE(strcmp(buf, "a") == 0);
- sscanf(".0p4", "%le%s", &d, buf);
+ ATF_REQUIRE_EQ(2, sscanf(".0p4", "%le%s", &d, buf));
ATF_REQUIRE(eq(DBL, d, 0.0));
ATF_REQUIRE(strcmp(buf, "p4") == 0);
d = 0.25;
- ATF_REQUIRE(sscanf(".", "%le", &d) == 0);
+ ATF_REQUIRE_EQ(0, sscanf(".", "%le", &d));
ATF_REQUIRE(d == 0.25);
- sscanf("0x08", "%le", &d);
+ ATF_REQUIRE_EQ(1, sscanf("0x08", "%le", &d));
ATF_REQUIRE(d == 0x8p0);
- sscanf("0x90a.bcdefP+09a", "%le%s", &d, buf);
+ ATF_REQUIRE_EQ(2, sscanf("0x90a.bcdefP+09a", "%le%s", &d, buf));
ATF_REQUIRE(d == 0x90a.bcdefp+09);
ATF_REQUIRE(strcmp(buf, "a") == 0);
#if (LDBL_MANT_DIG > DBL_MANT_DIG) && !defined(__i386__)
- sscanf("3.14159265358979323846", "%Lg", &ld);
+ ATF_REQUIRE_EQ(1, sscanf("3.14159265358979323846", "%Lg", &ld));
ATF_REQUIRE(eq(LDBL, ld, 3.14159265358979323846L));
- sscanf(" 0X.0123456789abcdefffp-3g", "%Le%s", &ld, buf);
+ ATF_REQUIRE_EQ(2, sscanf(" 0X.0123456789abcdefffp-3g", "%Le%s", &ld, buf));
ATF_REQUIRE(ld == 0x0.0123456789abcdefffp-3L);
ATF_REQUIRE(strcmp(buf, "g") == 0);
#endif
- sscanf("0xg", "%le%s", &d, buf);
+ ATF_REQUIRE_EQ(2, sscanf("0xg", "%le%s", &d, buf));
ATF_REQUIRE(d == 0.0);
ATF_REQUIRE(strcmp(buf, "xg") == 0);
ATF_REQUIRE(setlocale(LC_NUMERIC, "ru_RU.ISO8859-5")); /* decimalpoint==, */
- sscanf("1.23", "%le%s", &d, buf);
+ ATF_REQUIRE_EQ(2, sscanf("1.23", "%le%s", &d, buf));
ATF_REQUIRE(d == 1.0);
ATF_REQUIRE(strcmp(buf, ".23") == 0);
- sscanf("1,23", "%le", &d);
+ ATF_REQUIRE_EQ(1, sscanf("1,23", "%le", &d));
ATF_REQUIRE(d == 1.23);
ATF_REQUIRE(setlocale(LC_NUMERIC, ""));
@@ -157,40 +156,40 @@ ATF_TC_BODY(infinities_and_nans, tc)
ATF_REQUIRE(setlocale(LC_NUMERIC, "C"));
- sscanf("-Inf", "%le", &d);
+ ATF_REQUIRE_EQ(1, sscanf("-Inf", "%le", &d));
ATF_REQUIRE(d < 0.0 && isinf(d));
- sscanf("iNfInItY and beyond", "%le%s", &d, buf);
+ ATF_REQUIRE_EQ(2, sscanf("iNfInItY and beyond", "%le%s", &d, buf));
ATF_REQUIRE(d > 0.0 && isinf(d));
ATF_REQUIRE(strcmp(buf, " and beyond"));
- sscanf("NaN", "%le", &d);
+ ATF_REQUIRE_EQ(1, sscanf("NaN", "%le", &d));
ATF_REQUIRE(isnan(d));
- sscanf("NAN(123Y", "%le%s", &d, buf);
+ ATF_REQUIRE_EQ(2, sscanf("NAN(123Y", "%le%s", &d, buf));
ATF_REQUIRE(isnan(d));
ATF_REQUIRE(strcmp(buf, "(123Y") == 0);
- sscanf("nan(f00f)plugh", "%le%s", &d, buf);
+ ATF_REQUIRE_EQ(2, sscanf("nan(f00f)plugh", "%le%s", &d, buf));
ATF_REQUIRE(isnan(d));
ATF_REQUIRE(strcmp(buf, "plugh") == 0);
- sscanf("-nan", "%le", &d);
+ ATF_REQUIRE_EQ(1, sscanf("-nan", "%le", &d));
ATF_REQUIRE(isnan(d));
/* Only quiet NaNs should be returned. */
- sscanf("NaN", "%e", &f);
- sscanf("nan", "%le", &d);
- sscanf("nan", "%Le", &ld);
- feclearexcept(FE_ALL_EXCEPT);
+ ATF_REQUIRE_EQ(1, sscanf("NaN", "%e", &f));
+ ATF_REQUIRE_EQ(1, sscanf("nan", "%le", &d));
+ ATF_REQUIRE_EQ(1, sscanf("nan", "%Le", &ld));
+ ATF_REQUIRE_EQ(0, feclearexcept(FE_ALL_EXCEPT));
ATF_REQUIRE(f != f);
ATF_REQUIRE(d != d);
ATF_REQUIRE(ld != ld);
ATF_REQUIRE(fetestexcept(FE_INVALID) == 0);
- sscanf("nan(1234)", "%e", &f);
- sscanf("nan(1234)", "%le", &d);
- sscanf("nan(1234)", "%Le", &ld);
- feclearexcept(FE_ALL_EXCEPT);
+ ATF_REQUIRE_EQ(1, sscanf("nan(1234)", "%e", &f));
+ ATF_REQUIRE_EQ(1, sscanf("nan(1234)", "%le", &d));
+ ATF_REQUIRE_EQ(1, sscanf("nan(1234)", "%Le", &ld));
+ ATF_REQUIRE_EQ(0, feclearexcept(FE_ALL_EXCEPT));
ATF_REQUIRE(f != f);
ATF_REQUIRE(d != d);
ATF_REQUIRE(ld != ld);
@@ -206,74 +205,74 @@ ATF_TC_BODY(rounding_tests, tc)
ATF_REQUIRE(setlocale(LC_NUMERIC, "C"));
- fesetround(FE_DOWNWARD);
+ ATF_REQUIRE_EQ(0, fesetround(FE_DOWNWARD));
- sscanf("1.999999999999999999999999999999999", "%le", &d);
+ ATF_REQUIRE_EQ(1, sscanf("1.999999999999999999999999999999999", "%le", &d));
ATF_REQUIRE(d < 2.0);
- sscanf("0x1.ffffffffffffffp0", "%le", &d);
+ ATF_REQUIRE_EQ(1, sscanf("0x1.ffffffffffffffp0", "%le", &d));
ATF_REQUIRE(d < 2.0);
- sscanf("1.999999999999999999999999999999999", "%Le", &ld);
+ ATF_REQUIRE_EQ(1, sscanf("1.999999999999999999999999999999999", "%Le", &ld));
ATF_REQUIRE(ld < 2.0);
- sscanf("1.0571892669084007", "%le", &d);
+ ATF_REQUIRE_EQ(1, sscanf("1.0571892669084007", "%le", &d));
ATF_REQUIRE(d == 0x1.0ea3f4af0dc59p0);
- sscanf("-1.0571892669084007", "%le", &d);
+ ATF_REQUIRE_EQ(1, sscanf("-1.0571892669084007", "%le", &d));
ATF_REQUIRE(d == -0x1.0ea3f4af0dc5ap0);
- sscanf("1.0571892669084010", "%le", &d);
+ ATF_REQUIRE_EQ(1, sscanf("1.0571892669084010", "%le", &d));
ATF_REQUIRE(d == 0x1.0ea3f4af0dc5ap0);
- sscanf("0x1.23p-5000", "%le", &d);
+ ATF_REQUIRE_EQ(1, sscanf("0x1.23p-5000", "%le", &d));
ATF_REQUIRE(d == 0.0);
- sscanf("0x1.2345678p-1050", "%le", &d);
+ ATF_REQUIRE_EQ(1, sscanf("0x1.2345678p-1050", "%le", &d));
ATF_REQUIRE(d == 0x1.234567p-1050);
- fesetround(FE_UPWARD);
+ ATF_REQUIRE_EQ(0, fesetround(FE_UPWARD));
- sscanf("1.0571892669084007", "%le", &d);
+ ATF_REQUIRE_EQ(1, sscanf("1.0571892669084007", "%le", &d));
ATF_REQUIRE(d == 0x1.0ea3f4af0dc5ap0);
- sscanf("-1.0571892669084007", "%le", &d);
+ ATF_REQUIRE_EQ(1, sscanf("-1.0571892669084007", "%le", &d));
ATF_REQUIRE(d == -0x1.0ea3f4af0dc59p0);
- sscanf("1.0571892669084010", "%le", &d);
+ ATF_REQUIRE_EQ(1, sscanf("1.0571892669084010", "%le", &d));
ATF_REQUIRE(d == 0x1.0ea3f4af0dc5bp0);
- sscanf("0x1.23p-5000", "%le", &d);
+ ATF_REQUIRE_EQ(1, sscanf("0x1.23p-5000", "%le", &d));
ATF_REQUIRE(d == 0x1p-1074);
- sscanf("0x1.2345678p-1050", "%le", &d);
+ ATF_REQUIRE_EQ(1, sscanf("0x1.2345678p-1050", "%le", &d));
ATF_REQUIRE(d == 0x1.234568p-1050);
- fesetround(FE_TOWARDZERO);
+ ATF_REQUIRE_EQ(0, fesetround(FE_TOWARDZERO));
- sscanf("1.0571892669084007", "%le", &d);
+ ATF_REQUIRE_EQ(1, sscanf("1.0571892669084007", "%le", &d));
ATF_REQUIRE(d == 0x1.0ea3f4af0dc59p0);
- sscanf("-1.0571892669084007", "%le", &d);
+ ATF_REQUIRE_EQ(1, sscanf("-1.0571892669084007", "%le", &d));
ATF_REQUIRE(d == -0x1.0ea3f4af0dc59p0);
- sscanf("1.0571892669084010", "%le", &d);
+ ATF_REQUIRE_EQ(1, sscanf("1.0571892669084010", "%le", &d));
ATF_REQUIRE(d == 0x1.0ea3f4af0dc5ap0);
- sscanf("0x1.23p-5000", "%le", &d);
+ ATF_REQUIRE_EQ(1, sscanf("0x1.23p-5000", "%le", &d));
ATF_REQUIRE(d == 0.0);
- sscanf("0x1.2345678p-1050", "%le", &d);
+ ATF_REQUIRE_EQ(1, sscanf("0x1.2345678p-1050", "%le", &d));
ATF_REQUIRE(d == 0x1.234567p-1050);
- fesetround(FE_TONEAREST);
+ ATF_REQUIRE_EQ(0, fesetround(FE_TONEAREST));
/* 1.0571892669084007 is slightly closer to 0x1.0ea3f4af0dc59p0 */
- sscanf("1.0571892669084007", "%le", &d);
+ ATF_REQUIRE_EQ(1, sscanf("1.0571892669084007", "%le", &d));
ATF_REQUIRE(d == 0x1.0ea3f4af0dc59p0);
- sscanf("-1.0571892669084007", "%le", &d);
+ ATF_REQUIRE_EQ(1, sscanf("-1.0571892669084007", "%le", &d));
ATF_REQUIRE(d == -0x1.0ea3f4af0dc59p0);
- sscanf("1.0571892669084010", "%le", &d);
+ ATF_REQUIRE_EQ(1, sscanf("1.0571892669084010", "%le", &d));
ATF_REQUIRE(d == 0x1.0ea3f4af0dc5bp0);
/* strtod() should round small numbers to 0. */
- sscanf("0x1.23p-5000", "%le", &d);
+ ATF_REQUIRE_EQ(1, sscanf("0x1.23p-5000", "%le", &d));
ATF_REQUIRE(d == 0.0);
/* Extra digits in a denormal shouldn't break anything. */
- sscanf("0x1.2345678p-1050", "%le", &d);
+ ATF_REQUIRE_EQ(1, sscanf("0x1.2345678p-1050", "%le", &d));
ATF_REQUIRE(d == 0x1.234568p-1050);
}
@@ -288,16 +287,16 @@ ATF_TC_BODY(strtod, tc)
ATF_REQUIRE(strcmp("xy", endp) == 0);
/* This used to cause an infinite loop and round the wrong way. */
- fesetround(FE_DOWNWARD);
+ ATF_REQUIRE_EQ(0, fesetround(FE_DOWNWARD));
ATF_REQUIRE(strtof("3.5e38", &endp) == FLT_MAX);
ATF_REQUIRE(strtod("2e308", &endp) == DBL_MAX);
- fesetround(FE_UPWARD);
+ ATF_REQUIRE_EQ(0, fesetround(FE_UPWARD));
ATF_REQUIRE(strtof("3.5e38", &endp) == INFINITY);
ATF_REQUIRE(strtod("2e308", &endp) == INFINITY);
- fesetround(FE_TOWARDZERO);
+ ATF_REQUIRE_EQ(0, fesetround(FE_TOWARDZERO));
ATF_REQUIRE(strtof("3.5e38", &endp) == FLT_MAX);
ATF_REQUIRE(strtod("2e308", &endp) == DBL_MAX);
- fesetround(FE_TONEAREST);
+ ATF_REQUIRE_EQ(0, fesetround(FE_TONEAREST));
ATF_REQUIRE(strtof("3.5e38", &endp) == INFINITY);
ATF_REQUIRE(strtod("2e308", &endp) == INFINITY);
}
diff --git a/lib/libc/tests/stdio/snprintf_test.c b/lib/libc/tests/stdio/snprintf_test.c
index 0c335bc1a512..29b908b65120 100644
--- a/lib/libc/tests/stdio/snprintf_test.c
+++ b/lib/libc/tests/stdio/snprintf_test.c
@@ -12,18 +12,19 @@
#include <atf-c.h>
-#define SNPRINTF_TEST(output, format, ...) \
+#ifndef nitems
+#define nitems(a) (sizeof(a) / sizeof(a[0]))
+#endif
+
+#define SNPRINTF_TEST(output, format, ...) \
do { \
char buf[256]; \
- assert(output == NULL || strlen(output) < sizeof(buf)); \
- int ret = snprintf(buf, sizeof(buf), format, __VA_ARGS__); \
- if (output == NULL) { \
- ATF_CHECK_EQ(-1, ret); \
- } else { \
- ATF_CHECK_EQ(strlen(output), ret); \
- if (ret > 0) { \
- ATF_CHECK_STREQ(output, buf); \
- } \
+ assert(strlen(output) < nitems(buf)); \
+ int ret = snprintf(buf, nitems(buf), format, \
+ __VA_ARGS__); \
+ ATF_CHECK_EQ(strlen(output), ret); \
+ if (ret > 0) { \
+ ATF_CHECK_EQ(0, strcmp(output, buf)); \
} \
} while (0)
@@ -126,6 +127,70 @@ ATF_TC_BODY(snprintf_X, tc)
SNPRINTF_TEST("0X007FFFFFFF", "%#012X", INT_MAX);
}
+ATF_TC_WITHOUT_HEAD(snprintf_wN);
+ATF_TC_BODY(snprintf_wN, tc)
+{
+ SNPRINTF_TEST("0", "%w8d", (int8_t)0);
+ SNPRINTF_TEST("-128", "%w8d", (int8_t)SCHAR_MIN);
+ SNPRINTF_TEST("127", "%w8d", (int8_t)SCHAR_MAX);
+ SNPRINTF_TEST("0", "%w8u", (uint8_t)0);
+ SNPRINTF_TEST("255", "%w8u", (uint8_t)UCHAR_MAX);
+
+ SNPRINTF_TEST("0", "%w16d", (int16_t)0);
+ SNPRINTF_TEST("-32768", "%w16d", (int16_t)SHRT_MIN);
+ SNPRINTF_TEST("32767", "%w16d", (int16_t)SHRT_MAX);
+ SNPRINTF_TEST("0", "%w16u", (uint16_t)0);
+ SNPRINTF_TEST("65535", "%w16u", (uint16_t)USHRT_MAX);
+
+ SNPRINTF_TEST("0", "%w32d", (int32_t)0);
+ SNPRINTF_TEST("-2147483648", "%w32d", (int32_t)INT_MIN);
+ SNPRINTF_TEST("2147483647", "%w32d", (int32_t)INT_MAX);
+ SNPRINTF_TEST("0", "%w32u", (uint32_t)0);
+ SNPRINTF_TEST("4294967295", "%w32u", (uint32_t)UINT_MAX);
+
+ SNPRINTF_TEST("0", "%w64d", (int64_t)0);
+ SNPRINTF_TEST("-9223372036854775808", "%w64d", (int64_t)LLONG_MIN);
+ SNPRINTF_TEST("9223372036854775807", "%w64d", (int64_t)LLONG_MAX);
+ SNPRINTF_TEST("0", "%w64u", (uint64_t)0);
+ SNPRINTF_TEST("18446744073709551615", "%w64u", (uint64_t)ULLONG_MAX);
+
+ SNPRINTF_TEST("wd", "%wd", 0);
+ SNPRINTF_TEST("w1d", "%w1d", 0);
+ SNPRINTF_TEST("w128d", "%w128d", 0);
+}
+
+ATF_TC_WITHOUT_HEAD(snprintf_wfN);
+ATF_TC_BODY(snprintf_wfN, tc)
+{
+ SNPRINTF_TEST("0", "%wf8d", (int_fast8_t)0);
+ SNPRINTF_TEST("-2147483648", "%wf8d", (int_fast8_t)INT_MIN);
+ SNPRINTF_TEST("2147483647", "%wf8d", (int_fast8_t)INT_MAX);
+ SNPRINTF_TEST("0", "%wf8u", (uint8_t)0);
+ SNPRINTF_TEST("4294967295", "%wf8u", (uint_fast8_t)UINT_MAX);
+
+ SNPRINTF_TEST("0", "%wf16d", (int_fast16_t)0);
+ SNPRINTF_TEST("-2147483648", "%wf16d", (int_fast16_t)INT_MIN);
+ SNPRINTF_TEST("2147483647", "%wf16d", (int_fast16_t)INT_MAX);
+ SNPRINTF_TEST("0", "%wf16u", (uint16_t)0);
+ SNPRINTF_TEST("4294967295", "%wf16u", (uint_fast16_t)UINT_MAX);
+
+ SNPRINTF_TEST("0", "%wf32d", (int_fast32_t)0);
+ SNPRINTF_TEST("-2147483648", "%wf32d", (int_fast32_t)INT_MIN);
+ SNPRINTF_TEST("2147483647", "%wf32d", (int_fast32_t)INT_MAX);
+ SNPRINTF_TEST("0", "%wf32u", (uint32_t)0);
+ SNPRINTF_TEST("4294967295", "%wf32u", (uint_fast32_t)UINT_MAX);
+
+ SNPRINTF_TEST("0", "%wf64d", (int_fast64_t)0);
+ SNPRINTF_TEST("-9223372036854775808", "%wf64d", (int_fast64_t)LLONG_MIN);
+ SNPRINTF_TEST("9223372036854775807", "%wf64d", (int_fast64_t)LLONG_MAX);
+ SNPRINTF_TEST("0", "%wf64u", (uint64_t)0);
+ SNPRINTF_TEST("18446744073709551615", "%wf64u", (uint_fast64_t)ULLONG_MAX);
+
+ SNPRINTF_TEST("wfd", "%wfd", 0);
+ SNPRINTF_TEST("wf1d", "%wf1d", 0);
+ SNPRINTF_TEST("wf128d", "%wf128d", 0);
+}
+
ATF_TP_ADD_TCS(tp)
{
setlocale(LC_NUMERIC, "en_US.UTF-8");
@@ -134,5 +199,7 @@ ATF_TP_ADD_TCS(tp)
ATF_TP_ADD_TC(tp, snprintf_d);
ATF_TP_ADD_TC(tp, snprintf_x);
ATF_TP_ADD_TC(tp, snprintf_X);
+ ATF_TP_ADD_TC(tp, snprintf_wN);
+ ATF_TP_ADD_TC(tp, snprintf_wfN);
return (atf_no_error());
}
diff --git a/lib/libc/tests/stdio/sscanf_test.c b/lib/libc/tests/stdio/sscanf_test.c
index 462b4a6586da..e916873d38c3 100644
--- a/lib/libc/tests/stdio/sscanf_test.c
+++ b/lib/libc/tests/stdio/sscanf_test.c
@@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
+#include <limits.h>
#include <locale.h>
#include <stdint.h>
#include <stdio.h>
@@ -237,6 +238,68 @@ ATF_TC_BODY(sscanf_i, tc)
}
}
+ATF_TC_WITHOUT_HEAD(sscanf_wN);
+ATF_TC_BODY(sscanf_wN, tc)
+{
+ const char x00[] = "0x00";
+ const char x7f[] = "0x7fffffffffffffff";
+ const char xff[] = "0xffffffffffffffff";
+
+#define SSCANF_WN_TEST(N, imin, umax) \
+ do { \
+ int##N##_t i; \
+ uint##N##_t u; \
+ ATF_CHECK_EQ(1, sscanf(x00, "%w" #N "i", &i)); \
+ ATF_CHECK_EQ(0, i); \
+ ATF_CHECK_EQ(1, sscanf(x7f, "%w" #N "i", &i)); \
+ ATF_CHECK_EQ(imin, i); \
+ ATF_CHECK_EQ(1, sscanf(x00, "%w" #N "x", &u)); \
+ ATF_CHECK_EQ(0, u); \
+ ATF_CHECK_EQ(1, sscanf(xff, "%w" #N "x", &u)); \
+ ATF_CHECK_EQ(umax, u); \
+ } while (0)
+ SSCANF_WN_TEST(8, -1, UCHAR_MAX);
+ SSCANF_WN_TEST(16, -1, USHRT_MAX);
+ SSCANF_WN_TEST(32, -1, UINT_MAX);
+ SSCANF_WN_TEST(64, LLONG_MAX, ULLONG_MAX);
+#undef SSCANF_WN_TEST
+
+ ATF_CHECK_EQ(0, sscanf(x00, "%wi", (int *)NULL));
+ ATF_CHECK_EQ(0, sscanf(x00, "%w1i", (int *)NULL));
+ ATF_CHECK_EQ(0, sscanf(x00, "%w128i", (int *)NULL));
+}
+
+ATF_TC_WITHOUT_HEAD(sscanf_wfN);
+ATF_TC_BODY(sscanf_wfN, tc)
+{
+ const char x00[] = "0x00";
+ const char x7f[] = "0x7fffffffffffffff";
+ const char xff[] = "0xffffffffffffffff";
+
+#define SSCANF_WFN_TEST(N, imin, umax) \
+ do { \
+ int_fast##N##_t i; \
+ uint_fast##N##_t u; \
+ ATF_CHECK_EQ(1, sscanf(x00, "%wf" #N "i", &i)); \
+ ATF_CHECK_EQ(0, i); \
+ ATF_CHECK_EQ(1, sscanf(x7f, "%wf" #N "i", &i)); \
+ ATF_CHECK_EQ(imin, i); \
+ ATF_CHECK_EQ(1, sscanf(x00, "%wf" #N "x", &u)); \
+ ATF_CHECK_EQ(0, u); \
+ ATF_CHECK_EQ(1, sscanf(xff, "%wf" #N "x", &u)); \
+ ATF_CHECK_EQ(umax, u); \
+ } while (0)
+ SSCANF_WFN_TEST(8, -1, UINT_MAX);
+ SSCANF_WFN_TEST(16, -1, UINT_MAX);
+ SSCANF_WFN_TEST(32, -1, UINT_MAX);
+ SSCANF_WFN_TEST(64, LLONG_MAX, ULLONG_MAX);
+#undef SSCANF_WFN_TEST
+
+ ATF_CHECK_EQ(0, sscanf(x00, "%wfi", (int *)NULL));
+ ATF_CHECK_EQ(0, sscanf(x00, "%wf1i", (int *)NULL));
+ ATF_CHECK_EQ(0, sscanf(x00, "%wf128i", (int *)NULL));
+}
+
/*
* Test termination cases: non-numeric character, fixed width, EOF
*/
@@ -261,6 +324,8 @@ ATF_TP_ADD_TCS(tp)
ATF_TP_ADD_TC(tp, sscanf_d);
ATF_TP_ADD_TC(tp, sscanf_x);
ATF_TP_ADD_TC(tp, sscanf_i);
+ ATF_TP_ADD_TC(tp, sscanf_wN);
+ ATF_TP_ADD_TC(tp, sscanf_wfN);
ATF_TP_ADD_TC(tp, sscanf_termination);
return (atf_no_error());
}
diff --git a/lib/libc/tests/stdio/swprintf_test.c b/lib/libc/tests/stdio/swprintf_test.c
new file mode 100644
index 000000000000..f00ecc7f1c1d
--- /dev/null
+++ b/lib/libc/tests/stdio/swprintf_test.c
@@ -0,0 +1,206 @@
+/*-
+ * Copyright (c) 2023 Dag-Erling Smørgrav
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <assert.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <wchar.h>
+
+#include <atf-c.h>
+
+#ifndef nitems
+#define nitems(a) (sizeof(a) / sizeof(a[0]))
+#endif
+
+#define SWPRINTF_TEST(output, format, ...) \
+ do { \
+ wchar_t buf[256]; \
+ assert(wcslen(L##output) < nitems(buf)); \
+ int ret = swprintf(buf, nitems(buf), L##format, \
+ __VA_ARGS__); \
+ ATF_CHECK_EQ(wcslen(L##output), ret); \
+ if (ret > 0) { \
+ ATF_CHECK_EQ(0, wcscmp(L##output, buf)); \
+ } \
+ } while (0)
+
+ATF_TC_WITHOUT_HEAD(swprintf_b);
+ATF_TC_BODY(swprintf_b, tc)
+{
+ SWPRINTF_TEST("0", "%b", 0);
+ SWPRINTF_TEST(" 0", "%12b", 0);
+ SWPRINTF_TEST("000000000000", "%012b", 0);
+ SWPRINTF_TEST("1", "%b", 1);
+ SWPRINTF_TEST(" 1", "%12b", 1);
+ SWPRINTF_TEST("000000000001", "%012b", 1);
+ SWPRINTF_TEST("1111111111111111111111111111111", "%b", INT_MAX);
+ SWPRINTF_TEST("0", "%#b", 0);
+ SWPRINTF_TEST(" 0", "%#12b", 0);
+ SWPRINTF_TEST("000000000000", "%#012b", 0);
+ SWPRINTF_TEST("0b1", "%#b", 1);
+ SWPRINTF_TEST(" 0b1", "%#12b", 1);
+ SWPRINTF_TEST("0b0000000001", "%#012b", 1);
+ SWPRINTF_TEST("0b1111111111111111111111111111111", "%#b", INT_MAX);
+}
+
+ATF_TC_WITHOUT_HEAD(swprintf_B);
+ATF_TC_BODY(swprintf_B, tc)
+{
+ SWPRINTF_TEST("0", "%B", 0);
+ SWPRINTF_TEST(" 0", "%12B", 0);
+ SWPRINTF_TEST("000000000000", "%012B", 0);
+ SWPRINTF_TEST("1", "%B", 1);
+ SWPRINTF_TEST(" 1", "%12B", 1);
+ SWPRINTF_TEST("000000000001", "%012B", 1);
+ SWPRINTF_TEST("1111111111111111111111111111111", "%B", INT_MAX);
+ SWPRINTF_TEST("0", "%#B", 0);
+ SWPRINTF_TEST(" 0", "%#12B", 0);
+ SWPRINTF_TEST("000000000000", "%#012B", 0);
+ SWPRINTF_TEST("0B1", "%#B", 1);
+ SWPRINTF_TEST(" 0B1", "%#12B", 1);
+ SWPRINTF_TEST("0B0000000001", "%#012B", 1);
+ SWPRINTF_TEST("0B1111111111111111111111111111111", "%#B", INT_MAX);
+}
+
+ATF_TC_WITHOUT_HEAD(swprintf_d);
+ATF_TC_BODY(swprintf_d, tc)
+{
+ SWPRINTF_TEST("0", "%d", 0);
+ SWPRINTF_TEST(" 0", "%12d", 0);
+ SWPRINTF_TEST("000000000000", "%012d", 0);
+ SWPRINTF_TEST("1", "%d", 1);
+ SWPRINTF_TEST(" 1", "%12d", 1);
+ SWPRINTF_TEST("000000000001", "%012d", 1);
+ SWPRINTF_TEST("2147483647", "%d", INT_MAX);
+ SWPRINTF_TEST(" 2147483647", "%12d", INT_MAX);
+ SWPRINTF_TEST("002147483647", "%012d", INT_MAX);
+ SWPRINTF_TEST("2,147,483,647", "%'d", INT_MAX);
+}
+
+ATF_TC_WITHOUT_HEAD(swprintf_x);
+ATF_TC_BODY(swprintf_x, tc)
+{
+ SWPRINTF_TEST("0", "%x", 0);
+ SWPRINTF_TEST(" 0", "%12x", 0);
+ SWPRINTF_TEST("000000000000", "%012x", 0);
+ SWPRINTF_TEST("1", "%x", 1);
+ SWPRINTF_TEST(" 1", "%12x", 1);
+ SWPRINTF_TEST("000000000001", "%012x", 1);
+ SWPRINTF_TEST("7fffffff", "%x", INT_MAX);
+ SWPRINTF_TEST(" 7fffffff", "%12x", INT_MAX);
+ SWPRINTF_TEST("00007fffffff", "%012x", INT_MAX);
+ SWPRINTF_TEST("0", "%#x", 0);
+ SWPRINTF_TEST(" 0", "%#12x", 0);
+ SWPRINTF_TEST("000000000000", "%#012x", 0);
+ SWPRINTF_TEST("0x1", "%#x", 1);
+ SWPRINTF_TEST(" 0x1", "%#12x", 1);
+ SWPRINTF_TEST("0x0000000001", "%#012x", 1);
+ SWPRINTF_TEST("0x7fffffff", "%#x", INT_MAX);
+ SWPRINTF_TEST(" 0x7fffffff", "%#12x", INT_MAX);
+ SWPRINTF_TEST("0x007fffffff", "%#012x", INT_MAX);
+}
+
+ATF_TC_WITHOUT_HEAD(swprintf_X);
+ATF_TC_BODY(swprintf_X, tc)
+{
+ SWPRINTF_TEST("0", "%X", 0);
+ SWPRINTF_TEST(" 0", "%12X", 0);
+ SWPRINTF_TEST("000000000000", "%012X", 0);
+ SWPRINTF_TEST("1", "%X", 1);
+ SWPRINTF_TEST(" 1", "%12X", 1);
+ SWPRINTF_TEST("000000000001", "%012X", 1);
+ SWPRINTF_TEST("7FFFFFFF", "%X", INT_MAX);
+ SWPRINTF_TEST(" 7FFFFFFF", "%12X", INT_MAX);
+ SWPRINTF_TEST("00007FFFFFFF", "%012X", INT_MAX);
+ SWPRINTF_TEST("0", "%#X", 0);
+ SWPRINTF_TEST(" 0", "%#12X", 0);
+ SWPRINTF_TEST("000000000000", "%#012X", 0);
+ SWPRINTF_TEST("0X1", "%#X", 1);
+ SWPRINTF_TEST(" 0X1", "%#12X", 1);
+ SWPRINTF_TEST("0X0000000001", "%#012X", 1);
+ SWPRINTF_TEST("0X7FFFFFFF", "%#X", INT_MAX);
+ SWPRINTF_TEST(" 0X7FFFFFFF", "%#12X", INT_MAX);
+ SWPRINTF_TEST("0X007FFFFFFF", "%#012X", INT_MAX);
+}
+
+ATF_TC_WITHOUT_HEAD(swprintf_wN);
+ATF_TC_BODY(swprintf_wN, tc)
+{
+ SWPRINTF_TEST("0", "%w8d", (int8_t)0);
+ SWPRINTF_TEST("-128", "%w8d", (int8_t)SCHAR_MIN);
+ SWPRINTF_TEST("127", "%w8d", (int8_t)SCHAR_MAX);
+ SWPRINTF_TEST("0", "%w8u", (uint8_t)0);
+ SWPRINTF_TEST("255", "%w8u", (uint8_t)UCHAR_MAX);
+
+ SWPRINTF_TEST("0", "%w16d", (int16_t)0);
+ SWPRINTF_TEST("-32768", "%w16d", (int16_t)SHRT_MIN);
+ SWPRINTF_TEST("32767", "%w16d", (int16_t)SHRT_MAX);
+ SWPRINTF_TEST("0", "%w16u", (uint16_t)0);
+ SWPRINTF_TEST("65535", "%w16u", (uint16_t)USHRT_MAX);
+
+ SWPRINTF_TEST("0", "%w32d", (int32_t)0);
+ SWPRINTF_TEST("-2147483648", "%w32d", (int32_t)INT_MIN);
+ SWPRINTF_TEST("2147483647", "%w32d", (int32_t)INT_MAX);
+ SWPRINTF_TEST("0", "%w32u", (uint32_t)0);
+ SWPRINTF_TEST("4294967295", "%w32u", (uint32_t)UINT_MAX);
+
+ SWPRINTF_TEST("0", "%w64d", (int64_t)0);
+ SWPRINTF_TEST("-9223372036854775808", "%w64d", (int64_t)LLONG_MIN);
+ SWPRINTF_TEST("9223372036854775807", "%w64d", (int64_t)LLONG_MAX);
+ SWPRINTF_TEST("0", "%w64u", (uint64_t)0);
+ SWPRINTF_TEST("18446744073709551615", "%w64u", (uint64_t)ULLONG_MAX);
+
+ SWPRINTF_TEST("wd", "%wd", 0);
+ SWPRINTF_TEST("w1d", "%w1d", 0);
+ SWPRINTF_TEST("w128d", "%w128d", 0);
+}
+
+ATF_TC_WITHOUT_HEAD(swprintf_wfN);
+ATF_TC_BODY(swprintf_wfN, tc)
+{
+ SWPRINTF_TEST("0", "%wf8d", (int_fast8_t)0);
+ SWPRINTF_TEST("-2147483648", "%wf8d", (int_fast8_t)INT_MIN);
+ SWPRINTF_TEST("2147483647", "%wf8d", (int_fast8_t)INT_MAX);
+ SWPRINTF_TEST("0", "%wf8u", (uint8_t)0);
+ SWPRINTF_TEST("4294967295", "%wf8u", (uint_fast8_t)UINT_MAX);
+
+ SWPRINTF_TEST("0", "%wf16d", (int_fast16_t)0);
+ SWPRINTF_TEST("-2147483648", "%wf16d", (int_fast16_t)INT_MIN);
+ SWPRINTF_TEST("2147483647", "%wf16d", (int_fast16_t)INT_MAX);
+ SWPRINTF_TEST("0", "%wf16u", (uint16_t)0);
+ SWPRINTF_TEST("4294967295", "%wf16u", (uint_fast16_t)UINT_MAX);
+
+ SWPRINTF_TEST("0", "%wf32d", (int_fast32_t)0);
+ SWPRINTF_TEST("-2147483648", "%wf32d", (int_fast32_t)INT_MIN);
+ SWPRINTF_TEST("2147483647", "%wf32d", (int_fast32_t)INT_MAX);
+ SWPRINTF_TEST("0", "%wf32u", (uint32_t)0);
+ SWPRINTF_TEST("4294967295", "%wf32u", (uint_fast32_t)UINT_MAX);
+
+ SWPRINTF_TEST("0", "%wf64d", (int_fast64_t)0);
+ SWPRINTF_TEST("-9223372036854775808", "%wf64d", (int_fast64_t)LLONG_MIN);
+ SWPRINTF_TEST("9223372036854775807", "%wf64d", (int_fast64_t)LLONG_MAX);
+ SWPRINTF_TEST("0", "%wf64u", (uint64_t)0);
+ SWPRINTF_TEST("18446744073709551615", "%wf64u", (uint_fast64_t)ULLONG_MAX);
+
+ SWPRINTF_TEST("wfd", "%wfd", 0);
+ SWPRINTF_TEST("wf1d", "%wf1d", 0);
+ SWPRINTF_TEST("wf128d", "%wf128d", 0);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ setlocale(LC_NUMERIC, "en_US.UTF-8");
+ ATF_TP_ADD_TC(tp, swprintf_b);
+ ATF_TP_ADD_TC(tp, swprintf_B);
+ ATF_TP_ADD_TC(tp, swprintf_d);
+ ATF_TP_ADD_TC(tp, swprintf_x);
+ ATF_TP_ADD_TC(tp, swprintf_X);
+ ATF_TP_ADD_TC(tp, swprintf_wN);
+ ATF_TP_ADD_TC(tp, swprintf_wfN);
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/stdio/swscanf_test.c b/lib/libc/tests/stdio/swscanf_test.c
index 10eaf786e5fa..f7ad30b963a7 100644
--- a/lib/libc/tests/stdio/swscanf_test.c
+++ b/lib/libc/tests/stdio/swscanf_test.c
@@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
+#include <limits.h>
#include <locale.h>
#include <stdint.h>
#include <stdio.h>
@@ -11,6 +12,8 @@
#include <atf-c.h>
+#define L(s) L ## s
+
static const struct swscanf_test_case {
wchar_t input[8];
struct {
@@ -150,7 +153,7 @@ static const struct swscanf_test_case {
#define SWSCANF_TEST(string, format, expret, expval, explen) \
do { \
int ret = 0, val = 0, len = 0; \
- ret = swscanf(string, format "%n", &val, &len); \
+ ret = swscanf(string, format L"%n", &val, &len); \
ATF_CHECK_EQ(expret, ret); \
if (expret && ret) { \
ATF_CHECK_EQ(expval, val); \
@@ -238,6 +241,68 @@ ATF_TC_BODY(swscanf_i, tc)
}
}
+ATF_TC_WITHOUT_HEAD(swscanf_wN);
+ATF_TC_BODY(swscanf_wN, tc)
+{
+ const wchar_t x00[] = L"0x00";
+ const wchar_t x7f[] = L"0x7fffffffffffffff";
+ const wchar_t xff[] = L"0xffffffffffffffff";
+
+#define SWSCANF_WN_TEST(N, imin, umax) \
+ do { \
+ int##N##_t i; \
+ uint##N##_t u; \
+ ATF_CHECK_EQ(1, swscanf(x00, L"%w" L(#N) L"i", &i)); \
+ ATF_CHECK_EQ(0, i); \
+ ATF_CHECK_EQ(1, swscanf(x7f, L"%w" L(#N) L"i", &i)); \
+ ATF_CHECK_EQ(imin, i); \
+ ATF_CHECK_EQ(1, swscanf(x00, L"%w" L(#N) L"x", &u)); \
+ ATF_CHECK_EQ(0, u); \
+ ATF_CHECK_EQ(1, swscanf(xff, L"%w" L(#N) L"x", &u)); \
+ ATF_CHECK_EQ(umax, u); \
+ } while (0)
+ SWSCANF_WN_TEST(8, -1, UCHAR_MAX);
+ SWSCANF_WN_TEST(16, -1, USHRT_MAX);
+ SWSCANF_WN_TEST(32, -1, UINT_MAX);
+ SWSCANF_WN_TEST(64, LLONG_MAX, ULLONG_MAX);
+#undef SWSCANF_WN_TEST
+
+ ATF_CHECK_EQ(0, swscanf(x00, L"%wi", (int *)NULL));
+ ATF_CHECK_EQ(0, swscanf(x00, L"%w1i", (int *)NULL));
+ ATF_CHECK_EQ(0, swscanf(x00, L"%w128i", (int *)NULL));
+}
+
+ATF_TC_WITHOUT_HEAD(swscanf_wfN);
+ATF_TC_BODY(swscanf_wfN, tc)
+{
+ const wchar_t x00[] = L"0x00";
+ const wchar_t x7f[] = L"0x7fffffffffffffff";
+ const wchar_t xff[] = L"0xffffffffffffffff";
+
+#define SWSCANF_WFN_TEST(N, imin, umax) \
+ do { \
+ int_fast##N##_t i; \
+ uint_fast##N##_t u; \
+ ATF_CHECK_EQ(1, swscanf(x00, L"%wf" L(#N) L"i", &i)); \
+ ATF_CHECK_EQ(0, i); \
+ ATF_CHECK_EQ(1, swscanf(x7f, L"%wf" L(#N) L"i", &i)); \
+ ATF_CHECK_EQ(imin, i); \
+ ATF_CHECK_EQ(1, swscanf(x00, L"%wf" L(#N) L"x", &u)); \
+ ATF_CHECK_EQ(0, u); \
+ ATF_CHECK_EQ(1, swscanf(xff, L"%wf" L(#N) L"x", &u)); \
+ ATF_CHECK_EQ(umax, u); \
+ } while (0)
+ SWSCANF_WFN_TEST(8, -1, UINT_MAX);
+ SWSCANF_WFN_TEST(16, -1, UINT_MAX);
+ SWSCANF_WFN_TEST(32, -1, UINT_MAX);
+ SWSCANF_WFN_TEST(64, LLONG_MAX, ULLONG_MAX);
+#undef SWSCANF_WFN_TEST
+
+ ATF_CHECK_EQ(0, swscanf(x00, L"%wfi", (int *)NULL));
+ ATF_CHECK_EQ(0, swscanf(x00, L"%wf1i", (int *)NULL));
+ ATF_CHECK_EQ(0, swscanf(x00, L"%wf128i", (int *)NULL));
+}
+
/*
* Test termination cases: non-numeric character, fixed width, EOF
*/
@@ -245,9 +310,9 @@ ATF_TC_WITHOUT_HEAD(swscanf_termination);
ATF_TC_BODY(swscanf_termination, tc)
{
int a = 0, b = 0, c = 0;
- char d = 0;
+ wchar_t d = 0;
- ATF_CHECK_EQ(4, swscanf(L"3.1415", L"%d%c%2d%d", &a, &d, &b, &c));
+ ATF_CHECK_EQ(4, swscanf(L"3.1415", L"%d%lc%2d%d", &a, &d, &b, &c));
ATF_CHECK_EQ(3, a);
ATF_CHECK_EQ(14, b);
ATF_CHECK_EQ(15, c);
@@ -262,6 +327,8 @@ ATF_TP_ADD_TCS(tp)
ATF_TP_ADD_TC(tp, swscanf_d);
ATF_TP_ADD_TC(tp, swscanf_x);
ATF_TP_ADD_TC(tp, swscanf_i);
+ ATF_TP_ADD_TC(tp, swscanf_wN);
+ ATF_TP_ADD_TC(tp, swscanf_wfN);
ATF_TP_ADD_TC(tp, swscanf_termination);
return (atf_no_error());
}