summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2010-04-24 05:42:50 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2010-04-24 05:42:50 +0000
commit78db46b31c4472291f4e45cf0374853ac3c5740a (patch)
treeb192bb6730f4a59338bda792267c3fb6909742f7
parent7309f9cc007f1cc05eb70967356069161d867356 (diff)
* 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
-rw-r--r--ChangeLog6
-rw-r--r--io.c58
-rw-r--r--test/ruby/test_io_m17n.rb33
3 files changed, 79 insertions, 18 deletions
diff --git a/ChangeLog b/ChangeLog
index 9ada39f61d..785637a5fe 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/io.c b/io.c
index f7bff6b0b0..23ea18f4db 100644
--- a/io.c
+++ b/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;
diff --git a/test/ruby/test_io_m17n.rb b/test/ruby/test_io_m17n.rb
index 1220170e1b..98a52939d0 100644
--- a/test/ruby/test_io_m17n.rb
+++ b/test/ruby/test_io_m17n.rb
@@ -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