diff options
Diffstat (limited to 'lib/libc/tests/stdio')
-rw-r--r-- | lib/libc/tests/stdio/Makefile | 11 | ||||
-rw-r--r-- | lib/libc/tests/stdio/fdopen_test.c | 1 | ||||
-rw-r--r-- | lib/libc/tests/stdio/flushlbuf_test.c | 155 | ||||
-rw-r--r-- | lib/libc/tests/stdio/fmemopen2_test.c | 34 | ||||
-rw-r--r-- | lib/libc/tests/stdio/fopen_test.c | 1 | ||||
-rw-r--r-- | lib/libc/tests/stdio/freopen_test.c | 1 | ||||
-rw-r--r-- | lib/libc/tests/stdio/getdelim_test.c | 1 | ||||
-rw-r--r-- | lib/libc/tests/stdio/gets_s_test.c | 1 | ||||
-rw-r--r-- | lib/libc/tests/stdio/mkostemp_test.c | 1 | ||||
-rw-r--r-- | lib/libc/tests/stdio/open_memstream2_test.c | 1 | ||||
-rw-r--r-- | lib/libc/tests/stdio/open_wmemstream_test.c | 1 | ||||
-rw-r--r-- | lib/libc/tests/stdio/perror_test.c | 1 | ||||
-rw-r--r-- | lib/libc/tests/stdio/print_positional_test.c | 1 | ||||
-rw-r--r-- | lib/libc/tests/stdio/printbasic_test.c | 1 | ||||
-rw-r--r-- | lib/libc/tests/stdio/printfloat_test.c | 1 | ||||
-rw-r--r-- | lib/libc/tests/stdio/scanfloat_test.c | 137 | ||||
-rw-r--r-- | lib/libc/tests/stdio/snprintf_test.c | 87 | ||||
-rw-r--r-- | lib/libc/tests/stdio/sscanf_test.c | 65 | ||||
-rw-r--r-- | lib/libc/tests/stdio/swprintf_test.c | 206 | ||||
-rw-r--r-- | lib/libc/tests/stdio/swscanf_test.c | 73 |
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()); } |