* vasnprintf-posix: Fix possible bug with negative width handling for %lc
@ 2023-01-28 18:09 Bruno Haible
0 siblings, 0 replies; only message in thread
From: Bruno Haible @ 2023-01-28 18:09 UTC (permalink / raw)
To: bug-gnulib
vasnprintf.c can be compiled with -DENABLE_WCHAR_FALLBACK. Currently this
option is not used by any package. But if some package was to use it, it
would see the same bug as just fixed in
<https://lists.gnu.org/archive/html/bug-gnulib/2023-01/msg00231.html>.
So let me fix that as well, and add corresponding unit tests.
2023-01-28 Bruno Haible <bruno@clisp.org>
vasnprintf-posix: Fix possible bug with negative width handling for %lc.
* lib/vasnprintf.c (VASNPRINTF): In the code for %lc in vasnprintf, 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 %c, %lc.
* tests/test-vasprintf-posix.c (test_function): Likewise.
* tests/test-snprintf-posix.h (test_function): Likewise.
* tests/test-sprintf-posix.h (test_function): Likewise.
* tests/test-snprintf-posix.c: Include <wchar.h>, for wint_t.
* tests/test-sprintf-posix.c: Likewise.
diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c
index 5ab8edbab7..0e6220ae18 100644
--- a/lib/vasnprintf.c
+++ b/lib/vasnprintf.c
@@ -2977,7 +2977,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));
@@ -3033,7 +3033,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.c b/tests/test-snprintf-posix.c
index d8d89fcd05..3dec989d7b 100644
--- a/tests/test-snprintf-posix.c
+++ b/tests/test-snprintf-posix.c
@@ -25,6 +25,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <wchar.h>
#include "macros.h"
diff --git a/tests/test-snprintf-posix.h b/tests/test-snprintf-posix.h
index e5c1d3f89d..4db76deb75 100644
--- a/tests/test-snprintf-posix.h
+++ b/tests/test-snprintf-posix.h
@@ -2987,4 +2987,70 @@ test_function (int (*my_snprintf) (char *, size_t, const char *, ...))
}
}
#endif
+
+ /* Test the support of the %c format directive. */
+
+ { /* Width. */
+ int retval =
+ my_snprintf (result, sizeof (result),
+ "%10c %d", (unsigned char) 'x', 33, 44, 55);
+ ASSERT (strcmp (result, " x 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+
+ { /* Width given as argument. */
+ int retval =
+ my_snprintf (result, sizeof (result),
+ "%*c %d", 10, (unsigned char) 'x', 33, 44, 55);
+ ASSERT (strcmp (result, " x 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+
+ { /* Negative width given as argument (cf. FLAG_LEFT below). */
+ int retval =
+ my_snprintf (result, sizeof (result),
+ "%*c %d", -10, (unsigned char) 'x', 33, 44, 55);
+ ASSERT (strcmp (result, "x 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+
+ { /* FLAG_LEFT. */
+ int retval =
+ my_snprintf (result, sizeof (result),
+ "%-10c %d", (unsigned char) 'x', 33, 44, 55);
+ ASSERT (strcmp (result, "x 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+
+#if HAVE_WCHAR_T
+ static wint_t L_x = (wchar_t) 'x';
+
+ { /* Width. */
+ int retval =
+ my_snprintf (result, sizeof (result), "%10lc %d", L_x, 33, 44, 55);
+ ASSERT (strcmp (result, " x 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+
+ { /* Width given as argument. */
+ int retval =
+ my_snprintf (result, sizeof (result), "%*lc %d", 10, L_x, 33, 44, 55);
+ ASSERT (strcmp (result, " x 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+
+ { /* Negative width given as argument (cf. FLAG_LEFT below). */
+ int retval =
+ my_snprintf (result, sizeof (result), "%*lc %d", -10, L_x, 33, 44, 55);
+ ASSERT (strcmp (result, "x 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+
+ { /* FLAG_LEFT. */
+ int retval =
+ my_snprintf (result, sizeof (result), "%-10lc %d", L_x, 33, 44, 55);
+ ASSERT (strcmp (result, "x 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+#endif
}
diff --git a/tests/test-sprintf-posix.c b/tests/test-sprintf-posix.c
index 9404a6fc99..54c951c72c 100644
--- a/tests/test-sprintf-posix.c
+++ b/tests/test-sprintf-posix.c
@@ -28,6 +28,7 @@ SIGNATURE_CHECK (sprintf, int, (char *, char const *, ...));
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <wchar.h>
#include "macros.h"
diff --git a/tests/test-sprintf-posix.h b/tests/test-sprintf-posix.h
index 011df3b46a..979254acc7 100644
--- a/tests/test-sprintf-posix.h
+++ b/tests/test-sprintf-posix.h
@@ -2973,4 +2973,66 @@ test_function (int (*my_sprintf) (char *, const char *, ...))
}
}
#endif
+
+ /* Test the support of the %c format directive. */
+
+ { /* Width. */
+ int retval =
+ my_sprintf (result, "%10c %d", (unsigned char) 'x', 33, 44, 55);
+ ASSERT (strcmp (result, " x 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+
+ { /* Width given as argument. */
+ int retval =
+ my_sprintf (result, "%*c %d", 10, (unsigned char) 'x', 33, 44, 55);
+ ASSERT (strcmp (result, " x 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+
+ { /* Negative width given as argument (cf. FLAG_LEFT below). */
+ int retval =
+ my_sprintf (result, "%*c %d", -10, (unsigned char) 'x', 33, 44, 55);
+ ASSERT (strcmp (result, "x 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+
+ { /* FLAG_LEFT. */
+ int retval =
+ my_sprintf (result, "%-10c %d", (unsigned char) 'x', 33, 44, 55);
+ ASSERT (strcmp (result, "x 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+
+#if HAVE_WCHAR_T
+ static wint_t L_x = (wchar_t) 'x';
+
+ { /* Width. */
+ int retval =
+ my_sprintf (result, "%10lc %d", L_x, 33, 44, 55);
+ ASSERT (strcmp (result, " x 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+
+ { /* Width given as argument. */
+ int retval =
+ my_sprintf (result, "%*lc %d", 10, L_x, 33, 44, 55);
+ ASSERT (strcmp (result, " x 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+
+ { /* Negative width given as argument (cf. FLAG_LEFT below). */
+ int retval =
+ my_sprintf (result, "%*lc %d", -10, L_x, 33, 44, 55);
+ ASSERT (strcmp (result, "x 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+
+ { /* FLAG_LEFT. */
+ int retval =
+ my_sprintf (result, "%-10lc %d", L_x, 33, 44, 55);
+ ASSERT (strcmp (result, "x 33") == 0);
+ ASSERT (retval == strlen (result));
+ }
+#endif
}
diff --git a/tests/test-vasnprintf-posix.c b/tests/test-vasnprintf-posix.c
index 93d2bc5a38..4a83f6d243 100644
--- a/tests/test-vasnprintf-posix.c
+++ b/tests/test-vasnprintf-posix.c
@@ -27,6 +27,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <wchar.h>
#include "macros.h"
#include "minus-zero.h"
@@ -3883,6 +3884,96 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...))
}
#endif
+ /* Test the support of the %c format directive. */
+
+ { /* Width. */
+ size_t length;
+ char *result =
+ my_asnprintf (NULL, &length,
+ "%10c %d", (unsigned char) 'x', 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, " x 33") == 0);
+ ASSERT (length == strlen (result));
+ free (result);
+ }
+
+ { /* Width given as argument. */
+ size_t length;
+ char *result =
+ my_asnprintf (NULL, &length,
+ "%*c %d", 10, (unsigned char) 'x', 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, " x 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,
+ "%*c %d", -10, (unsigned char) 'x', 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, "x 33") == 0);
+ ASSERT (length == strlen (result));
+ free (result);
+ }
+
+ { /* FLAG_LEFT. */
+ size_t length;
+ char *result =
+ my_asnprintf (NULL, &length,
+ "%-10c %d", (unsigned char) 'x', 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, "x 33") == 0);
+ ASSERT (length == strlen (result));
+ free (result);
+ }
+
+#if HAVE_WCHAR_T
+ static wint_t L_x = (wchar_t) 'x';
+
+ { /* Width. */
+ size_t length;
+ char *result =
+ my_asnprintf (NULL, &length, "%10lc %d", L_x, 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, " x 33") == 0);
+ ASSERT (length == strlen (result));
+ free (result);
+ }
+
+ { /* Width given as argument. */
+ size_t length;
+ char *result =
+ my_asnprintf (NULL, &length, "%*lc %d", 10, L_x, 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, " x 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, "%*lc %d", -10, L_x, 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, "x 33") == 0);
+ ASSERT (length == strlen (result));
+ free (result);
+ }
+
+ { /* FLAG_LEFT. */
+ size_t length;
+ char *result =
+ my_asnprintf (NULL, &length, "%-10lc %d", L_x, 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, "x 33") == 0);
+ ASSERT (length == strlen (result));
+ free (result);
+ }
+#endif
+
#if (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)) && !defined __UCLIBC__
/* Test that the 'I' flag is supported. */
{
diff --git a/tests/test-vasprintf-posix.c b/tests/test-vasprintf-posix.c
index 3bfc18bb75..8563502c47 100644
--- a/tests/test-vasprintf-posix.c
+++ b/tests/test-vasprintf-posix.c
@@ -26,6 +26,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <wchar.h>
#include "macros.h"
#include "minus-zero.h"
@@ -3827,6 +3828,92 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
}
}
#endif
+
+ /* Test the support of the %c format directive. */
+
+ { /* Width. */
+ char *result;
+ int retval =
+ my_asprintf (&result, "%10c %d", (unsigned char) 'x', 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, " x 33") == 0);
+ ASSERT (retval == strlen (result));
+ free (result);
+ }
+
+ { /* Width given as argument. */
+ char *result;
+ int retval =
+ my_asprintf (&result, "%*c %d", 10, (unsigned char) 'x', 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, " x 33") == 0);
+ ASSERT (retval == strlen (result));
+ free (result);
+ }
+
+ { /* Negative width given as argument (cf. FLAG_LEFT below). */
+ char *result;
+ int retval =
+ my_asprintf (&result, "%*c %d", -10, (unsigned char) 'x', 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, "x 33") == 0);
+ ASSERT (retval == strlen (result));
+ free (result);
+ }
+
+ { /* FLAG_LEFT. */
+ char *result;
+ int retval =
+ my_asprintf (&result, "%-10c %d", (unsigned char) 'x', 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, "x 33") == 0);
+ ASSERT (retval == strlen (result));
+ free (result);
+ }
+
+#if HAVE_WCHAR_T
+ static wint_t L_x = (wchar_t) 'x';
+
+ { /* Width. */
+ char *result;
+ int retval =
+ my_asprintf (&result, "%10lc %d", L_x, 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, " x 33") == 0);
+ ASSERT (retval == strlen (result));
+ free (result);
+ }
+
+ { /* Width given as argument. */
+ char *result;
+ int retval =
+ my_asprintf (&result, "%*lc %d", 10, L_x, 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, " x 33") == 0);
+ ASSERT (retval == strlen (result));
+ free (result);
+ }
+
+ { /* Negative width given as argument (cf. FLAG_LEFT below). */
+ char *result;
+ int retval =
+ my_asprintf (&result, "%*lc %d", -10, L_x, 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, "x 33") == 0);
+ ASSERT (retval == strlen (result));
+ free (result);
+ }
+
+ { /* FLAG_LEFT. */
+ char *result;
+ int retval =
+ my_asprintf (&result, "%-10lc %d", L_x, 33, 44, 55);
+ ASSERT (result != NULL);
+ ASSERT (strcmp (result, "x 33") == 0);
+ ASSERT (retval == strlen (result));
+ free (result);
+ }
+#endif
}
static int
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2023-01-28 18:10 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-01-28 18:09 vasnprintf-posix: Fix possible bug with negative width handling for %lc 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).