* vasnprintf-posix: Fix negative width handling for %ls directive
@ 2023-01-28 17:54 Bruno Haible
0 siblings, 0 replies; only message in thread
From: Bruno Haible @ 2023-01-28 17:54 UTC (permalink / raw)
To: bug-gnulib
When I
1. add some unit tests for width given as argument,
2. create a testdir for the modules
vasnprintf-posix vasprintf-posix snprintf-posix sprintf-posix
3. build this testdir on one of these platforms:
- Solaris 11.4
- Solaris 9
- MSVC 14
- a glibc system with the environment variable settings
gl_cv_func_snprintf_retval_c99=no gl_cv_func_printf_directive_ls=no
I get a test failure in each of the corresponding tests.
The cause is that FLAG_LEFT is set in the 'flags' variable, but the code
is looking for it in 'dp->flags'.
2023-01-28 Bruno Haible <bruno@clisp.org>
vasnprintf-posix: Fix negative width handling for %ls directive.
Reported by clang via Po Lu <luangruo@yahoo.com>.
* lib/vasnprintf.c (VASNPRINTF): In the code for %ls in vasnprintf and
for %s in vasnwprintf, test for the FLAG_LEFT bit in the flags variable.
* tests/test-vasnprintf-posix.c (test_function): Add tests for width
given as argument for the directives %s, %ls.
* tests/test-vasprintf-posix.c (test_function): Likewise.
* tests/test-snprintf-posix.h (test_function): Likewise.
* tests/test-sprintf-posix.h (test_function): Likewise.
diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c
index 277c39e3e0..5ab8edbab7 100644
--- a/lib/vasnprintf.c
+++ b/lib/vasnprintf.c
@@ -2551,7 +2551,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
characters = 0;
}
- if (characters < width && !(dp->flags & FLAG_LEFT))
+ if (characters < width && !(flags & FLAG_LEFT))
{
size_t n = width - characters;
ENSURE_ALLOCATION (xsum (length, n));
@@ -2612,7 +2612,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
}
}
- if (characters < width && (dp->flags & FLAG_LEFT))
+ if (characters < width && (flags & FLAG_LEFT))
{
size_t n = width - characters;
ENSURE_ALLOCATION (xsum (length, n));
@@ -2768,7 +2768,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
/* w doesn't matter. */
w = 0;
- if (w < width && !(dp->flags & FLAG_LEFT))
+ if (w < width && !(flags & FLAG_LEFT))
{
size_t n = width - w;
ENSURE_ALLOCATION (xsum (length, n));
@@ -2836,7 +2836,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
length += tmpdst_len;
# endif
- if (w < width && (dp->flags & FLAG_LEFT))
+ if (w < width && (flags & FLAG_LEFT))
{
size_t n = width - w;
ENSURE_ALLOCATION (xsum (length, n));
diff --git a/tests/test-snprintf-posix.h b/tests/test-snprintf-posix.h
index 42662a498e..e5c1d3f89d 100644
--- a/tests/test-snprintf-posix.h
+++ b/tests/test-snprintf-posix.h
@@ -2886,6 +2886,66 @@ test_function (int (*my_snprintf) (char *, size_t, const char *, ...))
/* Test the support of the %s format directive. */
+ { /* Width. */
+ int retval =
+ my_snprintf (result, sizeof (result), "%10s %d", "xyz", 33, 44, 55);
+ ASSERT (strcmp (result, " xyz 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+
+ { /* Width given as argument. */
+ int retval =
+ my_snprintf (result, sizeof (result), "%*s %d", 10, "xyz", 33, 44, 55);
+ ASSERT (strcmp (result, " xyz 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+
+ { /* Negative width given as argument (cf. FLAG_LEFT below). */
+ int retval =
+ my_snprintf (result, sizeof (result), "%*s %d", -10, "xyz", 33, 44, 55);
+ ASSERT (strcmp (result, "xyz 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+
+ { /* FLAG_LEFT. */
+ int retval =
+ my_snprintf (result, sizeof (result), "%-10s %d", "xyz", 33, 44, 55);
+ ASSERT (strcmp (result, "xyz 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+
+#if HAVE_WCHAR_T
+ static wchar_t L_xyz[4] = { 'x', 'y', 'z', 0 };
+
+ { /* Width. */
+ int retval =
+ my_snprintf (result, sizeof (result), "%10ls %d", L_xyz, 33, 44, 55);
+ ASSERT (strcmp (result, " xyz 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+
+ { /* Width given as argument. */
+ int retval =
+ my_snprintf (result, sizeof (result), "%*ls %d", 10, L_xyz, 33, 44, 55);
+ ASSERT (strcmp (result, " xyz 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+
+ { /* Negative width given as argument (cf. FLAG_LEFT below). */
+ int retval =
+ my_snprintf (result, sizeof (result), "%*ls %d", -10, L_xyz, 33, 44, 55);
+ ASSERT (strcmp (result, "xyz 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+
+ { /* FLAG_LEFT. */
+ int retval =
+ my_snprintf (result, sizeof (result), "%-10ls %d", L_xyz, 33, 44, 55);
+ ASSERT (strcmp (result, "xyz 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+#endif
+
/* To verify that these tests succeed, it is necessary to run them under
a tool that checks against invalid memory accesses, such as ElectricFence
or "valgrind --tool=memcheck". */
diff --git a/tests/test-sprintf-posix.h b/tests/test-sprintf-posix.h
index 3b54cabd64..011df3b46a 100644
--- a/tests/test-sprintf-posix.h
+++ b/tests/test-sprintf-posix.h
@@ -2872,6 +2872,66 @@ test_function (int (*my_sprintf) (char *, const char *, ...))
/* Test the support of the %s format directive. */
+ { /* Width. */
+ int retval =
+ my_sprintf (result, "%10s %d", "xyz", 33, 44, 55);
+ ASSERT (strcmp (result, " xyz 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+
+ { /* Width given as argument. */
+ int retval =
+ my_sprintf (result, "%*s %d", 10, "xyz", 33, 44, 55);
+ ASSERT (strcmp (result, " xyz 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+
+ { /* Negative width given as argument (cf. FLAG_LEFT below). */
+ int retval =
+ my_sprintf (result, "%*s %d", -10, "xyz", 33, 44, 55);
+ ASSERT (strcmp (result, "xyz 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+
+ { /* FLAG_LEFT. */
+ int retval =
+ my_sprintf (result, "%-10s %d", "xyz", 33, 44, 55);
+ ASSERT (strcmp (result, "xyz 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+
+#if HAVE_WCHAR_T
+ static wchar_t L_xyz[4] = { 'x', 'y', 'z', 0 };
+
+ { /* Width. */
+ int retval =
+ my_sprintf (result, "%10ls %d", L_xyz, 33, 44, 55);
+ ASSERT (strcmp (result, " xyz 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+
+ { /* Width given as argument. */
+ int retval =
+ my_sprintf (result, "%*ls %d", 10, L_xyz, 33, 44, 55);
+ ASSERT (strcmp (result, " xyz 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+
+ { /* Negative width given as argument (cf. FLAG_LEFT below). */
+ int retval =
+ my_sprintf (result, "%*ls %d", -10, L_xyz, 33, 44, 55);
+ ASSERT (strcmp (result, "xyz 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+
+ { /* FLAG_LEFT. */
+ int retval =
+ my_sprintf (result, "%-10ls %d", L_xyz, 33, 44, 55);
+ ASSERT (strcmp (result, "xyz 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+#endif
+
/* To verify that these tests succeed, it is necessary to run them under
a tool that checks against invalid memory accesses, such as ElectricFence
or "valgrind --tool=memcheck". */
diff --git a/tests/test-vasnprintf-posix.c b/tests/test-vasnprintf-posix.c
index 6c81c7c5f4..93d2bc5a38 100644
--- a/tests/test-vasnprintf-posix.c
+++ b/tests/test-vasnprintf-posix.c
@@ -3711,6 +3711,90 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...))
/* Test the support of the %s format directive. */
+ { /* Width. */
+ size_t length;
+ char *result =
+ my_asnprintf (NULL, &length, "%10s %d", "xyz", 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, " xyz 33") == 0);
+ ASSERT (length == strlen (result));
+ free (result);
+ }
+
+ { /* Width given as argument. */
+ size_t length;
+ char *result =
+ my_asnprintf (NULL, &length, "%*s %d", 10, "xyz", 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, " xyz 33") == 0);
+ ASSERT (length == strlen (result));
+ free (result);
+ }
+
+ { /* Negative width given as argument (cf. FLAG_LEFT below). */
+ size_t length;
+ char *result =
+ my_asnprintf (NULL, &length, "%*s %d", -10, "xyz", 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, "xyz 33") == 0);
+ ASSERT (length == strlen (result));
+ free (result);
+ }
+
+ { /* FLAG_LEFT. */
+ size_t length;
+ char *result =
+ my_asnprintf (NULL, &length, "%-10s %d", "xyz", 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, "xyz 33") == 0);
+ ASSERT (length == strlen (result));
+ free (result);
+ }
+
+#if HAVE_WCHAR_T
+ static wchar_t L_xyz[4] = { 'x', 'y', 'z', 0 };
+
+ { /* Width. */
+ size_t length;
+ char *result =
+ my_asnprintf (NULL, &length, "%10ls %d", L_xyz, 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, " xyz 33") == 0);
+ ASSERT (length == strlen (result));
+ free (result);
+ }
+
+ { /* Width given as argument. */
+ size_t length;
+ char *result =
+ my_asnprintf (NULL, &length, "%*ls %d", 10, L_xyz, 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, " xyz 33") == 0);
+ ASSERT (length == strlen (result));
+ free (result);
+ }
+
+ { /* Negative width given as argument (cf. FLAG_LEFT below). */
+ size_t length;
+ char *result =
+ my_asnprintf (NULL, &length, "%*ls %d", -10, L_xyz, 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, "xyz 33") == 0);
+ ASSERT (length == strlen (result));
+ free (result);
+ }
+
+ { /* FLAG_LEFT. */
+ size_t length;
+ char *result =
+ my_asnprintf (NULL, &length, "%-10ls %d", L_xyz, 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, "xyz 33") == 0);
+ ASSERT (length == strlen (result));
+ free (result);
+ }
+#endif
+
/* To verify that these tests succeed, it is necessary to run them under
a tool that checks against invalid memory accesses, such as ElectricFence
or "valgrind --tool=memcheck". */
diff --git a/tests/test-vasprintf-posix.c b/tests/test-vasprintf-posix.c
index 5bef8d4a2a..3bfc18bb75 100644
--- a/tests/test-vasprintf-posix.c
+++ b/tests/test-vasprintf-posix.c
@@ -3696,6 +3696,90 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
/* Test the support of the %s format directive. */
+ { /* Width. */
+ char *result;
+ int retval =
+ my_asprintf (&result, "%10s %d", "xyz", 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, " xyz 33") == 0);
+ ASSERT (retval == strlen (result));
+ free (result);
+ }
+
+ { /* Width given as argument. */
+ char *result;
+ int retval =
+ my_asprintf (&result, "%*s %d", 10, "xyz", 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, " xyz 33") == 0);
+ ASSERT (retval == strlen (result));
+ free (result);
+ }
+
+ { /* Negative width given as argument (cf. FLAG_LEFT below). */
+ char *result;
+ int retval =
+ my_asprintf (&result, "%*s %d", -10, "xyz", 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, "xyz 33") == 0);
+ ASSERT (retval == strlen (result));
+ free (result);
+ }
+
+ { /* FLAG_LEFT. */
+ char *result;
+ int retval =
+ my_asprintf (&result, "%-10s %d", "xyz", 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, "xyz 33") == 0);
+ ASSERT (retval == strlen (result));
+ free (result);
+ }
+
+#if HAVE_WCHAR_T
+ static wchar_t L_xyz[4] = { 'x', 'y', 'z', 0 };
+
+ { /* Width. */
+ char *result;
+ int retval =
+ my_asprintf (&result, "%10ls %d", L_xyz, 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, " xyz 33") == 0);
+ ASSERT (retval == strlen (result));
+ free (result);
+ }
+
+ { /* Width given as argument. */
+ char *result;
+ int retval =
+ my_asprintf (&result, "%*ls %d", 10, L_xyz, 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, " xyz 33") == 0);
+ ASSERT (retval == strlen (result));
+ free (result);
+ }
+
+ { /* Negative width given as argument (cf. FLAG_LEFT below). */
+ char *result;
+ int retval =
+ my_asprintf (&result, "%*ls %d", -10, L_xyz, 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, "xyz 33") == 0);
+ ASSERT (retval == strlen (result));
+ free (result);
+ }
+
+ { /* FLAG_LEFT. */
+ char *result;
+ int retval =
+ my_asprintf (&result, "%-10ls %d", L_xyz, 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, "xyz 33") == 0);
+ ASSERT (retval == strlen (result));
+ free (result);
+ }
+#endif
+
/* To verify that these tests succeed, it is necessary to run them under
a tool that checks against invalid memory accesses, such as ElectricFence
or "valgrind --tool=memcheck". */
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2023-01-28 17:54 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-01-28 17:54 vasnprintf-posix: Fix negative width handling for %ls directive Bruno Haible
Code repositories for project(s) associated with this public inbox
https://public-inbox.org/mirrors/gnulib.git/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).