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 <stdio.h> #include <wchar.h> #include <errno.h> 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 <a href="https://sourceware.org/bugzilla/show_bug.cgi?id=20677">bugreport to upstream</a> 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 <none> ii libc-l10n 2.24-3 ii locales 2.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.000000000 +0700 +++ glibc-2.24/stdio-common/perror.c 2016-10-18 08:59:48.996440346 +0700 @@ -22,9 +22,15 @@ #include <wchar.h> #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)