about summary refs log tree commit diff
path: root/libio/wfileops.c
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2019-05-20 21:54:57 +0200
committerFlorian Weimer <fweimer@redhat.com>2019-05-20 21:54:57 +0200
commit09e1b0e3f6facc1af2dbcfef204f0aaa8718772b (patch)
tree18056a8f7177511eff47519d176c310901f5e455 /libio/wfileops.c
parent75c51570c710aa9c6df6b7a1e131392e1408c63f (diff)
downloadglibc-09e1b0e3f6facc1af2dbcfef204f0aaa8718772b.tar.gz
glibc-09e1b0e3f6facc1af2dbcfef204f0aaa8718772b.tar.xz
glibc-09e1b0e3f6facc1af2dbcfef204f0aaa8718772b.zip
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>
Diffstat (limited to 'libio/wfileops.c')
-rw-r--r--libio/wfileops.c89
1 files changed, 44 insertions, 45 deletions
diff --git a/libio/wfileops.c b/libio/wfileops.c
index 69fbb62a02..f1863db638 100644
--- a/libio/wfileops.c
+++ b/libio/wfileops.c
@@ -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.  */
-	  result = (*cc->__codecvt_do_out) (cc, &fp->_wide_data->_IO_state,
-					    data, data + to_do, &new_data,
-					    write_ptr,
-					    buf_end,
-					    &write_ptr);
+	  result = __libio_codecvt_out (cc, &fp->_wide_data->_IO_state,
+					data, data + to_do, &new_data,
+					write_ptr,
+					buf_end,
+					&write_ptr);
 
 	  /* Write out what we produced so far.  */
 	  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_read_base = fp->_wide_data->_IO_read_ptr =
 	fp->_wide_data->_IO_buf_base;
-      status = (*cd->__codecvt_do_in) (cd, &fp->_wide_data->_IO_state,
-				       fp->_IO_read_ptr, fp->_IO_read_end,
-				       &read_stop,
-				       fp->_wide_data->_IO_read_ptr,
-				       fp->_wide_data->_IO_buf_end,
-				       &fp->_wide_data->_IO_read_end);
+      status = __libio_codecvt_in (cd, &fp->_wide_data->_IO_state,
+				   fp->_IO_read_ptr, fp->_IO_read_end,
+				   &read_stop,
+				   fp->_wide_data->_IO_read_ptr,
+				   fp->_wide_data->_IO_buf_end,
+				   &fp->_wide_data->_IO_read_end);
 
       fp->_IO_read_base = fp->_IO_read_ptr;
       fp->_IO_read_ptr = (char *) read_stop;
@@ -266,11 +266,11 @@ _IO_wfile_underflow (FILE *fp)
       naccbuf += to_copy;
       from = accbuf;
     }
-  status = (*cd->__codecvt_do_in) (cd, &fp->_wide_data->_IO_state,
-				   from, to, &read_ptr_copy,
-				   fp->_wide_data->_IO_read_end,
-				   fp->_wide_data->_IO_buf_end,
-				   &fp->_wide_data->_IO_read_end);
+  status = __libio_codecvt_in (cd, &fp->_wide_data->_IO_state,
+			       from, to, &read_ptr_copy,
+			       fp->_wide_data->_IO_read_end,
+			       fp->_wide_data->_IO_buf_end,
+			       &fp->_wide_data->_IO_read_end);
 
   if (__glibc_unlikely (naccbuf != 0))
     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_read_base = fp->_wide_data->_IO_read_ptr =
     fp->_wide_data->_IO_buf_base;
-  (*cd->__codecvt_do_in) (cd, &fp->_wide_data->_IO_state,
-			  fp->_IO_read_ptr, fp->_IO_read_end,
-			  &read_stop,
-			  fp->_wide_data->_IO_read_ptr,
-			  fp->_wide_data->_IO_buf_end,
-			  &fp->_wide_data->_IO_read_end);
+  __libio_codecvt_in (cd, &fp->_wide_data->_IO_state,
+		      fp->_IO_read_ptr, fp->_IO_read_end,
+		      &read_stop,
+		      fp->_wide_data->_IO_read_ptr,
+		      fp->_wide_data->_IO_buf_end,
+		      &fp->_wide_data->_IO_read_end);
 
   fp->_IO_read_ptr = (char *) read_stop;
 
@@ -495,7 +495,7 @@ _IO_wfile_sync (FILE *fp)
       struct _IO_codecvt *cv = fp->_codecvt;
       off64_t new_pos;
 
-      int clen = (*cv->__codecvt_do_encoding) (cv);
+      int clen = __libio_codecvt_encoding (cv);
 
       if (clen > 0)
 	/* 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
 			   - fp->_wide_data->_IO_read_base);
 	  fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
-	  nread = (*cv->__codecvt_do_length) (cv, &fp->_wide_data->_IO_state,
-					      fp->_IO_read_base,
-					      fp->_IO_read_end, wnread);
+	  nread = __libio_codecvt_length (cv, &fp->_wide_data->_IO_state,
+					  fp->_IO_read_base,
+					  fp->_IO_read_end, wnread);
 	  fp->_IO_read_ptr = 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;
 
-  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
      convert.  */
@@ -565,12 +565,12 @@ adjust_wide_data (FILE *fp, bool do_convert)
     {
 
       fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state;
-      status = (*cv->__codecvt_do_in) (cv, &fp->_wide_data->_IO_state,
-				       fp->_IO_read_base, fp->_IO_read_ptr,
-				       &read_stop,
-				       fp->_wide_data->_IO_read_base,
-				       fp->_wide_data->_IO_buf_end,
-				       &fp->_wide_data->_IO_read_end);
+      status = __libio_codecvt_in (cv, &fp->_wide_data->_IO_state,
+				   fp->_IO_read_base, fp->_IO_read_ptr,
+				   &read_stop,
+				   fp->_wide_data->_IO_read_base,
+				   fp->_wide_data->_IO_buf_end,
+				   &fp->_wide_data->_IO_read_end);
 
       /* Should we return EILSEQ?  */
       if (__glibc_unlikely (status == __codecvt_error))
@@ -648,7 +648,7 @@ do_ftell_wide (FILE *fp)
 	}
 
       struct _IO_codecvt *cv = fp->_codecvt;
-      int clen = (*cv->__codecvt_do_encoding) (cv);
+      int clen = __libio_codecvt_encoding (cv);
 
       if (!unflushed_writes)
 	{
@@ -663,9 +663,9 @@ do_ftell_wide (FILE *fp)
 
 	      size_t delta = wide_read_ptr - wide_read_base;
 	      __mbstate_t state = fp->_wide_data->_IO_last_state;
-	      nread = (*cv->__codecvt_do_length) (cv, &state,
-						  fp->_IO_read_base,
-						  fp->_IO_read_end, delta);
+	      nread = __libio_codecvt_length (cv, &state,
+					      fp->_IO_read_base,
+					      fp->_IO_read_end, delta);
 	      offset -= fp->_IO_read_end - fp->_IO_read_base - nread;
 	    }
 	}
@@ -688,9 +688,8 @@ do_ftell_wide (FILE *fp)
 	      enum __codecvt_result status;
 
 	      __mbstate_t state = fp->_wide_data->_IO_last_state;
-	      status = (*cv->__codecvt_do_out) (cv, &state,
-						in, in + delta, &in,
-						out, out + outsize, &outstop);
+	      status = __libio_codecvt_out (cv, &state, in, in + delta, &in,
+					    out, out + outsize, &outstop);
 
 	      /* We don't check for __codecvt_partial because it can be
 		 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
 	 the current position in the internal buffer.  */
       cv = fp->_codecvt;
-      clen = (*cv->__codecvt_do_encoding) (cv);
+      clen = __libio_codecvt_encoding (cv);
 
       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
 		       - fp->_wide_data->_IO_read_base);
 	      fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
-	      nread = (*cv->__codecvt_do_length) (cv,
-						  &fp->_wide_data->_IO_state,
-						  fp->_IO_read_base,
-						  fp->_IO_read_end, delta);
+	      nread = __libio_codecvt_length (cv,
+					      &fp->_wide_data->_IO_state,
+					      fp->_IO_read_base,
+					      fp->_IO_read_end, delta);
 	      fp->_IO_read_ptr = fp->_IO_read_base + nread;
 	      fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_read_ptr;
 	      offset -= fp->_IO_read_end - fp->_IO_read_base - nread;