From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from re-prd-fep-048.btinternet.com (mailomta23-re.btinternet.com [213.120.69.116]) by sourceware.org (Postfix) with ESMTPS id 7989D3858D28 for ; Mon, 3 Jul 2023 14:49:08 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 7989D3858D28 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=dronecode.org.uk Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=dronecode.org.uk Received: from re-prd-rgout-002.btmx-prd.synchronoss.net ([10.2.54.5]) by re-prd-fep-048.btinternet.com with ESMTP id <20230703144906.CXDA17945.re-prd-fep-048.btinternet.com@re-prd-rgout-002.btmx-prd.synchronoss.net> for ; Mon, 3 Jul 2023 15:49:06 +0100 Authentication-Results: btinternet.com; auth=pass (PLAIN) smtp.auth=jonturney@btinternet.com; bimi=skipped X-SNCR-Rigid: 63FE976D0E51060B X-Originating-IP: [86.140.193.60] X-OWM-Source-IP: 86.140.193.60 (GB) X-OWM-Env-Sender: jonturney@btinternet.com X-VadeSecure-score: verdict=clean score=0/300, class=clean X-RazorGate-Vade: gggruggvucftvghtrhhoucdtuddrgedviedruddvgdejlecutefuodetggdotefrodftvfcurfhrohhfihhlvgemuceutffkvffkuffjvffgnffgvefqofdpqfgfvfenuceurghilhhouhhtmecufedtudenucenucfjughrpefkffggfgfuvfhfhfgjtgfgsehtjeertddtfeejnecuhfhrohhmpeflohhnucfvuhhrnhgvhicuoehjohhnrdhtuhhrnhgvhiesughrohhnvggtohguvgdrohhrghdruhhkqeenucggtffrrghtthgvrhhnpeffkeeigfdujeehteduiefgjeeltdelgeelteekudetfedtffefhfeufefgueettdenucfkphepkeeirddugedtrdduleefrdeitdenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhephhgvlhhopegludelvddrudeikedruddruddtiegnpdhinhgvthepkeeirddugedtrdduleefrdeitddpmhgrihhlfhhrohhmpehjohhnrdhtuhhrnhgvhiesughrohhnvggtohguvgdrohhrghdruhhkpdhnsggprhgtphhtthhopedupdhrtghpthhtohepnhgvfihlihgssehsohhurhgtvgifrghrvgdrohhrghdprhgvvhfkrfephhhoshhtkeeiqddugedtqdduleefqdeitddrrhgrnhhgvgekiedqudegtddrsghttggvnhhtrhgrlhhplhhushdrtghomhdprghuthhhpghushgvrhepjhhonhhtuhhrnhgvhiessghtihhnthgvrhhnvghtrdgtohhmpdhgvghokffrpefiuedpoffvtefjohhstheprhgvqdhprhguqdhrghhouhhtqddttddv X-RazorGate-Vade-Verdict: clean 0 X-RazorGate-Vade-Classification: clean Received: from [192.168.1.106] (86.140.193.60) by re-prd-rgout-002.btmx-prd.synchronoss.net (5.8.814) (authenticated as jonturney@btinternet.com) id 63FE976D0E51060B for newlib@sourceware.org; Mon, 3 Jul 2023 15:49:06 +0100 Message-ID: Date: Mon, 3 Jul 2023 15:49:05 +0100 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Thunderbird/102.12.0 Subject: Re: bug with printf positional arguments? Content-Language: en-GB To: "newlib@sourceware.org" References: From: Jon Turney In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,JMQ_SPF_NEUTRAL,KAM_DMARC_STATUS,NICE_REPLY_A,RCVD_IN_DNSWL_NONE,SPF_HELO_PASS,SPF_PASS,TXREP,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: On 03/07/2023 12:14, Corinna Vinschen wrote: > On Jun 28 14:28, Jon Turney wrote: >> >> The following trivial program (extracted from a glib testcase) >> >>> #include >>> >>> int main() >>> { >>> printf ("%1$*2$.*3$s", "abc", 5, 2); >>> } >> >> does not produce the expected output of " ab", on 64-bit Cygwin. >> >> From a bit of staring at and stepping through get_args() in >> libc/stdio/vfprintf.c, it looks like the problem is (something like) we >> don't have the knowledge that the first positional variadic argument should >> be treated as a pointer, at the point that we store it's value, so it gets >> treated as an integer (the default), which is going to lead to truncation on >> LP64 platforms. >> >> A straightforward way to fix this eludes me. > > Can you point out where in the code this problem occurs, so maybe > we can discuss the necessary code changes in this thread? Sure, I'll try: Let's suppose you're executing the STC above. This is what I think happens... We end up in _vprintf_r. We hit line 1072, which digests the '1', and on the following '$', knows to interpret this as a positional argument and stores it. The subsequent '*' is processed at line 967 as introducing the width, where we chomp the '2', which again the following '$' indicates should be treated as a positional arg. We hit GET_ARG for the first time, to retrieve the width, which invokes get_arg() to do the work (as we haven't yet stored the requested arg in args[]). get_arg() digests the format string (again) using a state machine (to populate args[] with the positional parameters) The state machine moves through START (action NUMBER) -> WDIG (action GETPOS) -> DONE. Stopping here looks like maybe an error in the state machine design? The loop starting at line 2310 iterates over the seen args, fetching their values. Because we haven't processed the 's' at the end in the GETARG state, we retrieve the first argument using the default case, as an integer (32 bits, truncating the 64-bit pointer value) (it looks like we're maybe also lucking out on handling the width properly, as we're never hitting the PWPOS state to record that it should be treated as an INT).