From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: AS22989 209.51.188.0/24 X-Spam-Status: No, score=-3.8 required=3.0 tests=AWL,BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI,RCVD_IN_MSPIKE_H2,SPF_HELO_PASS,SPF_PASS shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dcvr.yhbt.net (Postfix) with ESMTPS id ECC451F47C for ; Sat, 28 Jan 2023 18:10:23 +0000 (UTC) Authentication-Results: dcvr.yhbt.net; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=clisp.org header.i=@clisp.org header.a=rsa-sha256 header.s=strato-dkim-0002 header.b=DthTx545; dkim-atps=neutral Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pLpeP-0006TG-00; Sat, 28 Jan 2023 13:10:05 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pLpeN-0006Sx-0q for bug-gnulib@gnu.org; Sat, 28 Jan 2023 13:10:03 -0500 Received: from mo4-p00-ob.smtp.rzone.de ([85.215.255.23]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pLpeK-0006MD-7W for bug-gnulib@gnu.org; Sat, 28 Jan 2023 13:10:02 -0500 ARC-Seal: i=1; a=rsa-sha256; t=1674929397; cv=none; d=strato.com; s=strato-dkim-0002; b=boapH+ZwfCBElOszzUmxKmSjKOFhRiOwOCzru/49qfCkyIwo8MQzN69PPtuc73kilG NscF2T3IYOlbH/iuWrc/5uDbV7E7eW53gROlUYBJ21jrqg8x1yGhL+J8L/IYHiKHavkx +lpl3vbA6h8P9EY4SyJpG0NB5EmSZFCWXYq0YNwXqlmzOJV4uZL/7sba75BIZ2Dr99pf NK3Qhn2E4qUrF9skQqABkDWHa6SWhHxe2nN8MLELpP5bFDZUg/fVC+dTMPX1OIBs5WS2 3tPuZwu78m4gQSuytSN3GvNB/SUkXEd5PhXG8Okm91AOP4wTq7nphl9Rj0lbE8blxZWg 8VMw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; t=1674929397; s=strato-dkim-0002; d=strato.com; h=Message-ID:Date:Subject:To:From:Cc:Date:From:Subject:Sender; bh=1p6uO4XtSu/PcReqrqlDyPNelo0sbIYk4UdEdCpZj84=; b=OZlVfCvygX6GAqGl53YRb4L5qHASr2VxYfw27RhHzIgft+EWJaLw4yUSj/hPcHACWq 0hqSB8A0xuKCsgN0tlsQpkF+bxsJhLz6QKovJMw5dCs05yquGVA9wrIC6zCpnUtEDPbs lOK+EBTBvWZQ7zxI9ioIXL2R7qL+UzUX3/4fCBiUmgs4+EXYQS3YGwrVlWMKb2thfgG2 8HfZxbal9vHg+JBJLSzKeyZ4BCVD88lD/jUH8/AX+x/B3RQY/J6dkcV0s8CF6X8aa9Vq NSgdEejSxlbh57rDaV1yLr2/Lox4/rqL29OMmS2o0+BqIjMFvDVsRQEpzJWRRBtZBIM/ iM2Q== ARC-Authentication-Results: i=1; strato.com; arc=none; dkim=none X-RZG-CLASS-ID: mo00 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; t=1674929397; s=strato-dkim-0002; d=clisp.org; h=Message-ID:Date:Subject:To:From:Cc:Date:From:Subject:Sender; bh=1p6uO4XtSu/PcReqrqlDyPNelo0sbIYk4UdEdCpZj84=; b=DthTx545mBhgj24fi+bC3k71qFhxW5CTtCP033ZtrYijVtqfhDFBJoK3Y0ZgpPYDAT 4dDwZjHVKAvQsqWY0+0u3brfO+tQuAyOM/Y6DbyQXYT69MaBT5FkpPqekwkrB1w4btwK qp1ILNEHBp15Y/D2a5VI2i0oG/LCHdPr1nx5Eszh0s/y9l3DfNqispGW2bnmelQ2lwZn yxU4rz45jaInARSUsW1BTyy4xtVjSZTNpu7HPcFUg8tO+9pXso8yo6SyEeUv3lkY/8l7 vVuZ4aAR4EVBT7fvqrnaY2MPddcPQmbJIr0mAtFvV1M62M0R+UMDcQUDq9dgSlBpKSim PSDw== X-RZG-AUTH: ":Ln4Re0+Ic/6oZXR1YgKryK8brlshOcZlIWs+iCP5vnk6shH0WWb0LN8XZoH94zq68+3cfpPDjvwA7022TV+YfjovfFy3RIl4" Received: from nimes.localnet by smtp.strato.de (RZmta 49.2.2 AUTH) with ESMTPSA id 098542z0SI9vNYs (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256 bits)) (Client did not present a certificate); Sat, 28 Jan 2023 19:09:57 +0100 (CET) From: Bruno Haible To: bug-gnulib@gnu.org Subject: vasnprintf-posix: Fix possible bug with negative width handling for %lc Date: Sat, 28 Jan 2023 19:09:56 +0100 Message-ID: <2682333.6tenTkhIk7@nimes> MIME-Version: 1.0 Content-Transfer-Encoding: 7Bit Content-Type: text/plain; charset="us-ascii" Received-SPF: none client-ip=85.215.255.23; envelope-from=bruno@clisp.org; helo=mo4-p00-ob.smtp.rzone.de X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_PASS=-0.001, SPF_NONE=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: bug-gnulib@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gnulib discussion list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnulib-bounces+normalperson=yhbt.net@gnu.org Sender: bug-gnulib-bounces+normalperson=yhbt.net@gnu.org 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 . So let me fix that as well, and add corresponding unit tests. 2023-01-28 Bruno Haible 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 , 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 #include #include +#include #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 #include #include +#include #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 #include #include +#include #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 #include #include +#include #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