Fix freopen handling of ,ccs= (bug 23675)

Message ID 64e04f8-e6d7-ab27-dedb-c521df508ece@redhat.com
State Committed
Commit e44ca1c085b3bd41266c882ea1cb0fd436231635
Headers
Series Fix freopen handling of ,ccs= (bug 23675) |

Checks

Context Check Description
redhat-pt-bot/TryBot-apply_patch success Patch applied to master at the time it was sent
linaro-tcwg-bot/tcwg_glibc_build--master-arm warning Patch is already merged
redhat-pt-bot/TryBot-32bit success Build for i686
linaro-tcwg-bot/tcwg_glibc_build--master-aarch64 warning Patch is already merged

Commit Message

Joseph Myers Sept. 5, 2024, 7:36 p.m. UTC
  As reported in bug 23675 and shown up in the recently added tests of
different cases of freopen (relevant part of the test currently
conditioned under #if 0 to avoid a failure resulting from this bug),
freopen wrongly forces the stream to unoriented even when a mode with
,ccs= is specified, though such a mode is supposed to result in a
wide-oriented stream.  Move the clearing of _mode to before the actual
reopening occurs, so that the main fopen implementation can leave a
wide-oriented stream in the ,ccs= case.

Tested for x86_64.
  

Comments

Carlos O'Donell Sept. 5, 2024, 7:57 p.m. UTC | #1
On 9/5/24 3:36 PM, Joseph Myers wrote:
> As reported in bug 23675 and shown up in the recently added tests of
> different cases of freopen (relevant part of the test currently
> conditioned under #if 0 to avoid a failure resulting from this bug),
> freopen wrongly forces the stream to unoriented even when a mode with
> ,ccs= is specified, though such a mode is supposed to result in a
> wide-oriented stream.  Move the clearing of _mode to before the actual
> reopening occurs, so that the main fopen implementation can leave a
> wide-oriented stream in the ,ccs= case.
> 
> Tested for x86_64.

LGTM.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>

> diff --git a/libio/freopen.c b/libio/freopen.c
> index ceeff8f2ac..00f26ad578 100644
> --- a/libio/freopen.c
> +++ b/libio/freopen.c
> @@ -66,6 +66,7 @@ freopen (const char *filename, const char *mode, FILE *fp)
>        fp->_flags2 &= ~(_IO_FLAGS2_MMAP
>  		       | _IO_FLAGS2_NOTCANCEL
>  		       | _IO_FLAGS2_CLOEXEC);
> +      fp->_mode = 0;

OK. Clear mode ahead of _IO_old_file_fopen (compat).

>        result = _IO_old_file_fopen (fp, gfilename, mode);
>      }
>    else
> @@ -78,6 +79,7 @@ freopen (const char *filename, const char *mode, FILE *fp)
>        fp->_flags2 &= ~(_IO_FLAGS2_MMAP
>  		       | _IO_FLAGS2_NOTCANCEL
>  		       | _IO_FLAGS2_CLOEXEC);
> +      fp->_mode = 0;

OK. Clear mode ahead of _IO_file_fopen (new interface).

>        result = _IO_file_fopen (fp, gfilename, mode, 1);
>        if (result != NULL)
>  	result = __fopen_maybe_mmap (result);
> @@ -85,9 +87,6 @@ freopen (const char *filename, const char *mode, FILE *fp)
>    fp->_flags2 &= ~_IO_FLAGS2_NOCLOSE;
>    if (result != NULL)
>      {
> -      /* unbound stream orientation */
> -      result->_mode = 0;

OK. Don't clear the mode.

> -
>        if (fd != -1 && _IO_fileno (result) != fd)
>  	{
>  	  /* At this point we have both file descriptors already allocated,
> diff --git a/libio/freopen64.c b/libio/freopen64.c
> index 3a314aca5c..77c0dd3fdf 100644
> --- a/libio/freopen64.c
> +++ b/libio/freopen64.c
> @@ -59,15 +59,13 @@ freopen64 (const char *filename, const char *mode, FILE *fp)
>    fp->_flags2 &= ~(_IO_FLAGS2_MMAP
>  		   | _IO_FLAGS2_NOTCANCEL
>  		   | _IO_FLAGS2_CLOEXEC);
> +  fp->_mode = 0;

OK. Set mode before internal _IO_file_fopen.

>    result = _IO_file_fopen (fp, gfilename, mode, 0);
>    fp->_flags2 &= ~_IO_FLAGS2_NOCLOSE;
>    if (result != NULL)
>      result = __fopen_maybe_mmap (result);
>    if (result != NULL)
>      {
> -      /* unbound stream orientation */
> -      result->_mode = 0;
> -

OK. Correct, don't clear the mode later.

>        if (fd != -1 && _IO_fileno (result) != fd)
>  	{
>  	  /* At this point we have both file descriptors already allocated,
> diff --git a/stdio-common/tst-freopen2-main.c b/stdio-common/tst-freopen2-main.c
> index 5dad41c76b..74c3125fca 100644
> --- a/stdio-common/tst-freopen2-main.c
> +++ b/stdio-common/tst-freopen2-main.c
> @@ -386,13 +386,8 @@ do_test (void)
>    fp = xfopen (file2, "w,ccs=iso-8859-1");
>    ret = fputws (L"\xc0\xc1", fp);
>    TEST_VERIFY (ret >= 0);
> -#if 0 /* Doesn't work (bug 23675).  */
>    fp = FREOPEN (file1, "r,ccs=utf-8", fp);
>    TEST_VERIFY_EXIT (fp != NULL);
> -#else /* Works instead.  */
> -  xfclose (fp);
> -  fp = xfopen (file1, "r,ccs=utf-8");
> -#endif

OK. Enables expanded test for UTF-8 freopen.

>    wc = fgetwc (fp);
>    TEST_COMPARE (wc, (wint_t) 0xc0);
>    wc = fgetwc (fp);
>
  

Patch

diff --git a/libio/freopen.c b/libio/freopen.c
index ceeff8f2ac..00f26ad578 100644
--- a/libio/freopen.c
+++ b/libio/freopen.c
@@ -66,6 +66,7 @@  freopen (const char *filename, const char *mode, FILE *fp)
       fp->_flags2 &= ~(_IO_FLAGS2_MMAP
 		       | _IO_FLAGS2_NOTCANCEL
 		       | _IO_FLAGS2_CLOEXEC);
+      fp->_mode = 0;
       result = _IO_old_file_fopen (fp, gfilename, mode);
     }
   else
@@ -78,6 +79,7 @@  freopen (const char *filename, const char *mode, FILE *fp)
       fp->_flags2 &= ~(_IO_FLAGS2_MMAP
 		       | _IO_FLAGS2_NOTCANCEL
 		       | _IO_FLAGS2_CLOEXEC);
+      fp->_mode = 0;
       result = _IO_file_fopen (fp, gfilename, mode, 1);
       if (result != NULL)
 	result = __fopen_maybe_mmap (result);
@@ -85,9 +87,6 @@  freopen (const char *filename, const char *mode, FILE *fp)
   fp->_flags2 &= ~_IO_FLAGS2_NOCLOSE;
   if (result != NULL)
     {
-      /* unbound stream orientation */
-      result->_mode = 0;
-
       if (fd != -1 && _IO_fileno (result) != fd)
 	{
 	  /* At this point we have both file descriptors already allocated,
diff --git a/libio/freopen64.c b/libio/freopen64.c
index 3a314aca5c..77c0dd3fdf 100644
--- a/libio/freopen64.c
+++ b/libio/freopen64.c
@@ -59,15 +59,13 @@  freopen64 (const char *filename, const char *mode, FILE *fp)
   fp->_flags2 &= ~(_IO_FLAGS2_MMAP
 		   | _IO_FLAGS2_NOTCANCEL
 		   | _IO_FLAGS2_CLOEXEC);
+  fp->_mode = 0;
   result = _IO_file_fopen (fp, gfilename, mode, 0);
   fp->_flags2 &= ~_IO_FLAGS2_NOCLOSE;
   if (result != NULL)
     result = __fopen_maybe_mmap (result);
   if (result != NULL)
     {
-      /* unbound stream orientation */
-      result->_mode = 0;
-
       if (fd != -1 && _IO_fileno (result) != fd)
 	{
 	  /* At this point we have both file descriptors already allocated,
diff --git a/stdio-common/tst-freopen2-main.c b/stdio-common/tst-freopen2-main.c
index 5dad41c76b..74c3125fca 100644
--- a/stdio-common/tst-freopen2-main.c
+++ b/stdio-common/tst-freopen2-main.c
@@ -386,13 +386,8 @@  do_test (void)
   fp = xfopen (file2, "w,ccs=iso-8859-1");
   ret = fputws (L"\xc0\xc1", fp);
   TEST_VERIFY (ret >= 0);
-#if 0 /* Doesn't work (bug 23675).  */
   fp = FREOPEN (file1, "r,ccs=utf-8", fp);
   TEST_VERIFY_EXIT (fp != NULL);
-#else /* Works instead.  */
-  xfclose (fp);
-  fp = xfopen (file1, "r,ccs=utf-8");
-#endif
   wc = fgetwc (fp);
   TEST_COMPARE (wc, (wint_t) 0xc0);
   wc = fgetwc (fp);