mailing list of musl libc
 help / color / mirror / code / Atom feed
From: Rich Felker <dalias@libc.org>
To: Bruno Haible <bruno@clisp.org>
Cc: musl@lists.openwall.com
Subject: Re: [musl] swprintf: count returned by %n is wrong after conversion error
Date: Mon, 20 Mar 2023 08:15:59 -0400	[thread overview]
Message-ID: <20230320121559.GQ4163@brightrain.aerifal.cx> (raw)
In-Reply-To: <4620016.0WQXIW03uk@nimes>

On Mon, Mar 20, 2023 at 12:48:59AM +0100, Bruno Haible wrote:
> Hi,
> 
> On musl-1.2.3 I see this violation of the POSIX specification of swprintf [1]:
> 
> ==================================== foo1.c ====================================
> #include <stdio.h>
> #include <wchar.h>
> 
> int main ()
> {
>   static const wchar_t input[] = { (wchar_t) 1702057263, 114, 0 };
>   wchar_t buf[12] = { 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF };
>   int count = -1;
>   int ret = swprintf (buf, 12, L"%ls%n", input, &count);
>   printf ("ret = %d, count = %d, buf[0] = 0x%x, buf[1] = 0x%x, buf[2] = 0x%x\n",
>           ret, count,
>           (unsigned int) buf[0], (unsigned int) buf[1], (unsigned int) buf[2]);
>   return 0;
> }
> /*
> glibc:      ret = 2, count = 2, buf[0] = 0x6573552f, buf[1] = 0x72, buf[2] = 0x0
> musl libc:  ret = -1, count = 2, buf[0] = 0x0, buf[1] = 0xdeadbeef, buf[2] = 0xdeadbeef
> FreeBSD 13: ret = -1, count = -1, buf[0] = 0x0, buf[1] = 0xdeadbeef, buf[2] = 0xdeadbeef
> Solaris OI: ret = 2, count = 2, buf[0] = 0x6573552f, buf[1] = 0x72, buf[2] = 0x0
> */
> ================================================================================
> 
> $ gcc -Wall foo1.c
> $ ./a.out
> ret = -1, count = 2, buf[0] = 0x0, buf[1] = 0xdeadbeef, buf[2] = 0xdeadbeef
> 
> The POSIX specification says:
>   "The application shall ensure that the argument is a pointer to an integer
>    into which is written the number of wide characters written to the output
>    so far by this call to one of the fwprintf() functions."
> 
> From the values of buf[0], buf[1], buf[2] it can be seen that the number
> of wide characters written after the %ls directive is 0, not 2. Therefore
> the value of count should be 0 or — if the processing of the format string
> stops right after the %ls directive, like it does on FreeBSD 13 — -1.
> 
> It is OK for the %ls directive to fail, because of the invalid wide characters
> in the input[] arrary. What is not OK is for the %n directive to report 2
> written wide characters, when in fact 0 wide characters have been written.

Thanks. It looks like the wide printf core is just missing any
validation logic for the wchar_t[] array. Probably it was assumed
writing it that any wchar_t would be accepted so that no error
handling would be needed, but the backend doesn't actually accept
them.

I'm not sure what the best fix is, but the simplest one is to iterate
and validate the entire range to be printed before printing anything
and error out on EILSEQ. But I'm not sure if this is actually
conforming either.

Since fwprintf is supposed to behave as if by repeated fputwc, and the
allowance (rather mandate) for EILSEQ comes from fputwc, the error
should only happen at the point the invalid character is written, with
all output up to that point being visible. So I guess we should drop
use of the out() helper function here and call fputc explicitly in a
loop where we can process the error. And in fact out() is only used
two places (also for the format string, where not being a valid wchar
string is UB so it doesn't really matter) so maybe we should just drop
the helper altogether and open-code it both places with proper error
handling...

Rich

  reply	other threads:[~2023-03-20 12:16 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-03-19 23:48 Bruno Haible
2023-03-20 12:15 ` Rich Felker [this message]
2023-03-20 18:08   ` Rich Felker
2023-03-20 18:22     ` Bruno Haible
2023-03-20 21:19       ` Rich Felker

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230320121559.GQ4163@brightrain.aerifal.cx \
    --to=dalias@libc.org \
    --cc=bruno@clisp.org \
    --cc=musl@lists.openwall.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).