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.
+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.
+
2023-01-28 Bruno Haible <bruno@clisp.org>
vasnprintf-posix: Add more unit tests.
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));
}
}
- if (characters < width && (dp->flags & FLAG_LEFT))
+ if (characters < width && (flags & FLAG_LEFT))
{
size_t n = width - characters;
ENSURE_ALLOCATION (xsum (length, n));
/* 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));
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));
/* 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". */
/* 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". */
/* 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". */
/* 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". */