|
Message-ID: <20230322165629.GY4163@brightrain.aerifal.cx> Date: Wed, 22 Mar 2023 12:56:34 -0400 From: Rich Felker <dalias@...c.org> To: Bruno Haible <bruno@...sp.org> Cc: musl@...ts.openwall.com Subject: Re: swprintf produces garbage after a null wide character On Wed, Mar 22, 2023 at 05:24:18PM +0100, Bruno Haible wrote: > When swprintf is meant to produce output with a null wide character, in > musl libc 1.2.3, it produces a correct return value, but fills the entire > destination buffer with null wide characters. I.e. in this case, the number > of written wide characters is larger than the return value + 1. > > How to reproduce: > ==================================== foo.c ==================================== > #include <stdio.h> > #include <wchar.h> > > int main () > { > { > wchar_t buf[5] = { 0xBEEF, 0xBEEF, 0xBEEF, 0xBEEF, 0xBEEF }; > int ret = swprintf (buf, 4, L"%c", '\0'); > printf ("ret = %d, buf[0] = 0x%x, buf[1] = 0x%x, buf[2] = 0x%x, buf[3] = 0x%x, buf[4] = 0x%x\n", > ret, > (unsigned int) buf[0], (unsigned int) buf[1], > (unsigned int) buf[2], (unsigned int) buf[3], > (unsigned int) buf[4]); > } > { > wchar_t buf[5] = { 0xBEEF, 0xBEEF, 0xBEEF, 0xBEEF, 0xBEEF }; > int ret = swprintf (buf, 4, L"%cz", '\0'); > printf ("ret = %d, buf[0] = 0x%x, buf[1] = 0x%x, buf[2] = 0x%x, buf[3] = 0x%x, buf[4] = 0x%x\n", > ret, > (unsigned int) buf[0], (unsigned int) buf[1], > (unsigned int) buf[2], (unsigned int) buf[3], > (unsigned int) buf[4]); > } > return 0; > } > /* > glibc, Solaris 11, Cygwin: > ret = 1, buf[0] = 0x0, buf[1] = 0x0, buf[2] = 0xbeef, buf[3] = 0xbeef, buf[4] = 0xbeef > ret = 2, buf[0] = 0x0, buf[1] = 0x7a, buf[2] = 0x0, buf[3] = 0xbeef, buf[4] = 0xbeef > musl libc: > ret = 1, buf[0] = 0x0, buf[1] = 0x0, buf[2] = 0x0, buf[3] = 0x0, buf[4] = 0xbeef > ret = 2, buf[0] = 0x0, buf[1] = 0x0, buf[2] = 0x0, buf[3] = 0x0, buf[4] = 0xbeef > FreeBSD 13, NetBSD 9, OpenBSD 7.2, macOS 12.5, AIX 7.1: > ret = 1, buf[0] = 0x0, buf[1] = 0xbeef, buf[2] = 0xbeef, buf[3] = 0xbeef, buf[4] = 0xbeef > ret = 2, buf[0] = 0x0, buf[1] = 0xbeef, buf[2] = 0xbeef, buf[3] = 0xbeef, buf[4] = 0xbeef > */ > =============================================================================== > > $ gcc -Wall foo.c > $ ./a.out > > Expected output: > ret = 1, buf[0] = 0x0, buf[1] = 0x0, buf[2] = 0xbeef, buf[3] = 0xbeef, buf[4] = 0xbeef > ret = 2, buf[0] = 0x0, buf[1] = 0x7a, buf[2] = 0x0, buf[3] = 0xbeef, buf[4] = 0xbeef > > Actual output: > ret = 1, buf[0] = 0x0, buf[1] = 0x0, buf[2] = 0x0, buf[3] = 0x0, buf[4] = 0xbeef > ret = 2, buf[0] = 0x0, buf[1] = 0x0, buf[2] = 0x0, buf[3] = 0x0, buf[4] = 0xbeef Thanks. This one is an easy one-line fix. Caught by the bad mbtowc behavior of returning 0 rather than 1 when converting a nul character (thereby not advancing past it in the buffer). Rich
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.