wcstombs: also call __WCTOMB on terminating NUL if output buffer is NULL

Message ID 59a1e693-b46a-92f5-a209-0d21f9d73d69@t-online.de
State New
Headers
Series wcstombs: also call __WCTOMB on terminating NUL if output buffer is NULL |

Commit Message

Christian Franke July 1, 2025, 9:17 a.m. UTC
  Testcase (requires sizeof(wchar_t)==2):

$ uname -sr
CYGWIN_NT-10.0-22631 3.7.0-0.165.g1b60f4861b70.x86_64

$ cat mbslen.c
#include <stdlib.h>
#include <stdio.h>
#include <locale.h>

int main()
{
   setlocale(LC_ALL, "en_US.UTF-8");
   const wchar_t w[] = L"t-\xD801";
   size_t n1 = wcstombs(NULL, w, 0);
   char s[42]; // "t-\xED\xA0\x81"
   size_t n2 = wcstombs(s, w, sizeof(s));
   printf("n1=%zd\nn2=%zd\n", n1, n2);
   return 0;
}

$ gcc -W -Wall -o mbslen mbslen.c

$ ./mbslen
n1=2
n2=5
  

Comments

Corinna Vinschen July 2, 2025, 4:16 p.m. UTC | #1
On Jul  1 11:17, Christian Franke wrote:
> From 32a58b0df028c5894f4a8d02fabf89a8d90e16f2 Mon Sep 17 00:00:00 2001
> From: Christian Franke <christian.franke@t-online.de>
> Date: Tue, 1 Jul 2025 11:00:41 +0200
> Subject: [PATCH] wcstombs: also call __WCTOMB on terminating NUL if output
>  buffer is NULL
> 
> A __WCTOMB call on the terminating NUL may emit more than a NUL byte.
> This is the case if the string ends with a lone UTF-16 high surrogate.
> 
> Fixes: 2a3a02a68764 ("Add SUSV2 support for calculating size if output buffer is NULL")
> Signed-off-by: Christian Franke <christian.franke@t-online.de>
> ---
>  newlib/libc/stdlib/wcstombs_r.c | 7 ++++---
>  1 file changed, 4 insertions(+), 3 deletions(-)

Pushed.

Thanks,
Corinna
  

Patch

diff --git a/newlib/libc/stdlib/wcstombs_r.c b/newlib/libc/stdlib/wcstombs_r.c
index c6a06a39a..2c82a2c25 100644
--- a/newlib/libc/stdlib/wcstombs_r.c
+++ b/newlib/libc/stdlib/wcstombs_r.c
@@ -17,14 +17,15 @@  _wcstombs_r (struct _reent *r,
   if (s == NULL)
     {
       size_t num_bytes = 0;
-      while (*pwcs != 0)
+      do
 	{
-	  bytes = __WCTOMB (r, buff, *pwcs++, state);
+	  bytes = __WCTOMB (r, buff, *pwcs, state);
 	  if (bytes == -1)
 	    return -1;
 	  num_bytes += bytes;
 	}
-      return num_bytes;
+      while (*pwcs++ != 0x00);
+      return num_bytes - 1;
     }
   else
     {