From 572d2511a00bb6a608517c4975ee7ad693218c61 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Thu, 20 Jun 2024 03:24:18 +0200 Subject: [PATCH] vasnprintf, u*-asnprintf tests: Add test of huge %ls arguments. * tests/test-vasnprintf-big.c: Include . (main): Add tests for wide string arguments with > 2^31 wide characters. * tests/unistdio/test-u8-asnprintf-big.c: Include . (main): Add tests for wide string arguments with > 2^31 wide characters. * tests/unistdio/test-ulc-asnprintf-big.c: Include . (main): Add tests for wide string arguments with > 2^31 wide characters. --- ChangeLog | 8 +++ tests/test-vasnprintf-big.c | 92 +++++++++++++++++++++--- tests/unistdio/test-u8-asnprintf-big.c | 92 +++++++++++++++++++++--- tests/unistdio/test-ulc-asnprintf-big.c | 93 ++++++++++++++++++++++--- 4 files changed, 261 insertions(+), 24 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4b9485f6c7..1c156b791e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,13 @@ 2024-06-19 Bruno Haible + vasnprintf, u*-asnprintf tests: Add test of huge %ls arguments. + * tests/test-vasnprintf-big.c: Include . + (main): Add tests for wide string arguments with > 2^31 wide characters. + * tests/unistdio/test-u8-asnprintf-big.c: Include . + (main): Add tests for wide string arguments with > 2^31 wide characters. + * tests/unistdio/test-ulc-asnprintf-big.c: Include . + (main): Add tests for wide string arguments with > 2^31 wide characters. + vasnprintf, u*-vasnprintf: Support huge wide string arguments. * lib/vasnprintf.c: (VASNPRINTF): In 64-bit builds, handle the %ls directive ourselves. diff --git a/tests/test-vasnprintf-big.c b/tests/test-vasnprintf-big.c index 65b4dc3f7c..eae1d2704d 100644 --- a/tests/test-vasnprintf-big.c +++ b/tests/test-vasnprintf-big.c @@ -31,6 +31,7 @@ #include #include #include +#include #if HAVE_SETRLIMIT # include @@ -54,14 +55,16 @@ main () rl.rlim_cur = rl.rlim_max = 0; setrlimit (RLIMIT_CORE, &rl); # endif - /* The test below needs about 10 GiB of memory: + /* The test below needs about 25 GiB of memory: $ time /usr/bin/time -f "Max RSS: %M KiB" ./test-vasnprintf-big - Max RSS: 10487464 KiB - real 0m34,417s - user 0m26,175s - sys 0m8,240s - 5 GiB for the inputs and up to 5 GiB for temporary output buffers. */ - double needed = 10.0 * 1024 * 1024 * 1024; + Max RSS: 26216128 KiB + real 3m54,169s + user 3m33,309s + sys 0m20,819s + 5 GiB for the inputs in the %s tests, + or 20 GiB for the inputs in the %ls tests, + and up to 5 GiB for temporary output buffers. */ + double needed = 25.0 * 1024 * 1024 * 1024; double avail = physmem_claimable (1.0); printf ("memory needed = %g MiB, available = %g MiB\n", needed / 1024 / 1024, avail / 1024 / 1024); @@ -69,7 +72,7 @@ main () { /* Note: The malloc() calls can fail, due to ulimit of RLIMIT_DATA. For example, on OpenBSD 7.5, the soft limit is 1.0 GiB or 1.5 GiB, - and you need "ulimit -d 15728640". */ + and you need "ulimit -d 27262976". */ /* Verify that asnprintf() can return a string of size > 4 GiB. */ { @@ -189,6 +192,79 @@ main () } } } + + /* Verify that asnprintf() can take a wide string with an element count + > 2^31, < 2^32 as argument. */ + { + size_t n1 = 3 * (size_t) (INT_MAX / 2) + 10; + wchar_t *s1; + + s1 = (wchar_t *) malloc ((n1 + 1) * sizeof (wchar_t)); + if (s1 != NULL) + { + wmemset (s1, L'a', n1); + s1[n1] = L'\0'; + + size_t len; + char *s = asnprintf (NULL, &len, "x%lsy", s1); + if (s == NULL) + { + ASSERT (errno == ENOMEM); + skipped = true; + } + else + { + ASSERT (strlen (s) == len); + ASSERT (len == n1 + 2); + size_t i; + for (i = 0; i <= len; i++) + s[i] = (i == 0 ? 'x' : + i <= n1 ? 'a' : + i == n1 + 1 ? 'y' : + '\0'); + free (s); + } + free (s1); + } + } + + /* Verify that asnprintf() can take a wide string with an element count + > 2^32 as argument. */ + { + size_t n1 = 5 * (size_t) (INT_MAX / 2) + 10; + if (n1 > (size_t) INT_MAX) + { + wchar_t *s1; + + s1 = (wchar_t *) malloc ((n1 + 1) * sizeof (wchar_t)); + if (s1 != NULL) + { + wmemset (s1, L'a', n1); + s1[n1] = L'\0'; + + size_t len; + char *s = asnprintf (NULL, &len, "x%lsy", s1); + if (s == NULL) + { + ASSERT (errno == ENOMEM); + skipped = true; + } + else + { + ASSERT (strlen (s) == len); + ASSERT (len == n1 + 2); + size_t i; + for (i = 0; i <= len; i++) + s[i] = (i == 0 ? 'x' : + i <= n1 ? 'a' : + i == n1 + 1 ? 'y' : + '\0'); + free (s); + } + free (s1); + } + } + } } else skipped = true; diff --git a/tests/unistdio/test-u8-asnprintf-big.c b/tests/unistdio/test-u8-asnprintf-big.c index 6b7cced5ce..1a5b46d098 100644 --- a/tests/unistdio/test-u8-asnprintf-big.c +++ b/tests/unistdio/test-u8-asnprintf-big.c @@ -32,6 +32,7 @@ #include #include #include +#include #if HAVE_SETRLIMIT # include @@ -55,14 +56,16 @@ main () rl.rlim_cur = rl.rlim_max = 0; setrlimit (RLIMIT_CORE, &rl); # endif - /* The test below needs about 15 GiB of memory: + /* The test below needs about 30 GiB of memory: $ time /usr/bin/time -f "Max RSS: %M KiB" ./test-u8-asnprintf-big - Max RSS: 15730356 KiB - real 0m58,011s - user 0m46,403s - sys 0m11,604s - 5 GiB for the inputs and up to 10 GiB for temporary output buffers. */ - double needed = 15.0 * 1024 * 1024 * 1024; + Max RSS: 31459148 KiB + real 6m57,851s + user 6m28,413s + sys 0m29,382s + 5 GiB for the inputs in the %s tests, + or 20 GiB for the inputs in the %ls tests, + and up to 10 GiB for temporary output buffers. */ + double needed = 30.0 * 1024 * 1024 * 1024; double avail = physmem_claimable (1.0); printf ("memory needed = %g MiB, available = %g MiB\n", needed / 1024 / 1024, avail / 1024 / 1024); @@ -70,7 +73,7 @@ main () { /* Note: The malloc() calls can fail, due to ulimit of RLIMIT_DATA. For example, on OpenBSD 7.5, the soft limit is 1.0 GiB or 1.5 GiB, - and you need "ulimit -d 15728640". */ + and you need "ulimit -d 32505856". */ /* Verify that u8_asnprintf() can return a string of size > 4 GiB. */ { @@ -190,6 +193,79 @@ main () } } } + + /* Verify that u8_asnprintf() can take a wide string with an element count + > 2^31, < 2^32 as argument. */ + { + size_t n1 = 3 * (size_t) (INT_MAX / 2) + 10; + wchar_t *s1; + + s1 = (wchar_t *) malloc ((n1 + 1) * sizeof (wchar_t)); + if (s1 != NULL) + { + wmemset (s1, L'a', n1); + s1[n1] = L'\0'; + + size_t len; + uint8_t *s = u8_asnprintf (NULL, &len, "x%lsy", s1); + if (s == NULL) + { + ASSERT (errno == ENOMEM); + skipped = true; + } + else + { + ASSERT (u8_strlen (s) == len); + ASSERT (len == n1 + 2); + size_t i; + for (i = 0; i <= len; i++) + s[i] = (i == 0 ? 'x' : + i <= n1 ? 'a' : + i == n1 + 1 ? 'y' : + '\0'); + free (s); + } + free (s1); + } + } + + /* Verify that u8_asnprintf() can take a wide string with an element count + > 2^32 as argument. */ + { + size_t n1 = 5 * (size_t) (INT_MAX / 2) + 10; + if (n1 > (size_t) INT_MAX) + { + wchar_t *s1; + + s1 = (wchar_t *) malloc ((n1 + 1) * sizeof (wchar_t)); + if (s1 != NULL) + { + wmemset (s1, L'a', n1); + s1[n1] = L'\0'; + + size_t len; + uint8_t *s = u8_asnprintf (NULL, &len, "x%lsy", s1); + if (s == NULL) + { + ASSERT (errno == ENOMEM); + skipped = true; + } + else + { + ASSERT (u8_strlen (s) == len); + ASSERT (len == n1 + 2); + size_t i; + for (i = 0; i <= len; i++) + s[i] = (i == 0 ? 'x' : + i <= n1 ? 'a' : + i == n1 + 1 ? 'y' : + '\0'); + free (s); + } + free (s1); + } + } + } } else skipped = true; diff --git a/tests/unistdio/test-ulc-asnprintf-big.c b/tests/unistdio/test-ulc-asnprintf-big.c index 8ef733d962..fcb8799684 100644 --- a/tests/unistdio/test-ulc-asnprintf-big.c +++ b/tests/unistdio/test-ulc-asnprintf-big.c @@ -31,6 +31,7 @@ #include #include #include +#include #if HAVE_SETRLIMIT # include @@ -54,14 +55,17 @@ main () rl.rlim_cur = rl.rlim_max = 0; setrlimit (RLIMIT_CORE, &rl); # endif - /* The test below needs about 15 GiB of memory: + /* The test below needs about 25 GiB of memory: $ time /usr/bin/time -f "Max RSS: %M KiB" ./test-ulc-asnprintf-big - Max RSS: 15730376 KiB - real 1m13,702s - user 1m0,184s - sys 0m13,512s - 5 GiB for the inputs and up to 10 GiB for temporary output buffers. */ - double needed = 15.0 * 1024 * 1024 * 1024; + Max RSS: 26216192 KiB + real 4m34,682s + user 4m8,592s + sys 0m26,063s + - In the %s tests: + 5 GiB for the inputs and up to 10 GiB for temporary output buffers. + - In the %ls tests: + 20 GiB for the inputs and up to 5 GiB for temporary output buffers. */ + double needed = 25.0 * 1024 * 1024 * 1024; double avail = physmem_claimable (1.0); printf ("memory needed = %g MiB, available = %g MiB\n", needed / 1024 / 1024, avail / 1024 / 1024); @@ -69,7 +73,7 @@ main () { /* Note: The malloc() calls can fail, due to ulimit of RLIMIT_DATA. For example, on OpenBSD 7.5, the soft limit is 1.0 GiB or 1.5 GiB, - and you need "ulimit -d 15728640". */ + and you need "ulimit -d 27262976". */ /* Verify that ulc_asnprintf() can return a string of size > 4 GiB. */ { @@ -243,6 +247,79 @@ main () } } } + + /* Verify that ulc_asnprintf() can take a wide string with an element count + > 2^31, < 2^32 as argument. */ + { + size_t n1 = 3 * (size_t) (INT_MAX / 2) + 10; + wchar_t *s1; + + s1 = (wchar_t *) malloc ((n1 + 1) * sizeof (wchar_t)); + if (s1 != NULL) + { + wmemset (s1, L'a', n1); + s1[n1] = L'\0'; + + size_t len; + char *s = ulc_asnprintf (NULL, &len, "x%lsy", s1); + if (s == NULL) + { + ASSERT (errno == ENOMEM); + skipped = true; + } + else + { + ASSERT (strlen (s) == len); + ASSERT (len == n1 + 2); + size_t i; + for (i = 0; i <= len; i++) + s[i] = (i == 0 ? 'x' : + i <= n1 ? 'a' : + i == n1 + 1 ? 'y' : + '\0'); + free (s); + } + free (s1); + } + } + + /* Verify that ulc_asnprintf() can take a wide string with an element count + > 2^32 as argument. */ + { + size_t n1 = 5 * (size_t) (INT_MAX / 2) + 10; + if (n1 > (size_t) INT_MAX) + { + wchar_t *s1; + + s1 = (wchar_t *) malloc ((n1 + 1) * sizeof (wchar_t)); + if (s1 != NULL) + { + wmemset (s1, L'a', n1); + s1[n1] = L'\0'; + + size_t len; + char *s = ulc_asnprintf (NULL, &len, "x%lsy", s1); + if (s == NULL) + { + ASSERT (errno == ENOMEM); + skipped = true; + } + else + { + ASSERT (strlen (s) == len); + ASSERT (len == n1 + 2); + size_t i; + for (i = 0; i <= len; i++) + s[i] = (i == 0 ? 'x' : + i <= n1 ? 'a' : + i == n1 + 1 ? 'y' : + '\0'); + free (s); + } + free (s1); + } + } + } } else skipped = true; -- 2.39.5