зеркало из 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>
|
||||
|
||||
* 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_BUFFERED(fptr) READ_DATA_PENDING(fptr)
|
||||
|
||||
#define READ_CHAR_PENDING(fptr) ((fptr)->cbuf_len)
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define WAIT_FD_IN_WIN32(fptr) rb_thread_wait_fd((fptr)->fd);
|
||||
#else
|
||||
|
@ -401,7 +403,7 @@ flush_before_seek(rb_io_t *fptr)
|
|||
#define FMODE_SYNCWRITE (FMODE_SYNC|FMODE_WRITABLE)
|
||||
|
||||
void
|
||||
rb_io_check_readable(rb_io_t *fptr)
|
||||
rb_io_check_char_readable(rb_io_t *fptr)
|
||||
{
|
||||
rb_io_check_closed(fptr);
|
||||
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*
|
||||
io_read_encoding(rb_io_t *fptr)
|
||||
{
|
||||
|
@ -452,6 +469,9 @@ rb_io_check_writable(rb_io_t *fptr)
|
|||
int
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1242,8 +1262,9 @@ rb_io_eof(VALUE io)
|
|||
rb_io_t *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;
|
||||
READ_CHECK(fptr);
|
||||
if (io_fillbuf(fptr) < 0) {
|
||||
|
@ -1814,7 +1835,7 @@ io_getpartial(int argc, VALUE *argv, VALUE io, int nonblock)
|
|||
OBJ_TAINT(str);
|
||||
|
||||
GetOpenFile(io, fptr);
|
||||
rb_io_check_readable(fptr);
|
||||
rb_io_check_byte_readable(fptr);
|
||||
|
||||
if (len == 0)
|
||||
return str;
|
||||
|
@ -2133,7 +2154,7 @@ io_read(int argc, VALUE *argv, VALUE io)
|
|||
if (NIL_P(length)) {
|
||||
if (!NIL_P(str)) StringValue(str);
|
||||
GetOpenFile(io, fptr);
|
||||
rb_io_check_readable(fptr);
|
||||
rb_io_check_char_readable(fptr);
|
||||
return read_all(fptr, remain_size(fptr), str);
|
||||
}
|
||||
len = NUM2LONG(length);
|
||||
|
@ -2151,7 +2172,7 @@ io_read(int argc, VALUE *argv, VALUE io)
|
|||
}
|
||||
|
||||
GetOpenFile(io, fptr);
|
||||
rb_io_check_readable(fptr);
|
||||
rb_io_check_byte_readable(fptr);
|
||||
if (len == 0) return str;
|
||||
|
||||
READ_CHECK(fptr);
|
||||
|
@ -2385,7 +2406,7 @@ rb_io_getline_1(VALUE rs, long limit, VALUE io)
|
|||
rb_encoding *enc;
|
||||
|
||||
GetOpenFile(io, fptr);
|
||||
rb_io_check_readable(fptr);
|
||||
rb_io_check_char_readable(fptr);
|
||||
if (NIL_P(rs) && limit < 0) {
|
||||
str = read_all(fptr, 0, Qnil);
|
||||
if (RSTRING_LEN(str) == 0) return Qnil;
|
||||
|
@ -2550,7 +2571,7 @@ rb_io_lineno(VALUE io)
|
|||
rb_io_t *fptr;
|
||||
|
||||
GetOpenFile(io, fptr);
|
||||
rb_io_check_readable(fptr);
|
||||
rb_io_check_char_readable(fptr);
|
||||
return INT2NUM(fptr->lineno);
|
||||
}
|
||||
|
||||
|
@ -2577,7 +2598,7 @@ rb_io_set_lineno(VALUE io, VALUE lineno)
|
|||
rb_io_t *fptr;
|
||||
|
||||
GetOpenFile(io, fptr);
|
||||
rb_io_check_readable(fptr);
|
||||
rb_io_check_char_readable(fptr);
|
||||
fptr->lineno = NUM2INT(lineno);
|
||||
return lineno;
|
||||
}
|
||||
|
@ -2722,7 +2743,7 @@ rb_io_each_byte(VALUE io)
|
|||
p++;
|
||||
errno = 0;
|
||||
}
|
||||
rb_io_check_readable(fptr);
|
||||
rb_io_check_byte_readable(fptr);
|
||||
READ_CHECK(fptr);
|
||||
if (io_fillbuf(fptr) < 0) {
|
||||
break;
|
||||
|
@ -2859,7 +2880,7 @@ rb_io_each_char(VALUE io)
|
|||
|
||||
RETURN_ENUMERATOR(io, 0, 0);
|
||||
GetOpenFile(io, fptr);
|
||||
rb_io_check_readable(fptr);
|
||||
rb_io_check_char_readable(fptr);
|
||||
|
||||
enc = io_input_encoding(fptr);
|
||||
READ_CHECK(fptr);
|
||||
|
@ -2899,7 +2920,7 @@ rb_io_each_codepoint(VALUE io)
|
|||
|
||||
RETURN_ENUMERATOR(io, 0, 0);
|
||||
GetOpenFile(io, fptr);
|
||||
rb_io_check_readable(fptr);
|
||||
rb_io_check_char_readable(fptr);
|
||||
|
||||
READ_CHECK(fptr);
|
||||
if (NEED_READCONV(fptr)) {
|
||||
|
@ -2989,7 +3010,7 @@ rb_io_getc(VALUE io)
|
|||
rb_encoding *enc;
|
||||
|
||||
GetOpenFile(io, fptr);
|
||||
rb_io_check_readable(fptr);
|
||||
rb_io_check_char_readable(fptr);
|
||||
|
||||
enc = io_input_encoding(fptr);
|
||||
READ_CHECK(fptr);
|
||||
|
@ -3038,7 +3059,7 @@ rb_io_getbyte(VALUE io)
|
|||
int c;
|
||||
|
||||
GetOpenFile(io, fptr);
|
||||
rb_io_check_readable(fptr);
|
||||
rb_io_check_byte_readable(fptr);
|
||||
READ_CHECK(fptr);
|
||||
if (fptr->fd == 0 && (fptr->mode & FMODE_TTY) && TYPE(rb_stdout) == T_FILE) {
|
||||
rb_io_t *ofp;
|
||||
|
@ -3098,7 +3119,7 @@ rb_io_ungetbyte(VALUE io, VALUE b)
|
|||
rb_io_t *fptr;
|
||||
|
||||
GetOpenFile(io, fptr);
|
||||
rb_io_check_readable(fptr);
|
||||
rb_io_check_byte_readable(fptr);
|
||||
io_unset_eof(fptr);
|
||||
if (NIL_P(b)) return Qnil;
|
||||
if (FIXNUM_P(b)) {
|
||||
|
@ -3135,7 +3156,7 @@ rb_io_ungetc(VALUE io, VALUE c)
|
|||
long len;
|
||||
|
||||
GetOpenFile(io, fptr);
|
||||
rb_io_check_readable(fptr);
|
||||
rb_io_check_char_readable(fptr);
|
||||
io_unset_eof(fptr);
|
||||
if (NIL_P(c)) return Qnil;
|
||||
if (FIXNUM_P(c)) {
|
||||
|
@ -3739,7 +3760,8 @@ rb_io_sysseek(int argc, VALUE *argv, VALUE io)
|
|||
}
|
||||
pos = NUM2OFFT(offset);
|
||||
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");
|
||||
}
|
||||
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;
|
||||
|
||||
GetOpenFile(io, fptr);
|
||||
rb_io_check_readable(fptr);
|
||||
rb_io_check_byte_readable(fptr);
|
||||
|
||||
if (READ_DATA_BUFFERED(fptr)) {
|
||||
rb_raise(rb_eIOError, "sysread for buffered IO");
|
||||
|
@ -8387,7 +8409,7 @@ copy_stream_body(VALUE arg)
|
|||
stp->close_src = 1;
|
||||
}
|
||||
GetOpenFile(src_io, src_fptr);
|
||||
rb_io_check_readable(src_fptr);
|
||||
rb_io_check_byte_readable(src_fptr);
|
||||
src_fd = src_fptr->fd;
|
||||
}
|
||||
stp->src_fd = src_fd;
|
||||
|
|
|
@ -1741,5 +1741,38 @@ EOT
|
|||
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
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче