Bug#841386: libc6: perror() changes orientation of non-oriented stderr when it is redirected

2016-10-20 Thread Aurelien Jarno
control: forwarded -1 https://sourceware.org/bugzilla/show_bug.cgi?id=20677
control: severity -1 normal

On 2016-10-20 12:50, Igor Liferenko wrote:
> Package: libc6
> Version: 2.24-3
> Severity: important
> Tags: patch
> 
> Dear Maintainer,
> 
> This bug can be seen by compiling the following program and then running
> 
> $ ./a.out 2>/dev/null
> 
> The output is
> 
> initial fwide: 0
> fwide: -1
> 
> The attached patch fixes this, so that the output becomes
> 
> initial fwide: 0
> fwide: 0
> 
> 
> #include 
> #include 
> #include 
> int main(void)
> {
>   printf("initial fwide: %d\n", fwide(stderr, 0));
>   errno = EINVAL;
>   perror(""); /* note, that prior to this call stderr was not oriented */
>   printf("fwide: %d\n", fwide(stderr, 0));
>   return 0;
> }
> 
> Cheers,
> Igor
> 
> P.S. I posted a  href="https://sourceware.org/bugzilla/show_bug.cgi?id=20677;>bugreport to 
> upstream
> I can only guess why this 100% *small* bug has not been fixed ...

This bug is only open upstream for 10 days, and you got comments about
it 3 days ago. Please be a bit patient.

Anyway thanks for reporting the bug upstream, I have marked the bug as
forwarded, so we'll get warned when it the bug has been fixed upstream.

Aurelien

-- 
Aurelien Jarno  GPG: 4096R/1DDD8C9B
aurel...@aurel32.net http://www.aurel32.net



Bug#841386: libc6: perror() changes orientation of non-oriented stderr when it is redirected

2016-10-19 Thread Igor Liferenko
Package: libc6
Version: 2.24-3
Severity: important
Tags: patch

Dear Maintainer,

This bug can be seen by compiling the following program and then running

$ ./a.out 2>/dev/null

The output is

initial fwide: 0
fwide: -1

The attached patch fixes this, so that the output becomes

initial fwide: 0
fwide: 0


#include 
#include 
#include 
int main(void)
{
  printf("initial fwide: %d\n", fwide(stderr, 0));
  errno = EINVAL;
  perror(""); /* note, that prior to this call stderr was not oriented */
  printf("fwide: %d\n", fwide(stderr, 0));
  return 0;
}

Cheers,
Igor

P.S. I posted a https://sourceware.org/bugzilla/show_bug.cgi?id=20677;>bugreport to 
upstream
I can only guess why this 100% *small* bug has not been fixed ...

-- System Information:
Debian Release: stretch/sid
  APT prefers testing
  APT policy: (500, 'testing')
Architecture: amd64 (x86_64)

Kernel: Linux 4.7.0-1-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)

Versions of packages libc6 depends on:
ii  libgcc1  1:6.2.0-6

libc6 recommends no packages.

Versions of packages libc6 suggests:
ii  debconf [debconf-2.0]  1.5.59
pn  glibc-doc  
ii  libc-l10n  2.24-3
ii  locales2.24-3

-- debconf information excluded
diff -ur glibc-2.24.orig/stdio-common/perror.c glibc-2.24/stdio-common/perror.c
--- glibc-2.24.orig/stdio-common/perror.c	2016-08-02 09:01:36.0 +0700
+++ glibc-2.24/stdio-common/perror.c	2016-10-18 08:59:48.996440346 +0700
@@ -22,9 +22,15 @@
 #include 
 #include "libioP.h"
 
-static void
-perror_internal (FILE *fp, const char *s, int errnum)
+/* Print a line on stderr consisting of the text in S, a colon, a space,
+   a message describing the meaning of the contents of `errno' and a newline.
+   If S is NULL or "", the colon and space are omitted.  */
+void
+perror (const char *s)
 {
+  int errnum = errno;
+  int fd = -1;
+
   char buf[1024];
   const char *colon;
   const char *errstring;
@@ -36,48 +42,30 @@
 
   errstring = __strerror_r (errnum, buf, sizeof buf);
 
-  (void) __fxprintf (fp, "%s%s%s\n", s, colon, errstring);
-}
-
-
-/* Print a line on stderr consisting of the text in S, a colon, a space,
-   a message describing the meaning of the contents of `errno' and a newline.
-   If S is NULL or "", the colon and space are omitted.  */
-void
-perror (const char *s)
-{
-  int errnum = errno;
-  FILE *fp;
-  int fd = -1;
-
-
   /* The standard says that 'perror' must not change the orientation
  of the stream.  What is supposed to happen when the stream isn't
- oriented yet?  In this case we'll create a new stream which is
- using the same underlying file descriptor.  */
-  if (__builtin_expect (_IO_fwide (stderr, 0) != 0, 1)
-  || (fd = __fileno (stderr)) == -1
-  || (fd = __dup (fd)) == -1
-  || (fp = fdopen (fd, "w+")) == NULL)
-{
-  if (__glibc_unlikely (fd != -1))
-	__close (fd);
+ oriented yet?  In this case we'll write directly to the same
+ underlying file descriptor.
 
-  /* Use standard error as is.  */
-  perror_internal (stderr, s, errnum);
-}
+ TODO: implement this feature for streams which are not backed by a POSIX
+ file descriptor (e.g., fopencookie and fmemopen).  */
+
+  if (__builtin_expect (_IO_fwide (stderr, 0) != 0, 1)
+  || (fd = __fileno (stderr)) == -1)
+/* Use standard error as is.  */
+(void) __fxprintf (stderr, "%s%s%s\n", s, colon, errstring);
   else
 {
-  /* We don't have to do any special hacks regarding the file
-	 position.  Since the stderr stream wasn't used so far we just
-	 write to the descriptor.  */
-  perror_internal (fp, s, errnum);
-
-  if (_IO_ferror_unlocked (fp))
-	stderr->_flags |= _IO_ERR_SEEN;
-
-  /* Close the stream.  */
-  fclose (fp);
+  /* Streams without orientation have never had any output directed at
+ them, so they are definitely still in the initial shift state with an
+ empty buffer (if the stream is buffered). Thus, in the case when
+ stderr has no orientation, we may safely use "__write", considering
+ the fact that "__write" has no internal buffer.  */
+
+  __write(fd, s, strlen(s));
+  __write(fd, colon, strlen(colon));
+  __write(fd, errstring, strlen(errstring));
+  __write(fd, "\n", 1);
 }
 }
 libc_hidden_def (perror)