1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-28 00:21:52 +03:00

libio: Remove codecvt vtable [BZ #24588]

The codecvt vtable is not a real vtable because it also contains the
conversion state data.  Furthermore, wide stream support was added to
GCC 3.0, after a C++ ABI bump, so there is no compatibility
requirement with libstdc++.

This change removes several unmangled function pointers which could
be used with a corrupted FILE object to redirect execution.  (libio
vtable verification did not cover the codecvt vtable.)

Reviewed-by: Yann Droneaud <ydroneaud@opteya.com>
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
This commit is contained in:
Florian Weimer
2019-05-20 21:54:57 +02:00
parent 75c51570c7
commit 09e1b0e3f6
10 changed files with 135 additions and 205 deletions

View File

@ -1,3 +1,46 @@
2019-05-20 Florian Weimer <fweimer@redhat.com>
[BZ #24588]
libio: Remove codecvt vtable.
* libio/fileops.c ( _IO_new_file_fopen): Do not copy
__libio_codecvt.
* libio/iofgetpos.c (_IO_new_fgetpos): Call
__libio_codecvt_encoding.
* libio/iofgetpos64.c (_IO_new_fgetpos): Likewise.
* libio/iofsetpos.c (_IO_new_fsetpos): Likewise.
* libio/iofsetpos64.c (_IO_new_fsetpos): Likewise.
* libio/iofwide.c (__libio_codecvt): Remove variable.
(_IO_fwide): Do not copy __libio_codecvt.
(__libio_codecvt_out): Rename from do_out and export.
(do_unshift): Remove function.
(__libio_codecvt_in): Rename from do_in and export.
(__libio_codecvt_encoding): Rename from do_encoding and export.
(do_always_noconv): Remove function.
(__libio_codecvt_length): Rename from do_length and export.
(do_max_length): Remove function.
* libio/libio.h (enum __codecvt_result): Remove definition; moved
to libioP.h.
(struct _IO_codecvt): Remove fields __codecvt_destr,
__codecvt_do_out, __codecvt_do_unshift, __codecvt_do_in,
__codecvt_do_encoding, __codecvt_do_always_noconv,
__codecvt_do_length, __codecvt_do_max_length.
* libio/libioP.h (enum __codecvt_result): Define; moved from
libio.h.
(__libio_codecvt_out, __libio_codecvt_in)
(__libio_codecvt_encoding, __libio_codecvt_length): Declare
functions.
* libio/wfileops.c (_IO_wdo_write): Call __libio_codecvt_out.
(_IO_wfile_underflow): Call __libio_codecvt_in.
(_IO_wfile_underflow): Likewise.
(_IO_wfile_underflow_mmap): Likewise.
(_IO_wfile_sync): Call __libio_codecvt_encoding,
__libio_codecvt_length.
(adjust_wide_data): Call __libio_codecvt_encoding,
__libio_codecvt_in.
(do_ftell_wide): Call __libio_codecvt_length, __libio_codecvt_out.
(_IO_wfile_seekoff): Call __libio_codecvt_encoding,
__libio_codecvt_length.
2019-05-20 Florian Weimer <fweimer@redhat.com> 2019-05-20 Florian Weimer <fweimer@redhat.com>
* support/support.h (support_sbindir_prefix): Declare. * support/support.h (support_sbindir_prefix): Declare.

View File

@ -331,9 +331,6 @@ _IO_new_file_fopen (FILE *fp, const char *filename, const char *mode,
cc = fp->_codecvt = &fp->_wide_data->_codecvt; cc = fp->_codecvt = &fp->_wide_data->_codecvt;
/* The functions are always the same. */
*cc = __libio_codecvt;
cc->__cd_in.__cd.__nsteps = fcts.towc_nsteps; cc->__cd_in.__cd.__nsteps = fcts.towc_nsteps;
cc->__cd_in.__cd.__steps = fcts.towc; cc->__cd_in.__cd.__steps = fcts.towc;

View File

@ -70,8 +70,7 @@ _IO_new_fgetpos (FILE *fp, __fpos_t *posp)
else else
{ {
posp->__pos = pos; posp->__pos = pos;
if (fp->_mode > 0 if (fp->_mode > 0 && __libio_codecvt_encoding (fp->_codecvt) < 0)
&& (*fp->_codecvt->__codecvt_do_encoding) (fp->_codecvt) < 0)
/* This is a stateful encoding, safe the state. */ /* This is a stateful encoding, safe the state. */
posp->__state = fp->_wide_data->_IO_state; posp->__state = fp->_wide_data->_IO_state;
} }

View File

@ -54,8 +54,7 @@ _IO_new_fgetpos64 (FILE *fp, __fpos64_t *posp)
else else
{ {
posp->__pos = pos; posp->__pos = pos;
if (fp->_mode > 0 if (fp->_mode > 0 && __libio_codecvt_encoding (fp->_codecvt) < 0)
&& (*fp->_codecvt->__codecvt_do_encoding) (fp->_codecvt) < 0)
/* This is a stateful encoding, safe the state. */ /* This is a stateful encoding, safe the state. */
posp->__state = fp->_wide_data->_IO_state; posp->__state = fp->_wide_data->_IO_state;
} }

View File

@ -58,8 +58,7 @@ _IO_new_fsetpos (FILE *fp, const __fpos_t *posp)
else else
{ {
result = 0; result = 0;
if (fp->_mode > 0 if (fp->_mode > 0 && __libio_codecvt_encoding (fp->_codecvt) < 0)
&& (*fp->_codecvt->__codecvt_do_encoding) (fp->_codecvt) < 0)
/* This is a stateful encoding, restore the state. */ /* This is a stateful encoding, restore the state. */
fp->_wide_data->_IO_state = posp->__state; fp->_wide_data->_IO_state = posp->__state;
} }

View File

@ -48,8 +48,7 @@ _IO_new_fsetpos64 (FILE *fp, const fpos64_t *posp)
else else
{ {
result = 0; result = 0;
if (fp->_mode > 0 if (fp->_mode > 0 && __libio_codecvt_encoding (fp->_codecvt) < 0)
&& (*fp->_codecvt->__codecvt_do_encoding) (fp->_codecvt) < 0)
/* This is a stateful encoding, safe the state. */ /* This is a stateful encoding, safe the state. */
fp->_wide_data->_IO_state = posp->__state; fp->_wide_data->_IO_state = posp->__state;
} }

View File

@ -39,44 +39,6 @@
#include <sysdep.h> #include <sysdep.h>
/* Prototypes of libio's codecvt functions. */
static enum __codecvt_result do_out (struct _IO_codecvt *codecvt,
__mbstate_t *statep,
const wchar_t *from_start,
const wchar_t *from_end,
const wchar_t **from_stop, char *to_start,
char *to_end, char **to_stop);
static enum __codecvt_result do_unshift (struct _IO_codecvt *codecvt,
__mbstate_t *statep, char *to_start,
char *to_end, char **to_stop);
static enum __codecvt_result do_in (struct _IO_codecvt *codecvt,
__mbstate_t *statep,
const char *from_start,
const char *from_end,
const char **from_stop, wchar_t *to_start,
wchar_t *to_end, wchar_t **to_stop);
static int do_encoding (struct _IO_codecvt *codecvt);
static int do_length (struct _IO_codecvt *codecvt, __mbstate_t *statep,
const char *from_start,
const char *from_end, size_t max);
static int do_max_length (struct _IO_codecvt *codecvt);
static int do_always_noconv (struct _IO_codecvt *codecvt);
/* The functions used in `codecvt' for libio are always the same. */
const struct _IO_codecvt __libio_codecvt =
{
.__codecvt_destr = NULL, /* Destructor, never used. */
.__codecvt_do_out = do_out,
.__codecvt_do_unshift = do_unshift,
.__codecvt_do_in = do_in,
.__codecvt_do_encoding = do_encoding,
.__codecvt_do_always_noconv = do_always_noconv,
.__codecvt_do_length = do_length,
.__codecvt_do_max_length = do_max_length
};
/* Return orientation of stream. If mode is nonzero try to change /* Return orientation of stream. If mode is nonzero try to change
the orientation first. */ the orientation first. */
#undef _IO_fwide #undef _IO_fwide
@ -118,9 +80,6 @@ _IO_fwide (FILE *fp, int mode)
assert (fcts.towc_nsteps == 1); assert (fcts.towc_nsteps == 1);
assert (fcts.tomb_nsteps == 1); assert (fcts.tomb_nsteps == 1);
/* The functions are always the same. */
*cc = __libio_codecvt;
cc->__cd_in.__cd.__nsteps = fcts.towc_nsteps; cc->__cd_in.__cd.__nsteps = fcts.towc_nsteps;
cc->__cd_in.__cd.__steps = fcts.towc; cc->__cd_in.__cd.__steps = fcts.towc;
@ -150,11 +109,11 @@ _IO_fwide (FILE *fp, int mode)
} }
static enum __codecvt_result enum __codecvt_result
do_out (struct _IO_codecvt *codecvt, __mbstate_t *statep, __libio_codecvt_out (struct _IO_codecvt *codecvt, __mbstate_t *statep,
const wchar_t *from_start, const wchar_t *from_end, const wchar_t *from_start, const wchar_t *from_end,
const wchar_t **from_stop, char *to_start, char *to_end, const wchar_t **from_stop, char *to_start, char *to_end,
char **to_stop) char **to_stop)
{ {
enum __codecvt_result result; enum __codecvt_result result;
@ -202,57 +161,11 @@ do_out (struct _IO_codecvt *codecvt, __mbstate_t *statep,
} }
static enum __codecvt_result enum __codecvt_result
do_unshift (struct _IO_codecvt *codecvt, __mbstate_t *statep, __libio_codecvt_in (struct _IO_codecvt *codecvt, __mbstate_t *statep,
char *to_start, char *to_end, char **to_stop) const char *from_start, const char *from_end,
{ const char **from_stop,
enum __codecvt_result result; wchar_t *to_start, wchar_t *to_end, wchar_t **to_stop)
struct __gconv_step *gs = codecvt->__cd_out.__cd.__steps;
int status;
size_t dummy;
codecvt->__cd_out.__cd.__data[0].__outbuf = (unsigned char *) to_start;
codecvt->__cd_out.__cd.__data[0].__outbufend = (unsigned char *) to_end;
codecvt->__cd_out.__cd.__data[0].__statep = statep;
__gconv_fct fct = gs->__fct;
#ifdef PTR_DEMANGLE
if (gs->__shlib_handle != NULL)
PTR_DEMANGLE (fct);
#endif
status = DL_CALL_FCT (fct,
(gs, codecvt->__cd_out.__cd.__data, NULL, NULL,
NULL, &dummy, 1, 0));
*to_stop = (char *) codecvt->__cd_out.__cd.__data[0].__outbuf;
switch (status)
{
case __GCONV_OK:
case __GCONV_EMPTY_INPUT:
result = __codecvt_ok;
break;
case __GCONV_FULL_OUTPUT:
case __GCONV_INCOMPLETE_INPUT:
result = __codecvt_partial;
break;
default:
result = __codecvt_error;
break;
}
return result;
}
static enum __codecvt_result
do_in (struct _IO_codecvt *codecvt, __mbstate_t *statep,
const char *from_start, const char *from_end, const char **from_stop,
wchar_t *to_start, wchar_t *to_end, wchar_t **to_stop)
{ {
enum __codecvt_result result; enum __codecvt_result result;
@ -300,8 +213,8 @@ do_in (struct _IO_codecvt *codecvt, __mbstate_t *statep,
} }
static int int
do_encoding (struct _IO_codecvt *codecvt) __libio_codecvt_encoding (struct _IO_codecvt *codecvt)
{ {
/* See whether the encoding is stateful. */ /* See whether the encoding is stateful. */
if (codecvt->__cd_in.__cd.__steps[0].__stateful) if (codecvt->__cd_in.__cd.__steps[0].__stateful)
@ -317,16 +230,10 @@ do_encoding (struct _IO_codecvt *codecvt)
} }
static int int
do_always_noconv (struct _IO_codecvt *codecvt) __libio_codecvt_length (struct _IO_codecvt *codecvt, __mbstate_t *statep,
{ const char *from_start, const char *from_end,
return 0; size_t max)
}
static int
do_length (struct _IO_codecvt *codecvt, __mbstate_t *statep,
const char *from_start, const char *from_end, size_t max)
{ {
int result; int result;
const unsigned char *cp = (const unsigned char *) from_start; const unsigned char *cp = (const unsigned char *) from_start;
@ -353,10 +260,3 @@ do_length (struct _IO_codecvt *codecvt, __mbstate_t *statep,
return result; return result;
} }
static int
do_max_length (struct _IO_codecvt *codecvt)
{
return codecvt->__cd_in.__cd.__steps[0].__max_needed_from;
}

View File

@ -116,40 +116,8 @@ struct _IO_marker {
int _pos; int _pos;
}; };
/* This is the structure from the libstdc++ codecvt class. */
enum __codecvt_result
{
__codecvt_ok,
__codecvt_partial,
__codecvt_error,
__codecvt_noconv
};
/* The order of the elements in the following struct must match the order
of the virtual functions in the libstdc++ codecvt class. */
struct _IO_codecvt struct _IO_codecvt
{ {
void (*__codecvt_destr) (struct _IO_codecvt *);
enum __codecvt_result (*__codecvt_do_out) (struct _IO_codecvt *,
__mbstate_t *,
const wchar_t *,
const wchar_t *,
const wchar_t **, char *,
char *, char **);
enum __codecvt_result (*__codecvt_do_unshift) (struct _IO_codecvt *,
__mbstate_t *, char *,
char *, char **);
enum __codecvt_result (*__codecvt_do_in) (struct _IO_codecvt *,
__mbstate_t *,
const char *, const char *,
const char **, wchar_t *,
wchar_t *, wchar_t **);
int (*__codecvt_do_encoding) (struct _IO_codecvt *);
int (*__codecvt_do_always_noconv) (struct _IO_codecvt *);
int (*__codecvt_do_length) (struct _IO_codecvt *, __mbstate_t *,
const char *, const char *, size_t);
int (*__codecvt_do_max_length) (struct _IO_codecvt *);
_IO_iconv_t __cd_in; _IO_iconv_t __cd_in;
_IO_iconv_t __cd_out; _IO_iconv_t __cd_out;
}; };

View File

@ -476,7 +476,6 @@ extern const struct _IO_jump_t _IO_streambuf_jumps;
extern const struct _IO_jump_t _IO_old_proc_jumps attribute_hidden; extern const struct _IO_jump_t _IO_old_proc_jumps attribute_hidden;
extern const struct _IO_jump_t _IO_str_jumps attribute_hidden; extern const struct _IO_jump_t _IO_str_jumps attribute_hidden;
extern const struct _IO_jump_t _IO_wstr_jumps attribute_hidden; extern const struct _IO_jump_t _IO_wstr_jumps attribute_hidden;
extern const struct _IO_codecvt __libio_codecvt attribute_hidden;
extern int _IO_do_write (FILE *, const char *, size_t); extern int _IO_do_write (FILE *, const char *, size_t);
libc_hidden_proto (_IO_do_write) libc_hidden_proto (_IO_do_write)
extern int _IO_new_do_write (FILE *, const char *, size_t); extern int _IO_new_do_write (FILE *, const char *, size_t);
@ -932,4 +931,32 @@ IO_validate_vtable (const struct _IO_jump_t *vtable)
return vtable; return vtable;
} }
/* Character set conversion. */
enum __codecvt_result
{
__codecvt_ok,
__codecvt_partial,
__codecvt_error,
__codecvt_noconv
};
enum __codecvt_result __libio_codecvt_out (struct _IO_codecvt *,
__mbstate_t *,
const wchar_t *,
const wchar_t *,
const wchar_t **, char *,
char *, char **)
attribute_hidden;
enum __codecvt_result __libio_codecvt_in (struct _IO_codecvt *,
__mbstate_t *,
const char *, const char *,
const char **, wchar_t *,
wchar_t *, wchar_t **)
attribute_hidden;
int __libio_codecvt_encoding (struct _IO_codecvt *) attribute_hidden;
int __libio_codecvt_length (struct _IO_codecvt *, __mbstate_t *,
const char *, const char *, size_t)
attribute_hidden;
#endif /* libioP.h. */ #endif /* libioP.h. */

View File

@ -72,11 +72,11 @@ _IO_wdo_write (FILE *fp, const wchar_t *data, size_t to_do)
} }
/* Now convert from the internal format into the external buffer. */ /* Now convert from the internal format into the external buffer. */
result = (*cc->__codecvt_do_out) (cc, &fp->_wide_data->_IO_state, result = __libio_codecvt_out (cc, &fp->_wide_data->_IO_state,
data, data + to_do, &new_data, data, data + to_do, &new_data,
write_ptr, write_ptr,
buf_end, buf_end,
&write_ptr); &write_ptr);
/* Write out what we produced so far. */ /* Write out what we produced so far. */
if (_IO_new_do_write (fp, write_base, write_ptr - write_base) == EOF) if (_IO_new_do_write (fp, write_base, write_ptr - write_base) == EOF)
@ -140,12 +140,12 @@ _IO_wfile_underflow (FILE *fp)
fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state; fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state;
fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr =
fp->_wide_data->_IO_buf_base; fp->_wide_data->_IO_buf_base;
status = (*cd->__codecvt_do_in) (cd, &fp->_wide_data->_IO_state, status = __libio_codecvt_in (cd, &fp->_wide_data->_IO_state,
fp->_IO_read_ptr, fp->_IO_read_end, fp->_IO_read_ptr, fp->_IO_read_end,
&read_stop, &read_stop,
fp->_wide_data->_IO_read_ptr, fp->_wide_data->_IO_read_ptr,
fp->_wide_data->_IO_buf_end, fp->_wide_data->_IO_buf_end,
&fp->_wide_data->_IO_read_end); &fp->_wide_data->_IO_read_end);
fp->_IO_read_base = fp->_IO_read_ptr; fp->_IO_read_base = fp->_IO_read_ptr;
fp->_IO_read_ptr = (char *) read_stop; fp->_IO_read_ptr = (char *) read_stop;
@ -266,11 +266,11 @@ _IO_wfile_underflow (FILE *fp)
naccbuf += to_copy; naccbuf += to_copy;
from = accbuf; from = accbuf;
} }
status = (*cd->__codecvt_do_in) (cd, &fp->_wide_data->_IO_state, status = __libio_codecvt_in (cd, &fp->_wide_data->_IO_state,
from, to, &read_ptr_copy, from, to, &read_ptr_copy,
fp->_wide_data->_IO_read_end, fp->_wide_data->_IO_read_end,
fp->_wide_data->_IO_buf_end, fp->_wide_data->_IO_buf_end,
&fp->_wide_data->_IO_read_end); &fp->_wide_data->_IO_read_end);
if (__glibc_unlikely (naccbuf != 0)) if (__glibc_unlikely (naccbuf != 0))
fp->_IO_read_ptr += MAX (0, read_ptr_copy - &accbuf[naccbuf - to_copy]); fp->_IO_read_ptr += MAX (0, read_ptr_copy - &accbuf[naccbuf - to_copy]);
@ -372,12 +372,12 @@ _IO_wfile_underflow_mmap (FILE *fp)
fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state; fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state;
fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr =
fp->_wide_data->_IO_buf_base; fp->_wide_data->_IO_buf_base;
(*cd->__codecvt_do_in) (cd, &fp->_wide_data->_IO_state, __libio_codecvt_in (cd, &fp->_wide_data->_IO_state,
fp->_IO_read_ptr, fp->_IO_read_end, fp->_IO_read_ptr, fp->_IO_read_end,
&read_stop, &read_stop,
fp->_wide_data->_IO_read_ptr, fp->_wide_data->_IO_read_ptr,
fp->_wide_data->_IO_buf_end, fp->_wide_data->_IO_buf_end,
&fp->_wide_data->_IO_read_end); &fp->_wide_data->_IO_read_end);
fp->_IO_read_ptr = (char *) read_stop; fp->_IO_read_ptr = (char *) read_stop;
@ -495,7 +495,7 @@ _IO_wfile_sync (FILE *fp)
struct _IO_codecvt *cv = fp->_codecvt; struct _IO_codecvt *cv = fp->_codecvt;
off64_t new_pos; off64_t new_pos;
int clen = (*cv->__codecvt_do_encoding) (cv); int clen = __libio_codecvt_encoding (cv);
if (clen > 0) if (clen > 0)
/* It is easy, a fixed number of input bytes are used for each /* It is easy, a fixed number of input bytes are used for each
@ -511,9 +511,9 @@ _IO_wfile_sync (FILE *fp)
size_t wnread = (fp->_wide_data->_IO_read_ptr size_t wnread = (fp->_wide_data->_IO_read_ptr
- fp->_wide_data->_IO_read_base); - fp->_wide_data->_IO_read_base);
fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state; fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
nread = (*cv->__codecvt_do_length) (cv, &fp->_wide_data->_IO_state, nread = __libio_codecvt_length (cv, &fp->_wide_data->_IO_state,
fp->_IO_read_base, fp->_IO_read_base,
fp->_IO_read_end, wnread); fp->_IO_read_end, wnread);
fp->_IO_read_ptr = fp->_IO_read_base + nread; fp->_IO_read_ptr = fp->_IO_read_base + nread;
delta = -(fp->_IO_read_end - fp->_IO_read_base - nread); delta = -(fp->_IO_read_end - fp->_IO_read_base - nread);
} }
@ -548,7 +548,7 @@ adjust_wide_data (FILE *fp, bool do_convert)
{ {
struct _IO_codecvt *cv = fp->_codecvt; struct _IO_codecvt *cv = fp->_codecvt;
int clen = (*cv->__codecvt_do_encoding) (cv); int clen = __libio_codecvt_encoding (cv);
/* Take the easy way out for constant length encodings if we don't need to /* Take the easy way out for constant length encodings if we don't need to
convert. */ convert. */
@ -565,12 +565,12 @@ adjust_wide_data (FILE *fp, bool do_convert)
{ {
fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state; fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state;
status = (*cv->__codecvt_do_in) (cv, &fp->_wide_data->_IO_state, status = __libio_codecvt_in (cv, &fp->_wide_data->_IO_state,
fp->_IO_read_base, fp->_IO_read_ptr, fp->_IO_read_base, fp->_IO_read_ptr,
&read_stop, &read_stop,
fp->_wide_data->_IO_read_base, fp->_wide_data->_IO_read_base,
fp->_wide_data->_IO_buf_end, fp->_wide_data->_IO_buf_end,
&fp->_wide_data->_IO_read_end); &fp->_wide_data->_IO_read_end);
/* Should we return EILSEQ? */ /* Should we return EILSEQ? */
if (__glibc_unlikely (status == __codecvt_error)) if (__glibc_unlikely (status == __codecvt_error))
@ -648,7 +648,7 @@ do_ftell_wide (FILE *fp)
} }
struct _IO_codecvt *cv = fp->_codecvt; struct _IO_codecvt *cv = fp->_codecvt;
int clen = (*cv->__codecvt_do_encoding) (cv); int clen = __libio_codecvt_encoding (cv);
if (!unflushed_writes) if (!unflushed_writes)
{ {
@ -663,9 +663,9 @@ do_ftell_wide (FILE *fp)
size_t delta = wide_read_ptr - wide_read_base; size_t delta = wide_read_ptr - wide_read_base;
__mbstate_t state = fp->_wide_data->_IO_last_state; __mbstate_t state = fp->_wide_data->_IO_last_state;
nread = (*cv->__codecvt_do_length) (cv, &state, nread = __libio_codecvt_length (cv, &state,
fp->_IO_read_base, fp->_IO_read_base,
fp->_IO_read_end, delta); fp->_IO_read_end, delta);
offset -= fp->_IO_read_end - fp->_IO_read_base - nread; offset -= fp->_IO_read_end - fp->_IO_read_base - nread;
} }
} }
@ -688,9 +688,8 @@ do_ftell_wide (FILE *fp)
enum __codecvt_result status; enum __codecvt_result status;
__mbstate_t state = fp->_wide_data->_IO_last_state; __mbstate_t state = fp->_wide_data->_IO_last_state;
status = (*cv->__codecvt_do_out) (cv, &state, status = __libio_codecvt_out (cv, &state, in, in + delta, &in,
in, in + delta, &in, out, out + outsize, &outstop);
out, out + outsize, &outstop);
/* We don't check for __codecvt_partial because it can be /* We don't check for __codecvt_partial because it can be
returned on one of two conditions: either the output returned on one of two conditions: either the output
@ -801,7 +800,7 @@ _IO_wfile_seekoff (FILE *fp, off64_t offset, int dir, int mode)
find out which position in the external buffer corresponds to find out which position in the external buffer corresponds to
the current position in the internal buffer. */ the current position in the internal buffer. */
cv = fp->_codecvt; cv = fp->_codecvt;
clen = (*cv->__codecvt_do_encoding) (cv); clen = __libio_codecvt_encoding (cv);
if (mode != 0 || !was_writing) if (mode != 0 || !was_writing)
{ {
@ -819,10 +818,10 @@ _IO_wfile_seekoff (FILE *fp, off64_t offset, int dir, int mode)
delta = (fp->_wide_data->_IO_read_ptr delta = (fp->_wide_data->_IO_read_ptr
- fp->_wide_data->_IO_read_base); - fp->_wide_data->_IO_read_base);
fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state; fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
nread = (*cv->__codecvt_do_length) (cv, nread = __libio_codecvt_length (cv,
&fp->_wide_data->_IO_state, &fp->_wide_data->_IO_state,
fp->_IO_read_base, fp->_IO_read_base,
fp->_IO_read_end, delta); fp->_IO_read_end, delta);
fp->_IO_read_ptr = fp->_IO_read_base + nread; fp->_IO_read_ptr = fp->_IO_read_base + nread;
fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_read_ptr; fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_read_ptr;
offset -= fp->_IO_read_end - fp->_IO_read_base - nread; offset -= fp->_IO_read_end - fp->_IO_read_base - nread;