From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 7871) id 9A9EC3858C36; Tue, 3 Jan 2023 09:34:24 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9A9EC3858C36 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1672738464; bh=3rBZXx2DLG/KkOLHJCtbj6uBVW5LmMjDgMn+IIpN3Oo=; h=From:To:Subject:Date:From; b=klk3DwMY0w45bKskIddaYdYFeIzKoHxB3Wm5RxqGToykkPWsw5cSe7Cd8xwNQC3p/ pqhijwFs0NNXWSJa3qeewIYyBDjl0zYAtE7m9fU6ALWHgGscqSsatUdWH6FgdFu9jP bHOVVk7DHN3VYk3S4byHf+GMUcitPXciiQe95K1w= MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Marc Poulhi?s To: gcc-cvs@gcc.gnu.org Subject: [gcc r13-4968] ada: Fix format string parsing in GNAT.Formatted_String X-Act-Checkin: gcc X-Git-Author: Ronan Desplanques X-Git-Refname: refs/heads/master X-Git-Oldrev: 32841e7e8480cb16d34f60feda226e4f582c3186 X-Git-Newrev: d3f50f75aa3e5054b28074c029d36c1cbce2d0cb Message-Id: <20230103093424.9A9EC3858C36@sourceware.org> Date: Tue, 3 Jan 2023 09:34:24 +0000 (GMT) List-Id: https://gcc.gnu.org/g:d3f50f75aa3e5054b28074c029d36c1cbce2d0cb commit r13-4968-gd3f50f75aa3e5054b28074c029d36c1cbce2d0cb Author: Ronan Desplanques Date: Wed Dec 7 17:37:21 2022 +0100 ada: Fix format string parsing in GNAT.Formatted_String Before this patch, format strings ending with "%%" (two consecutive percent signs) caused GNAT.Formatted_String."-" to give the wrong output, and cause the various GNAT.Formatted_String."&" to raise exceptions with misleading error messages. Also before this patch, a bug in GNAT.Formatted_String."-" caused characters from the format string to be dropped. Calling GNAT.Formatted_String."-" on an instance of GNAT.Formatted_String.Formatted_String caused subsequent uses of that instance to return wrong results. In addition to fixing the parsing of format strings, this patch centralizes the detection of format specifiers in a unique procedure. gcc/ada/ * libgnat/g-forstr.adb (Advance_And_Accumulate_Until_Next_Specifier): New procedure. ("-"): Replace inline code with call to Advance_And_Accumulate_Until_Next_Specifier. (Next_Format): likewise. Diff: --- gcc/ada/libgnat/g-forstr.adb | 67 ++++++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/gcc/ada/libgnat/g-forstr.adb b/gcc/ada/libgnat/g-forstr.adb index 8821de6f280..8353e2c4ad8 100644 --- a/gcc/ada/libgnat/g-forstr.adb +++ b/gcc/ada/libgnat/g-forstr.adb @@ -77,6 +77,12 @@ package body GNAT.Formatted_String is Value_Needed : Natural range 0 .. 2 := 0; end record; + procedure Advance_And_Accumulate_Until_Next_Specifier + (Format : Formatted_String); + -- Advance Format.D.Index until either the next format specifier is + -- encountered, or the end of Format.D.Format is reached. The characters + -- advanced over are appended to Format.D.Result. + procedure Next_Format (Format : Formatted_String; F_Spec : out F_Data; @@ -139,29 +145,13 @@ package body GNAT.Formatted_String is --------- function "-" (Format : Formatted_String) return String is - F : String renames Format.D.Format; - J : Natural renames Format.D.Index; - R : Unbounded_String := Format.D.Result; - begin -- Make sure we get the remaining character up to the next unhandled -- format specifier. - while (J <= F'Length and then F (J) /= '%') - or else (J < F'Length - 1 and then F (J + 1) = '%') - loop - Append (R, F (J)); - - -- If we have two consecutive %, skip the second one - - if F (J) = '%' and then J < F'Length - 1 and then F (J + 1) = '%' then - J := J + 1; - end if; - - J := J + 1; - end loop; + Advance_And_Accumulate_Until_Next_Specifier (Format); - return To_String (R); + return To_String (Format.D.Result); end "-"; --------- @@ -318,6 +308,33 @@ package body GNAT.Formatted_String is F.D.Ref_Count := F.D.Ref_Count + 1; end Adjust; + ------------------------------------------------- + -- Advance_And_Accumulate_Until_Next_Specifier -- + ------------------------------------------------- + + procedure Advance_And_Accumulate_Until_Next_Specifier + (Format : Formatted_String) + is + begin + loop + if Format.D.Index > Format.D.Format'Last then + exit; + end if; + + if Format.D.Format (Format.D.Index) /= '%' then + Append (Format.D.Result, Format.D.Format (Format.D.Index)); + Format.D.Index := Format.D.Index + 1; + elsif Format.D.Index + 1 <= Format.D.Format'Last + and then Format.D.Format (Format.D.Index + 1) = '%' + then + Append (Format.D.Result, '%'); + Format.D.Index := Format.D.Index + 2; + else + exit; + end if; + end loop; + end Advance_And_Accumulate_Until_Next_Specifier; + -------------------- -- Decimal_Format -- -------------------- @@ -505,19 +522,7 @@ package body GNAT.Formatted_String is -- Got to next % - while (J <= F'Last and then F (J) /= '%') - or else (J < F'Last - 1 and then F (J + 1) = '%') - loop - Append (Format.D.Result, F (J)); - - -- If we have two consecutive %, skip the second one - - if F (J) = '%' and then J < F'Last - 1 and then F (J + 1) = '%' then - J := J + 1; - end if; - - J := J + 1; - end loop; + Advance_And_Accumulate_Until_Next_Specifier (Format); if J >= F'Last or else F (J) /= '%' then raise Format_Error with "no format specifier found for parameter"