зеркало из https://github.com/github/ruby.git
* io.c: raise IOError when byte oriented operations occur with
non-empty character buffer. [ruby-dev:40493] [ruby-dev:40506] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27470 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
7309f9cc00
Коммит
78db46b31c
|
@ -1,3 +1,9 @@
|
||||||
|
Sat Apr 24 14:40:20 2010 Tanaka Akira <akr@fsij.org>
|
||||||
|
|
||||||
|
* io.c: raise IOError when byte oriented operations occur with
|
||||||
|
non-empty character buffer.
|
||||||
|
[ruby-dev:40493] [ruby-dev:40506]
|
||||||
|
|
||||||
Sat Apr 24 13:06:57 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
Sat Apr 24 13:06:57 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
* ruby.c (get_arglen): skip the last terminator of argv before
|
* ruby.c (get_arglen): skip the last terminator of argv before
|
||||||
|
|
58
io.c
58
io.c
|
@ -180,6 +180,8 @@ static int max_file_descriptor = NOFILE;
|
||||||
#define READ_DATA_PENDING_PTR(fptr) ((fptr)->rbuf+(fptr)->rbuf_off)
|
#define READ_DATA_PENDING_PTR(fptr) ((fptr)->rbuf+(fptr)->rbuf_off)
|
||||||
#define READ_DATA_BUFFERED(fptr) READ_DATA_PENDING(fptr)
|
#define READ_DATA_BUFFERED(fptr) READ_DATA_PENDING(fptr)
|
||||||
|
|
||||||
|
#define READ_CHAR_PENDING(fptr) ((fptr)->cbuf_len)
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#define WAIT_FD_IN_WIN32(fptr) rb_thread_wait_fd((fptr)->fd);
|
#define WAIT_FD_IN_WIN32(fptr) rb_thread_wait_fd((fptr)->fd);
|
||||||
#else
|
#else
|
||||||
|
@ -401,7 +403,7 @@ flush_before_seek(rb_io_t *fptr)
|
||||||
#define FMODE_SYNCWRITE (FMODE_SYNC|FMODE_WRITABLE)
|
#define FMODE_SYNCWRITE (FMODE_SYNC|FMODE_WRITABLE)
|
||||||
|
|
||||||
void
|
void
|
||||||
rb_io_check_readable(rb_io_t *fptr)
|
rb_io_check_char_readable(rb_io_t *fptr)
|
||||||
{
|
{
|
||||||
rb_io_check_closed(fptr);
|
rb_io_check_closed(fptr);
|
||||||
if (!(fptr->mode & FMODE_READABLE)) {
|
if (!(fptr->mode & FMODE_READABLE)) {
|
||||||
|
@ -419,6 +421,21 @@ rb_io_check_readable(rb_io_t *fptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_io_check_byte_readable(rb_io_t *fptr)
|
||||||
|
{
|
||||||
|
rb_io_check_char_readable(fptr);
|
||||||
|
if (READ_CHAR_PENDING(fptr)) {
|
||||||
|
rb_raise(rb_eIOError, "byte oriented read for character buffered IO");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_io_check_readable(rb_io_t *fptr)
|
||||||
|
{
|
||||||
|
rb_io_check_byte_readable(fptr);
|
||||||
|
}
|
||||||
|
|
||||||
static rb_encoding*
|
static rb_encoding*
|
||||||
io_read_encoding(rb_io_t *fptr)
|
io_read_encoding(rb_io_t *fptr)
|
||||||
{
|
{
|
||||||
|
@ -452,6 +469,9 @@ rb_io_check_writable(rb_io_t *fptr)
|
||||||
int
|
int
|
||||||
rb_io_read_pending(rb_io_t *fptr)
|
rb_io_read_pending(rb_io_t *fptr)
|
||||||
{
|
{
|
||||||
|
/* This function is used for bytes and chars. Confusing. */
|
||||||
|
if (READ_CHAR_PENDING(fptr))
|
||||||
|
return 1; /* should raise? */
|
||||||
return READ_DATA_PENDING(fptr);
|
return READ_DATA_PENDING(fptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1242,8 +1262,9 @@ rb_io_eof(VALUE io)
|
||||||
rb_io_t *fptr;
|
rb_io_t *fptr;
|
||||||
|
|
||||||
GetOpenFile(io, fptr);
|
GetOpenFile(io, fptr);
|
||||||
rb_io_check_readable(fptr);
|
rb_io_check_char_readable(fptr);
|
||||||
|
|
||||||
|
if (READ_CHAR_PENDING(fptr)) return Qfalse;
|
||||||
if (READ_DATA_PENDING(fptr)) return Qfalse;
|
if (READ_DATA_PENDING(fptr)) return Qfalse;
|
||||||
READ_CHECK(fptr);
|
READ_CHECK(fptr);
|
||||||
if (io_fillbuf(fptr) < 0) {
|
if (io_fillbuf(fptr) < 0) {
|
||||||
|
@ -1814,7 +1835,7 @@ io_getpartial(int argc, VALUE *argv, VALUE io, int nonblock)
|
||||||
OBJ_TAINT(str);
|
OBJ_TAINT(str);
|
||||||
|
|
||||||
GetOpenFile(io, fptr);
|
GetOpenFile(io, fptr);
|
||||||
rb_io_check_readable(fptr);
|
rb_io_check_byte_readable(fptr);
|
||||||
|
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
return str;
|
return str;
|
||||||
|
@ -2133,7 +2154,7 @@ io_read(int argc, VALUE *argv, VALUE io)
|
||||||
if (NIL_P(length)) {
|
if (NIL_P(length)) {
|
||||||
if (!NIL_P(str)) StringValue(str);
|
if (!NIL_P(str)) StringValue(str);
|
||||||
GetOpenFile(io, fptr);
|
GetOpenFile(io, fptr);
|
||||||
rb_io_check_readable(fptr);
|
rb_io_check_char_readable(fptr);
|
||||||
return read_all(fptr, remain_size(fptr), str);
|
return read_all(fptr, remain_size(fptr), str);
|
||||||
}
|
}
|
||||||
len = NUM2LONG(length);
|
len = NUM2LONG(length);
|
||||||
|
@ -2151,7 +2172,7 @@ io_read(int argc, VALUE *argv, VALUE io)
|
||||||
}
|
}
|
||||||
|
|
||||||
GetOpenFile(io, fptr);
|
GetOpenFile(io, fptr);
|
||||||
rb_io_check_readable(fptr);
|
rb_io_check_byte_readable(fptr);
|
||||||
if (len == 0) return str;
|
if (len == 0) return str;
|
||||||
|
|
||||||
READ_CHECK(fptr);
|
READ_CHECK(fptr);
|
||||||
|
@ -2385,7 +2406,7 @@ rb_io_getline_1(VALUE rs, long limit, VALUE io)
|
||||||
rb_encoding *enc;
|
rb_encoding *enc;
|
||||||
|
|
||||||
GetOpenFile(io, fptr);
|
GetOpenFile(io, fptr);
|
||||||
rb_io_check_readable(fptr);
|
rb_io_check_char_readable(fptr);
|
||||||
if (NIL_P(rs) && limit < 0) {
|
if (NIL_P(rs) && limit < 0) {
|
||||||
str = read_all(fptr, 0, Qnil);
|
str = read_all(fptr, 0, Qnil);
|
||||||
if (RSTRING_LEN(str) == 0) return Qnil;
|
if (RSTRING_LEN(str) == 0) return Qnil;
|
||||||
|
@ -2550,7 +2571,7 @@ rb_io_lineno(VALUE io)
|
||||||
rb_io_t *fptr;
|
rb_io_t *fptr;
|
||||||
|
|
||||||
GetOpenFile(io, fptr);
|
GetOpenFile(io, fptr);
|
||||||
rb_io_check_readable(fptr);
|
rb_io_check_char_readable(fptr);
|
||||||
return INT2NUM(fptr->lineno);
|
return INT2NUM(fptr->lineno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2577,7 +2598,7 @@ rb_io_set_lineno(VALUE io, VALUE lineno)
|
||||||
rb_io_t *fptr;
|
rb_io_t *fptr;
|
||||||
|
|
||||||
GetOpenFile(io, fptr);
|
GetOpenFile(io, fptr);
|
||||||
rb_io_check_readable(fptr);
|
rb_io_check_char_readable(fptr);
|
||||||
fptr->lineno = NUM2INT(lineno);
|
fptr->lineno = NUM2INT(lineno);
|
||||||
return lineno;
|
return lineno;
|
||||||
}
|
}
|
||||||
|
@ -2722,7 +2743,7 @@ rb_io_each_byte(VALUE io)
|
||||||
p++;
|
p++;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
}
|
}
|
||||||
rb_io_check_readable(fptr);
|
rb_io_check_byte_readable(fptr);
|
||||||
READ_CHECK(fptr);
|
READ_CHECK(fptr);
|
||||||
if (io_fillbuf(fptr) < 0) {
|
if (io_fillbuf(fptr) < 0) {
|
||||||
break;
|
break;
|
||||||
|
@ -2859,7 +2880,7 @@ rb_io_each_char(VALUE io)
|
||||||
|
|
||||||
RETURN_ENUMERATOR(io, 0, 0);
|
RETURN_ENUMERATOR(io, 0, 0);
|
||||||
GetOpenFile(io, fptr);
|
GetOpenFile(io, fptr);
|
||||||
rb_io_check_readable(fptr);
|
rb_io_check_char_readable(fptr);
|
||||||
|
|
||||||
enc = io_input_encoding(fptr);
|
enc = io_input_encoding(fptr);
|
||||||
READ_CHECK(fptr);
|
READ_CHECK(fptr);
|
||||||
|
@ -2899,7 +2920,7 @@ rb_io_each_codepoint(VALUE io)
|
||||||
|
|
||||||
RETURN_ENUMERATOR(io, 0, 0);
|
RETURN_ENUMERATOR(io, 0, 0);
|
||||||
GetOpenFile(io, fptr);
|
GetOpenFile(io, fptr);
|
||||||
rb_io_check_readable(fptr);
|
rb_io_check_char_readable(fptr);
|
||||||
|
|
||||||
READ_CHECK(fptr);
|
READ_CHECK(fptr);
|
||||||
if (NEED_READCONV(fptr)) {
|
if (NEED_READCONV(fptr)) {
|
||||||
|
@ -2989,7 +3010,7 @@ rb_io_getc(VALUE io)
|
||||||
rb_encoding *enc;
|
rb_encoding *enc;
|
||||||
|
|
||||||
GetOpenFile(io, fptr);
|
GetOpenFile(io, fptr);
|
||||||
rb_io_check_readable(fptr);
|
rb_io_check_char_readable(fptr);
|
||||||
|
|
||||||
enc = io_input_encoding(fptr);
|
enc = io_input_encoding(fptr);
|
||||||
READ_CHECK(fptr);
|
READ_CHECK(fptr);
|
||||||
|
@ -3038,7 +3059,7 @@ rb_io_getbyte(VALUE io)
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
GetOpenFile(io, fptr);
|
GetOpenFile(io, fptr);
|
||||||
rb_io_check_readable(fptr);
|
rb_io_check_byte_readable(fptr);
|
||||||
READ_CHECK(fptr);
|
READ_CHECK(fptr);
|
||||||
if (fptr->fd == 0 && (fptr->mode & FMODE_TTY) && TYPE(rb_stdout) == T_FILE) {
|
if (fptr->fd == 0 && (fptr->mode & FMODE_TTY) && TYPE(rb_stdout) == T_FILE) {
|
||||||
rb_io_t *ofp;
|
rb_io_t *ofp;
|
||||||
|
@ -3098,7 +3119,7 @@ rb_io_ungetbyte(VALUE io, VALUE b)
|
||||||
rb_io_t *fptr;
|
rb_io_t *fptr;
|
||||||
|
|
||||||
GetOpenFile(io, fptr);
|
GetOpenFile(io, fptr);
|
||||||
rb_io_check_readable(fptr);
|
rb_io_check_byte_readable(fptr);
|
||||||
io_unset_eof(fptr);
|
io_unset_eof(fptr);
|
||||||
if (NIL_P(b)) return Qnil;
|
if (NIL_P(b)) return Qnil;
|
||||||
if (FIXNUM_P(b)) {
|
if (FIXNUM_P(b)) {
|
||||||
|
@ -3135,7 +3156,7 @@ rb_io_ungetc(VALUE io, VALUE c)
|
||||||
long len;
|
long len;
|
||||||
|
|
||||||
GetOpenFile(io, fptr);
|
GetOpenFile(io, fptr);
|
||||||
rb_io_check_readable(fptr);
|
rb_io_check_char_readable(fptr);
|
||||||
io_unset_eof(fptr);
|
io_unset_eof(fptr);
|
||||||
if (NIL_P(c)) return Qnil;
|
if (NIL_P(c)) return Qnil;
|
||||||
if (FIXNUM_P(c)) {
|
if (FIXNUM_P(c)) {
|
||||||
|
@ -3739,7 +3760,8 @@ rb_io_sysseek(int argc, VALUE *argv, VALUE io)
|
||||||
}
|
}
|
||||||
pos = NUM2OFFT(offset);
|
pos = NUM2OFFT(offset);
|
||||||
GetOpenFile(io, fptr);
|
GetOpenFile(io, fptr);
|
||||||
if ((fptr->mode & FMODE_READABLE) && READ_DATA_BUFFERED(fptr)) {
|
if ((fptr->mode & FMODE_READABLE) &&
|
||||||
|
(READ_DATA_BUFFERED(fptr) || READ_CHAR_PENDING(fptr))) {
|
||||||
rb_raise(rb_eIOError, "sysseek for buffered IO");
|
rb_raise(rb_eIOError, "sysseek for buffered IO");
|
||||||
}
|
}
|
||||||
if ((fptr->mode & FMODE_WRITABLE) && fptr->wbuf_len) {
|
if ((fptr->mode & FMODE_WRITABLE) && fptr->wbuf_len) {
|
||||||
|
@ -3830,7 +3852,7 @@ rb_io_sysread(int argc, VALUE *argv, VALUE io)
|
||||||
if (ilen == 0) return str;
|
if (ilen == 0) return str;
|
||||||
|
|
||||||
GetOpenFile(io, fptr);
|
GetOpenFile(io, fptr);
|
||||||
rb_io_check_readable(fptr);
|
rb_io_check_byte_readable(fptr);
|
||||||
|
|
||||||
if (READ_DATA_BUFFERED(fptr)) {
|
if (READ_DATA_BUFFERED(fptr)) {
|
||||||
rb_raise(rb_eIOError, "sysread for buffered IO");
|
rb_raise(rb_eIOError, "sysread for buffered IO");
|
||||||
|
@ -8387,7 +8409,7 @@ copy_stream_body(VALUE arg)
|
||||||
stp->close_src = 1;
|
stp->close_src = 1;
|
||||||
}
|
}
|
||||||
GetOpenFile(src_io, src_fptr);
|
GetOpenFile(src_io, src_fptr);
|
||||||
rb_io_check_readable(src_fptr);
|
rb_io_check_byte_readable(src_fptr);
|
||||||
src_fd = src_fptr->fd;
|
src_fd = src_fptr->fd;
|
||||||
}
|
}
|
||||||
stp->src_fd = src_fd;
|
stp->src_fd = src_fd;
|
||||||
|
|
|
@ -1741,5 +1741,38 @@ EOT
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_cbuf
|
||||||
|
with_tmpdir {
|
||||||
|
fn = "tst"
|
||||||
|
open(fn, "w") {|f| f.print "foo" }
|
||||||
|
open(fn, "r+t") {|f|
|
||||||
|
f.ungetc(f.getc)
|
||||||
|
assert_raise(IOError, "[ruby-dev:40493]") { f.readpartial(2) }
|
||||||
|
assert_raise(IOError) { f.read(2) }
|
||||||
|
assert_raise(IOError) { f.each_byte {|c| } }
|
||||||
|
assert_raise(IOError) { f.getbyte }
|
||||||
|
assert_raise(IOError) { f.ungetbyte(0) }
|
||||||
|
assert_raise(IOError) { f.sysread(2) }
|
||||||
|
assert_raise(IOError) { IO.copy_stream(f, "tmpout") }
|
||||||
|
assert_raise(IOError) { f.sysseek(2) }
|
||||||
|
}
|
||||||
|
open(fn, "r+t") {|f|
|
||||||
|
f.ungetc(f.getc)
|
||||||
|
assert_equal("foo", f.read)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_text_mode_ungetc_eof
|
||||||
|
with_tmpdir {
|
||||||
|
open("ff", "w") {|f| }
|
||||||
|
open("ff", "rt") {|f|
|
||||||
|
f.ungetc "a"
|
||||||
|
assert(!f.eof?, "[ruby-dev:40506] (3)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче