diff options
Diffstat (limited to 'libio/strops.c')
-rw-r--r-- | libio/strops.c | 141 |
1 files changed, 84 insertions, 57 deletions
diff --git a/libio/strops.c b/libio/strops.c index 0932d4c1b1..df8268b7ab 100644 --- a/libio/strops.c +++ b/libio/strops.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993-2016 Free Software Foundation, Inc. +/* Copyright (C) 1993-2018 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 @@ -31,15 +31,15 @@ #include <stdio_ext.h> void -_IO_str_init_static_internal (_IO_strfile *sf, char *ptr, _IO_size_t size, +_IO_str_init_static_internal (_IO_strfile *sf, char *ptr, size_t size, char *pstart) { - _IO_FILE *fp = &sf->_sbf._f; + FILE *fp = &sf->_sbf._f; char *end; if (size == 0) end = __rawmemchr (ptr, '\0'); - else if ((_IO_size_t) ptr + size > (_IO_size_t) ptr) + else if ((size_t) ptr + size > (size_t) ptr) end = ptr + size; else end = (char *) -1; @@ -61,7 +61,7 @@ _IO_str_init_static_internal (_IO_strfile *sf, char *ptr, _IO_size_t size, fp->_IO_read_end = end; } /* A null _allocate_buffer function flags the strfile as being static. */ - sf->_s._allocate_buffer = (_IO_alloc_type) 0; + sf->_s._allocate_buffer_unused = (_IO_alloc_type) 0; } void @@ -74,14 +74,14 @@ void _IO_str_init_readonly (_IO_strfile *sf, const char *ptr, int size) { _IO_str_init_static_internal (sf, (char *) ptr, size < 0 ? -1 : size, NULL); - sf->_sbf._f._IO_file_flags |= _IO_NO_WRITES; + sf->_sbf._f._flags |= _IO_NO_WRITES; } int -_IO_str_overflow (_IO_FILE *fp, int c) +_IO_str_overflow (FILE *fp, int c) { int flush_only = c == EOF; - _IO_size_t pos; + size_t pos; if (fp->_flags & _IO_NO_WRITES) return flush_only ? 0 : EOF; if ((fp->_flags & _IO_TIED_PUT_GET) && !(fp->_flags & _IO_CURRENTLY_PUTTING)) @@ -91,7 +91,7 @@ _IO_str_overflow (_IO_FILE *fp, int c) fp->_IO_read_ptr = fp->_IO_read_end; } pos = fp->_IO_write_ptr - fp->_IO_write_base; - if (pos >= (_IO_size_t) (_IO_blen (fp) + flush_only)) + if (pos >= (size_t) (_IO_blen (fp) + flush_only)) { if (fp->_flags & _IO_USER_BUF) /* not allowed to enlarge */ return EOF; @@ -100,11 +100,10 @@ _IO_str_overflow (_IO_FILE *fp, int c) char *new_buf; char *old_buf = fp->_IO_buf_base; size_t old_blen = _IO_blen (fp); - _IO_size_t new_size = 2 * old_blen + 100; + size_t new_size = 2 * old_blen + 100; if (new_size < old_blen) return EOF; - new_buf - = (char *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size); + new_buf = malloc (new_size); if (new_buf == NULL) { /* __ferror(fp) = 1; */ @@ -113,7 +112,7 @@ _IO_str_overflow (_IO_FILE *fp, int c) if (old_buf) { memcpy (new_buf, old_buf, old_blen); - (*((_IO_strfile *) fp)->_s._free_buffer) (old_buf); + free (old_buf); /* Make sure _IO_setb won't try to delete _IO_buf_base. */ fp->_IO_buf_base = NULL; } @@ -139,7 +138,7 @@ _IO_str_overflow (_IO_FILE *fp, int c) libc_hidden_def (_IO_str_overflow) int -_IO_str_underflow (_IO_FILE *fp) +_IO_str_underflow (FILE *fp) { if (fp->_IO_write_ptr > fp->_IO_read_end) fp->_IO_read_end = fp->_IO_write_ptr; @@ -158,8 +157,8 @@ libc_hidden_def (_IO_str_underflow) /* The size of the valid part of the buffer. */ -_IO_ssize_t -_IO_str_count (_IO_FILE *fp) +ssize_t +_IO_str_count (FILE *fp) { return ((fp->_IO_write_ptr > fp->_IO_read_end ? fp->_IO_write_ptr : fp->_IO_read_end) @@ -168,29 +167,28 @@ _IO_str_count (_IO_FILE *fp) static int -enlarge_userbuf (_IO_FILE *fp, _IO_off64_t offset, int reading) +enlarge_userbuf (FILE *fp, off64_t offset, int reading) { - if ((_IO_ssize_t) offset <= _IO_blen (fp)) + if ((ssize_t) offset <= _IO_blen (fp)) return 0; - _IO_ssize_t oldend = fp->_IO_write_end - fp->_IO_write_base; + ssize_t oldend = fp->_IO_write_end - fp->_IO_write_base; /* Try to enlarge the buffer. */ if (fp->_flags & _IO_USER_BUF) /* User-provided buffer. */ return 1; - _IO_size_t newsize = offset + 100; + size_t newsize = offset + 100; char *oldbuf = fp->_IO_buf_base; - char *newbuf - = (char *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (newsize); + char *newbuf = malloc (newsize); if (newbuf == NULL) return 1; if (oldbuf != NULL) { memcpy (newbuf, oldbuf, _IO_blen (fp)); - (*((_IO_strfile *) fp)->_s._free_buffer) (oldbuf); + free (oldbuf); /* Make sure _IO_setb won't try to delete _IO_buf_base. */ fp->_IO_buf_base = NULL; @@ -230,74 +228,103 @@ enlarge_userbuf (_IO_FILE *fp, _IO_off64_t offset, int reading) return 0; } +static void +_IO_str_switch_to_get_mode (FILE *fp) +{ + if (_IO_in_backup (fp)) + fp->_IO_read_base = fp->_IO_backup_base; + else + { + fp->_IO_read_base = fp->_IO_buf_base; + if (fp->_IO_write_ptr > fp->_IO_read_end) + fp->_IO_read_end = fp->_IO_write_ptr; + } + fp->_IO_read_ptr = fp->_IO_read_end = fp->_IO_write_ptr; -_IO_off64_t -_IO_str_seekoff (_IO_FILE *fp, _IO_off64_t offset, int dir, int mode) + fp->_flags &= ~_IO_CURRENTLY_PUTTING; +} + +off64_t +_IO_str_seekoff (FILE *fp, off64_t offset, int dir, int mode) { - _IO_off64_t new_pos; + off64_t new_pos; if (mode == 0 && (fp->_flags & _IO_TIED_PUT_GET)) mode = (fp->_flags & _IO_CURRENTLY_PUTTING ? _IOS_OUTPUT : _IOS_INPUT); + bool was_writing = (fp->_IO_write_ptr > fp->_IO_write_base + || _IO_in_put_mode (fp)); + if (was_writing) + _IO_str_switch_to_get_mode (fp); + if (mode == 0) { - /* Don't move any pointers. But there is no clear indication what - mode FP is in. Let's guess. */ - if (fp->_IO_file_flags & _IO_NO_WRITES) - new_pos = fp->_IO_read_ptr - fp->_IO_read_base; - else - new_pos = fp->_IO_write_ptr - fp->_IO_write_base; + new_pos = fp->_IO_read_ptr - fp->_IO_read_base; } else { - _IO_ssize_t cur_size = _IO_str_count(fp); + ssize_t cur_size = _IO_str_count(fp); new_pos = EOF; /* Move the get pointer, if requested. */ if (mode & _IOS_INPUT) { + ssize_t base; switch (dir) { - case _IO_seek_end: - offset += cur_size; + case _IO_seek_set: + base = 0; break; case _IO_seek_cur: - offset += fp->_IO_read_ptr - fp->_IO_read_base; + base = fp->_IO_read_ptr - fp->_IO_read_base; break; - default: /* case _IO_seek_set: */ + default: /* case _IO_seek_end: */ + base = cur_size; break; } - if (offset < 0) - return EOF; - if ((_IO_ssize_t) offset > cur_size - && enlarge_userbuf (fp, offset, 1) != 0) + ssize_t maxval = SSIZE_MAX - base; + if (offset < -base || offset > maxval) + { + __set_errno (EINVAL); + return EOF; + } + base += offset; + if (base > cur_size + && enlarge_userbuf (fp, base, 1) != 0) return EOF; - fp->_IO_read_ptr = fp->_IO_read_base + offset; + fp->_IO_read_ptr = fp->_IO_read_base + base; fp->_IO_read_end = fp->_IO_read_base + cur_size; - new_pos = offset; + new_pos = base; } /* Move the put pointer, if requested. */ if (mode & _IOS_OUTPUT) { + ssize_t base; switch (dir) { - case _IO_seek_end: - offset += cur_size; + case _IO_seek_set: + base = 0; break; case _IO_seek_cur: - offset += fp->_IO_write_ptr - fp->_IO_write_base; + base = fp->_IO_write_ptr - fp->_IO_write_base; break; - default: /* case _IO_seek_set: */ + default: /* case _IO_seek_end: */ + base = cur_size; break; } - if (offset < 0) - return EOF; - if ((_IO_ssize_t) offset > cur_size - && enlarge_userbuf (fp, offset, 0) != 0) + ssize_t maxval = SSIZE_MAX - base; + if (offset < -base || offset > maxval) + { + __set_errno (EINVAL); + return EOF; + } + base += offset; + if (base > cur_size + && enlarge_userbuf (fp, base, 0) != 0) return EOF; - fp->_IO_write_ptr = fp->_IO_write_base + offset; - new_pos = offset; + fp->_IO_write_ptr = fp->_IO_write_base + base; + new_pos = base; } } return new_pos; @@ -305,7 +332,7 @@ _IO_str_seekoff (_IO_FILE *fp, _IO_off64_t offset, int dir, int mode) libc_hidden_def (_IO_str_seekoff) int -_IO_str_pbackfail (_IO_FILE *fp, int c) +_IO_str_pbackfail (FILE *fp, int c) { if ((fp->_flags & _IO_NO_WRITES) && c != EOF) return EOF; @@ -314,16 +341,16 @@ _IO_str_pbackfail (_IO_FILE *fp, int c) libc_hidden_def (_IO_str_pbackfail) void -_IO_str_finish (_IO_FILE *fp, int dummy) +_IO_str_finish (FILE *fp, int dummy) { if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF)) - (((_IO_strfile *) fp)->_s._free_buffer) (fp->_IO_buf_base); + free (fp->_IO_buf_base); fp->_IO_buf_base = NULL; _IO_default_finish (fp, 0); } -const struct _IO_jump_t _IO_str_jumps = +const struct _IO_jump_t _IO_str_jumps libio_vtable = { JUMP_INIT_DUMMY, JUMP_INIT(finish, _IO_str_finish), |