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 1DEBD1F47C for ; Sat, 28 Jan 2023 17:54:14 +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=VGsqaZRh; dkim-atps=neutral Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pLpOw-0002qr-NL; Sat, 28 Jan 2023 12:54:06 -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 1pLpOv-0002qU-M4 for bug-gnulib@gnu.org; Sat, 28 Jan 2023 12:54:05 -0500 Received: from mo4-p00-ob.smtp.rzone.de ([85.215.255.20]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pLpOt-00040j-Di for bug-gnulib@gnu.org; Sat, 28 Jan 2023 12:54:05 -0500 ARC-Seal: i=1; a=rsa-sha256; t=1674928441; cv=none; d=strato.com; s=strato-dkim-0002; b=bz3sK1a/DroskTORDIAvSTYZ6qVEF8sAkGpKCYL/WdRlcz7cybZq9r2OsKETpGsWMK WypveZk5tY6Z832yOUHfJvZ8ZneNlLUYnOzaiA2tNrff/yreUM78y5t0w18d3wi0KrDu pq4vC2DbTucvmEHOQUhc5ZpXkKqoLBmHeu33KEN+fwrB6sLM5Q2tXCs4Rud+MRw6u6WS 5s7MGT44wMuJXmHR/L0x2eHGDqsyhe13DNk6K7w9fLEXTq2qP5k6JYF7gz/uWqUc7Nm4 DTHOrJegO52rpLY2dF1QUtiFZpQWBoEKCfcmBlJZnvKQ3OB8y4lHeeKthauJ/8zrWmGI 4GPg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; t=1674928441; s=strato-dkim-0002; d=strato.com; h=Message-ID:Date:Subject:To:From:Cc:Date:From:Subject:Sender; bh=mkM6HqhO5FzQB24RnhZINvpxZ5pA9qGfQP0UAuizNio=; b=CD9XuBUxZz5whkXmUZktRugF8ukmyaAKK6TNCdVS2WP9s1CcQrHqAFikBxTIZh+bBM Bbg6x1+jjU+BaW9ndmAM4BT4yJ9YvDmhmkI+qCnEDGfkjxn+ygS8f2bBAnej62kVNR/j ev8PMaf5N8RhYhQs0a98RIpr8fokrmLd/XDELfFQFlrQJcPfW4yS2gcL94Hgr00PvBB5 tWA8O7PvBX4b+E/XUGY5Vvh3L3v6+Ryy4zPVRDViuOVtwLS2RmF340TljOC4txNWztqM 1qaGqbwPetYenYEofK/NTds0k3aekG1/4FK6SGBPf/3vxuUK7D9lsqu9/M4rPukT5dJm YUgA== 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=1674928441; s=strato-dkim-0002; d=clisp.org; h=Message-ID:Date:Subject:To:From:Cc:Date:From:Subject:Sender; bh=mkM6HqhO5FzQB24RnhZINvpxZ5pA9qGfQP0UAuizNio=; b=VGsqaZRhVjDV8KtCwbPrwkecgaFzZRfkRgIQDG3nkFb+n6cK1ekzGWtVxVQ+PL0JZo vWGxdzUkNyJbo9YTrGo5nqDJ+TbR1VIw8AC3zbYpKoOMNPid1TNe5RrXwGkZjbbgmmyg 5/Iy9Ajk5xWepAw+04f5RvIzTNifbNQCawUXThVKrDISPsuFYzNMMpf0+Kkr+qX4Y5hW +twduB9U+JtnvpGPilNT+8kWctNyg0MLi4yijNoU5KVMPlMEE6y9QGMivRI7dqdICnTS 6upe+36KCavdEh/AfVR14h4DcKpS+HfZtU2HHDuRlnXlt5NiGpt/NvYWVcFrNHu3ZoKa 9RiA== 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 098542z0SHs1NXr (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256 bits)) (Client did not present a certificate); Sat, 28 Jan 2023 18:54:01 +0100 (CET) From: Bruno Haible To: bug-gnulib@gnu.org Subject: vasnprintf-posix: Fix negative width handling for %ls directive Date: Sat, 28 Jan 2023 18:54:01 +0100 Message-ID: <3003231.vvmviz7Nmq@nimes> MIME-Version: 1.0 Content-Transfer-Encoding: 7Bit Content-Type: text/plain; charset="us-ascii" Received-SPF: none client-ip=85.215.255.20; 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 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 vasnprintf-posix: Fix negative width handling for %ls directive. Reported by clang via Po Lu . * 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". */