glibc: 2.21 -> 2.22

This commit is contained in:
Eelco Dolstra 2016-02-18 20:54:52 +01:00
parent b2b1511353
commit f98a5946b7
6 changed files with 51 additions and 397 deletions

View File

@ -13,7 +13,7 @@ cross:
let
version = "2.21";
version = "2.22";
in
@ -57,10 +57,6 @@ stdenv.mkDerivation ({
patch extends the search path by "/run/current-system/sw/bin". */
./fix_path_attribute_in_getconf.patch
./security-4a28f4d5.patch
./security-bdf1ff05.patch
./cve-2014-8121.patch
./cve-2015-1781.patch
./cve-2015-7547.patch
./glibc-locale-incompatibility.patch
@ -165,7 +161,7 @@ stdenv.mkDerivation ({
}
else fetchurl {
url = "mirror://gnu/glibc/glibc-${version}.tar.gz";
sha256 = "0f4prv4c0fcpi85wv4028wqxn075197gwxhgf0vp571fiw2pi3wd";
sha256 = "1rcby0cqgswgqaxyqz0yqc4zizb1kvpi5vlfqp7dh3sa132109m6";
};
# Remove absolute paths from `configure' & co.; build out-of-tree.

View File

@ -1,230 +0,0 @@
From 03d2730b44cc2236318fd978afa2651753666c55 Mon Sep 17 00:00:00 2001
From: Florian Weimer <fweimer@redhat.com>
Date: Wed, 29 Apr 2015 14:41:25 +0200
Subject: [PATCH] CVE-2014-8121: Do not close NSS files database during
iteration [BZ #18007]
MIME-Version: 1.0
Content-Type: text/plain; charset=utf8
Content-Transfer-Encoding: 8bit
Robin Hack discovered Samba would enter an infinite loop processing
certain quota-related requests. We eventually tracked this down to a
glibc issue.
Running a (simplified) test case under strace shows that /etc/passwd
is continuously opened and closed:
…
open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3
lseek(3, 0, SEEK_CUR) = 0
read(3, "root:x:0:0:root:/root:/bin/bash\n"..., 4096) = 2717
lseek(3, 2717, SEEK_SET) = 2717
close(3) = 0
open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3
lseek(3, 0, SEEK_CUR) = 0
lseek(3, 0, SEEK_SET) = 0
read(3, "root:x:0:0:root:/root:/bin/bash\n"..., 4096) = 2717
lseek(3, 2717, SEEK_SET) = 2717
close(3) = 0
open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3
lseek(3, 0, SEEK_CUR) = 0
…
The lookup function implementation in
nss/nss_files/files-XXX.c:DB_LOOKUP has code to prevent that. It is
supposed skip closing the input file if it was already open.
/* Reset file pointer to beginning or open file. */ \
status = internal_setent (keep_stream); \
\
if (status == NSS_STATUS_SUCCESS) \
{ \
/* Tell getent function that we have repositioned the file pointer. */ \
last_use = getby; \
\
while ((status = internal_getent (result, buffer, buflen, errnop \
H_ERRNO_ARG EXTRA_ARGS_VALUE)) \
== NSS_STATUS_SUCCESS) \
{ break_if_match } \
\
if (! keep_stream) \
internal_endent (); \
} \
keep_stream is initialized from the stayopen flag in internal_setent.
internal_setent is called from the set*ent implementation as:
status = internal_setent (stayopen);
However, for non-host database, this flag is always 0, per the
STAYOPEN magic in nss/getXXent_r.c.
Thus, the fix is this:
- status = internal_setent (stayopen);
+ status = internal_setent (1);
This is not a behavioral change even for the hosts database (where the
application can specify the stayopen flag) because with a call to
sethostent(0), the file handle is still not closed in the
implementation of gethostent.
---
ChangeLog | 8 ++++
NEWS | 12 +++--
nss/Makefile | 2 +-
nss/nss_files/files-XXX.c | 2 +-
nss/tst-nss-getpwent.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 136 insertions(+), 6 deletions(-)
create mode 100644 nss/tst-nss-getpwent.c
diff --git a/nss/Makefile b/nss/Makefile
index d75dad2..65ab7b5 100644
--- a/nss/Makefile
+++ b/nss/Makefile
@@ -47,7 +47,7 @@ install-bin := getent makedb
makedb-modules = xmalloc hash-string
extra-objs += $(makedb-modules:=.o)
-tests = test-netdb tst-nss-test1 test-digits-dots
+tests = test-netdb tst-nss-test1 test-digits-dots tst-nss-getpwent
xtests = bug-erange
# Specify rules for the nss_* modules. We have some services.
diff --git a/nss/nss_files/files-XXX.c b/nss/nss_files/files-XXX.c
index a7a45e5..a7ce5ea 100644
--- a/nss/nss_files/files-XXX.c
+++ b/nss/nss_files/files-XXX.c
@@ -134,7 +134,7 @@ CONCAT(_nss_files_set,ENTNAME) (int stayopen)
__libc_lock_lock (lock);
- status = internal_setent (stayopen);
+ status = internal_setent (1);
if (status == NSS_STATUS_SUCCESS && fgetpos (stream, &position) < 0)
{
diff --git a/nss/tst-nss-getpwent.c b/nss/tst-nss-getpwent.c
new file mode 100644
index 0000000..f2e8abc
--- /dev/null
+++ b/nss/tst-nss-getpwent.c
@@ -0,0 +1,118 @@
+/* Copyright (C) 2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pwd.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int
+do_test (void)
+{
+ /* Count the number of entries in the password database, and fetch
+ data from the first and last entries. */
+ size_t count = 0;
+ struct passwd * pw;
+ char *first_name = NULL;
+ uid_t first_uid = 0;
+ char *last_name = NULL;
+ uid_t last_uid = 0;
+ setpwent ();
+ while ((pw = getpwent ()) != NULL)
+ {
+ if (first_name == NULL)
+ {
+ first_name = strdup (pw->pw_name);
+ if (first_name == NULL)
+ {
+ printf ("strdup: %m\n");
+ return 1;
+ }
+ first_uid = pw->pw_uid;
+ }
+
+ free (last_name);
+ last_name = strdup (pw->pw_name);
+ if (last_name == NULL)
+ {
+ printf ("strdup: %m\n");
+ return 1;
+ }
+ last_uid = pw->pw_uid;
+ ++count;
+ }
+ endpwent ();
+
+ if (count == 0)
+ {
+ printf ("No entries in the password database.\n");
+ return 0;
+ }
+
+ /* Try again, this time interleaving with name-based and UID-based
+ lookup operations. The counts do not match if the interleaved
+ lookups affected the enumeration. */
+ size_t new_count = 0;
+ setpwent ();
+ while ((pw = getpwent ()) != NULL)
+ {
+ if (new_count == count)
+ {
+ printf ("Additional entry in the password database.\n");
+ return 1;
+ }
+ ++new_count;
+ struct passwd *pw2 = getpwnam (first_name);
+ if (pw2 == NULL)
+ {
+ printf ("getpwnam (%s) failed: %m\n", first_name);
+ return 1;
+ }
+ pw2 = getpwnam (last_name);
+ if (pw2 == NULL)
+ {
+ printf ("getpwnam (%s) failed: %m\n", last_name);
+ return 1;
+ }
+ pw2 = getpwuid (first_uid);
+ if (pw2 == NULL)
+ {
+ printf ("getpwuid (%llu) failed: %m\n",
+ (unsigned long long) first_uid);
+ return 1;
+ }
+ pw2 = getpwuid (last_uid);
+ if (pw2 == NULL)
+ {
+ printf ("getpwuid (%llu) failed: %m\n",
+ (unsigned long long) last_uid);
+ return 1;
+ }
+ }
+ endpwent ();
+ if (new_count < count)
+ {
+ printf ("Missing entry in the password database.\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"

View File

@ -1,27 +0,0 @@
From 2959eda9272a033863c271aff62095abd01bd4e3 Mon Sep 17 00:00:00 2001
From: Arjun Shankar <arjun.is@lostca.se>
Date: Tue, 21 Apr 2015 14:06:31 +0200
Subject: [PATCH] CVE-2015-1781: resolv/nss_dns/dns-host.c buffer overflow
[BZ#18287]
---
ChangeLog | 6 ++++++
NEWS | 9 ++++++++-
resolv/nss_dns/dns-host.c | 3 ++-
3 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
index b16b0dd..d8c5579 100644
--- a/resolv/nss_dns/dns-host.c
+++ b/resolv/nss_dns/dns-host.c
@@ -615,7 +615,8 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
int have_to_map = 0;
uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data);
buffer += pad;
- if (__glibc_unlikely (buflen < sizeof (struct host_data) + pad))
+ buflen = buflen > pad ? buflen - pad : 0;
+ if (__glibc_unlikely (buflen < sizeof (struct host_data)))
{
/* The buffer is too small. */
too_small:

View File

@ -1,23 +1,31 @@
commit b995d95a5943785be3ab862b2d3276f3b4a22481
Author: Carlos O'Donell <carlos@systemhalted.org>
Date: Tue Feb 16 21:26:37 2016 -0500
CVE-2015-7547
CVE-2015-7547: getaddrinfo() stack-based buffer overflow (Bug 18665).
2016-02-15 Carlos O'Donell <carlos@redhat.com>
* A stack-based buffer overflow was found in libresolv when invoked from
libnss_dns, allowing specially crafted DNS responses to seize control
of execution flow in the DNS client. The buffer overflow occurs in
the functions send_dg (send datagram) and send_vc (send TCP) for the
NSS module libnss_dns.so.2 when calling getaddrinfo with AF_UNSPEC
family. The use of AF_UNSPEC triggers the low-level resolver code to
send out two parallel queries for A and AAAA. A mismanagement of the
buffers used for those queries could result in the response of a query
writing beyond the alloca allocated buffer created by
_nss_dns_gethostbyname4_r. Buffer management is simplified to remove
the overflow. Thanks to the Google Security Team and Red Hat for
reporting the security impact of this issue, and Robert Holiday of
Ciena for reporting the related bug 18665. (CVE-2015-7547)
[BZ #18665]
* resolv/nss_dns/dns-host.c (gaih_getanswer_slice): Always set
*herrno_p.
(gaih_getanswer): Document functional behviour. Return tryagain
if any result is tryagain.
* resolv/res_query.c (__libc_res_nsearch): Set buffer size to zero
when freed.
* resolv/res_send.c: Add copyright text.
(__libc_res_nsend): Document that MAXPACKET is expected.
(send_vc): Document. Remove buffer reuse.
(send_dg): Document. Remove buffer reuse. Set *thisanssizp to set the
size of the buffer. Add Dprint for truncated UDP buffer.
See also:
https://sourceware.org/ml/libc-alpha/2016-02/msg00416.html
https://sourceware.org/ml/libc-alpha/2016-02/msg00418.html
(cherry picked from commit e9db92d3acfe1822d56d11abcea5bfc4c41cf6ca)
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
index a255d5e..47cfe27 100644
index 357ac04..a0fe9a8 100644
--- a/resolv/nss_dns/dns-host.c
+++ b/resolv/nss_dns/dns-host.c
@@ -1031,7 +1031,10 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
@ -69,8 +77,8 @@ index a255d5e..47cfe27 100644
+ expected application behaviour. Some of the synthesized responses
+ aren't very well thought out and sometimes appear to imply that
+ IPv4 responses are always answer 1, and IPv6 responses are always
+ answer 2, but that's not true (see the implemetnation of send_dg
+ and send_vc to see response can arrive in any order, particlarly
+ answer 2, but that's not true (see the implementation of send_dg
+ and send_vc to see response can arrive in any order, particularly
+ for UDP). However, we expect it holds roughly enough of the time
+ that this code works, but certainly needs to be fixed to make this
+ a more robust implementation.
@ -107,12 +115,12 @@ index a255d5e..47cfe27 100644
+ ----------------------------------------------
+
+ [1] If the first response is a success we return success.
+ This ignores the state of the second answer and in fact
+ incorrectly sets errno and h_errno to that of the second
+ This ignores the state of the second answer and in fact
+ incorrectly sets errno and h_errno to that of the second
+ answer. However because the response is a success we ignore
+ *errnop and *h_errnop (though that means you touched errno on
+ success). We are being conservative here and returning the
+ likely IPv4 response in the first answer as a success.
+ success). We are being conservative here and returning the
+ likely IPv4 response in the first answer as a success.
+
+ [2] If the first response is a recoverable TRYAGAIN we return
+ that instead of looking at the second response. The
@ -158,7 +166,7 @@ index a255d5e..47cfe27 100644
if (status != NSS_STATUS_SUCCESS && status2 != NSS_STATUS_NOTFOUND)
status = status2;
+ /* Do not return a truncated second response (unless it was
+ unavoidable e.g. unrecoverable TRYAGAIN). */
+ unavoidable e.g. unrecoverable TRYAGAIN). */
+ if (status == NSS_STATUS_SUCCESS
+ && (status2 == NSS_STATUS_TRYAGAIN
+ && *errnop == ERANGE && *h_errnop != NO_RECOVERY))
@ -195,7 +203,7 @@ index 4a9b3b3..95470a9 100644
}
if (saved_herrno != -1)
diff --git a/resolv/res_send.c b/resolv/res_send.c
index a968b95..21843f1 100644
index 5e53cc2..6511bb1 100644
--- a/resolv/res_send.c
+++ b/resolv/res_send.c
@@ -1,3 +1,20 @@
@ -219,7 +227,7 @@ index a968b95..21843f1 100644
/*
* Copyright (c) 1985, 1989, 1993
* The Regents of the University of California. All rights reserved.
@@ -355,6 +372,8 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
@@ -363,6 +380,8 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
#ifdef USE_HOOKS
if (__glibc_unlikely (statp->qhook || statp->rhook)) {
if (anssiz < MAXPACKET && ansp) {
@ -228,7 +236,7 @@ index a968b95..21843f1 100644
u_char *buf = malloc (MAXPACKET);
if (buf == NULL)
return (-1);
@@ -630,6 +649,77 @@ get_nsaddr (res_state statp, int n)
@@ -638,6 +657,77 @@ get_nsaddr (res_state statp, int n)
return (struct sockaddr *) (void *) &statp->nsaddr_list[n];
}
@ -270,7 +278,7 @@ index a968b95..21843f1 100644
+ are needed but ANSCP is NULL, then as much of the response as
+ possible is read into the buffer, but the results will be truncated.
+ When truncation happens because of a small answer buffer the DNS
+ packets header feild TC will bet set to 1, indicating a truncated
+ packets header field TC will bet set to 1, indicating a truncated
+ message and the rest of the socket data will be read and discarded.
+
+ Answers to the query are stored secondly in *ANSP2 up to a max of
@ -306,7 +314,7 @@ index a968b95..21843f1 100644
static int
send_vc(res_state statp,
const u_char *buf, int buflen, const u_char *buf2, int buflen2,
@@ -639,11 +729,7 @@ send_vc(res_state statp,
@@ -647,11 +737,7 @@ send_vc(res_state statp,
{
const HEADER *hp = (HEADER *) buf;
const HEADER *hp2 = (HEADER *) buf2;
@ -316,19 +324,19 @@ index a968b95..21843f1 100644
- // int anssiz = *anssizp;
- HEADER *anhp = (HEADER *) ans;
+ HEADER *anhp = (HEADER *) *ansp;
struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
struct sockaddr *nsap = get_nsaddr (statp, ns);
int truncating, connreset, n;
/* On some architectures compiler might emit a warning indicating
@@ -731,6 +817,8 @@ send_vc(res_state statp,
@@ -743,6 +829,8 @@ send_vc(res_state statp,
* Receive length & response
*/
int recvresp1 = 0;
+ /* Skip the second response if there is no second query.
+ To do that we mark the second response as received. */
+ To do that we mark the second response as received. */
int recvresp2 = buf2 == NULL;
uint16_t rlen16;
read_len:
@@ -767,40 +855,14 @@ send_vc(res_state statp,
@@ -779,40 +867,14 @@ send_vc(res_state statp,
u_char **thisansp;
int *thisresplenp;
if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
@ -372,7 +380,7 @@ index a968b95..21843f1 100644
thisanssizp = anssizp2;
thisansp = ansp2;
thisresplenp = resplen2;
@@ -804,10 +870,14 @@ send_vc(res_state statp,
@@ -820,10 +882,14 @@ send_vc(res_state statp,
anhp = (HEADER *) *thisansp;
*thisresplenp = rlen;
@ -391,7 +399,7 @@ index a968b95..21843f1 100644
u_char *newp = malloc (MAXPACKET);
if (newp == NULL) {
*terrno = ENOMEM;
@@ -819,6 +889,9 @@ send_vc(res_state statp,
@@ -835,6 +901,9 @@ send_vc(res_state statp,
if (thisansp == ansp2)
*ansp2_malloced = 1;
anhp = (HEADER *) newp;
@ -401,7 +409,7 @@ index a968b95..21843f1 100644
len = rlen;
} else {
Dprint(statp->options & RES_DEBUG,
@@ -948,6 +1021,66 @@ reopen (res_state statp, int *terrno, int ns)
@@ -997,6 +1066,66 @@ reopen (res_state statp, int *terrno, int ns)
return 1;
}
@ -425,7 +433,7 @@ index a968b95..21843f1 100644
+ are needed but ANSCP is NULL, then as much of the response as
+ possible is read into the buffer, but the results will be truncated.
+ When truncation happens because of a small answer buffer the DNS
+ packets header feild TC will bet set to 1, indicating a truncated
+ packets header field TC will bet set to 1, indicating a truncated
+ message, while the rest of the UDP packet is discarded.
+
+ Answers to the query are stored secondly in *ANSP2 up to a max of
@ -468,7 +476,7 @@ index a968b95..21843f1 100644
static int
send_dg(res_state statp,
const u_char *buf, int buflen, const u_char *buf2, int buflen2,
@@ -957,8 +1090,6 @@ send_dg(res_state statp,
@@ -1006,8 +1135,6 @@ send_dg(res_state statp,
{
const HEADER *hp = (HEADER *) buf;
const HEADER *hp2 = (HEADER *) buf2;
@ -477,16 +485,16 @@ index a968b95..21843f1 100644
struct timespec now, timeout, finish;
struct pollfd pfd[1];
int ptimeout;
@@ -991,6 +1122,8 @@ send_dg(res_state statp,
@@ -1040,6 +1167,8 @@ send_dg(res_state statp,
int need_recompute = 0;
int nwritten = 0;
int recvresp1 = 0;
+ /* Skip the second response if there is no second query.
+ To do that we mark the second response as received. */
+ To do that we mark the second response as received. */
int recvresp2 = buf2 == NULL;
pfd[0].fd = EXT(statp).nssocks[ns];
pfd[0].events = POLLOUT;
@@ -1154,55 +1287,56 @@ send_dg(res_state statp,
@@ -1203,55 +1332,56 @@ send_dg(res_state statp,
int *thisresplenp;
if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
@ -570,4 +578,3 @@ index a968b95..21843f1 100644
HEADER *anhp = (HEADER *) *thisansp;
socklen_t fromlen = sizeof(struct sockaddr_in6);
assert (sizeof(from) <= fromlen);

View File

@ -1,53 +0,0 @@
From 4a28f4d55a6cc33474c0792fe93b5942d81bf185 Mon Sep 17 00:00:00 2001
From: Andreas Schwab <schwab@suse.de>
Date: Thu, 26 Feb 2015 14:55:24 +0100
Subject: [PATCH] Fix read past end of pattern in fnmatch (bug 18032)
---
ChangeLog | 7 +++++++
NEWS | 2 +-
posix/fnmatch_loop.c | 5 ++---
posix/tst-fnmatch3.c | 8 +++++---
4 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/posix/fnmatch_loop.c b/posix/fnmatch_loop.c
index c0cb2fc..72c5d8f 100644
--- a/posix/fnmatch_loop.c
+++ b/posix/fnmatch_loop.c
@@ -945,14 +945,13 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used)
}
else if (c == L('[') && *p == L('.'))
{
- ++p;
while (1)
{
c = *++p;
- if (c == '\0')
+ if (c == L('\0'))
return FNM_NOMATCH;
- if (*p == L('.') && p[1] == L(']'))
+ if (c == L('.') && p[1] == L(']'))
break;
}
p += 2;
diff --git a/posix/tst-fnmatch3.c b/posix/tst-fnmatch3.c
index d27a557..75bc00a 100644
--- a/posix/tst-fnmatch3.c
+++ b/posix/tst-fnmatch3.c
@@ -21,9 +21,11 @@
int
do_test (void)
{
- const char *pattern = "[[:alpha:]'[:alpha:]\0]";
-
- return fnmatch (pattern, "a", 0) != FNM_NOMATCH;
+ if (fnmatch ("[[:alpha:]'[:alpha:]\0]", "a", 0) != FNM_NOMATCH)
+ return 1;
+ if (fnmatch ("[a[.\0.]]", "a", 0) != FNM_NOMATCH)
+ return 1;
+ return 0;
}
#define TEST_FUNCTION do_test ()

View File

@ -1,39 +0,0 @@
From bdf1ff052a8e23d637f2c838fa5642d78fcedc33 Mon Sep 17 00:00:00 2001
From: Paul Pluzhnikov <ppluzhnikov@google.com>
Date: Sun, 22 Feb 2015 12:01:47 -0800
Subject: [PATCH] Fix BZ #17269 -- _IO_wstr_overflow integer overflow
---
ChangeLog | 6 ++++++
NEWS | 6 +++---
libio/wstrops.c | 8 +++++++-
3 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/libio/wstrops.c b/libio/wstrops.c
index 43d847d..3993579 100644
--- a/libio/wstrops.c
+++ b/libio/wstrops.c
@@ -95,8 +95,11 @@ _IO_wstr_overflow (fp, c)
wchar_t *old_buf = fp->_wide_data->_IO_buf_base;
size_t old_wblen = _IO_wblen (fp);
_IO_size_t new_size = 2 * old_wblen + 100;
- if (new_size < old_wblen)
+
+ if (__glibc_unlikely (new_size < old_wblen)
+ || __glibc_unlikely (new_size > SIZE_MAX / sizeof (wchar_t)))
return EOF;
+
new_buf
= (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size
* sizeof (wchar_t));
@@ -186,6 +189,9 @@ enlarge_userbuf (_IO_FILE *fp, _IO_off64_t offset, int reading)
return 1;
_IO_size_t newsize = offset + 100;
+ if (__glibc_unlikely (newsize > SIZE_MAX / sizeof (wchar_t)))
+ return 1;
+
wchar_t *oldbuf = wd->_IO_buf_base;
wchar_t *newbuf
= (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (newsize