summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2020-04-28 17:59:40 +0900
committerHiroshi Mimaki <[email protected]>2020-05-07 09:32:46 +0900
commit6b839b231971f058656521dc39bd4f27968230c6 (patch)
tree3ea028c51527b22ec189dd2d9c0344b48b1735b3
parent45bd372755171cee72fd547f3295653918231f77 (diff)
downloadmruby-6b839b231971f058656521dc39bd4f27968230c6.tar.gz
mruby-6b839b231971f058656521dc39bd4f27968230c6.zip
Fix `IO#readchar` to return broken UTF-8 rather than `EOF` error.
The behavior is different from CRuby, but we believe this is a right behavior for mruby, which only supports either ASCII or UTF-8 exclusively; fix #4983, ref #4982 ``` $ printf '\xe3\x81' | ruby -e 'p STDIN.readchar' "\xE3\x81" ``` ``` $ printf '\xe3\x81' | mruby -e 'p STDIN.readchar' "\xE3" ```
-rw-r--r--mrbgems/mruby-io/mrblib/io.rb5
-rw-r--r--mrbgems/mruby-io/src/io.c17
2 files changed, 16 insertions, 6 deletions
diff --git a/mrbgems/mruby-io/mrblib/io.rb b/mrbgems/mruby-io/mrblib/io.rb
index e43b81004..e597db886 100644
--- a/mrbgems/mruby-io/mrblib/io.rb
+++ b/mrbgems/mruby-io/mrblib/io.rb
@@ -284,15 +284,14 @@ class IO
def readchar
_read_buf
_readchar(@buf)
-# c = @buf[0]
-# @buf[0] = ""
-# c
end
def getc
begin
readchar
rescue EOFError
+ c = @buf[0]
+ @buf[0,1]="" if c
nil
end
end
diff --git a/mrbgems/mruby-io/src/io.c b/mrbgems/mruby-io/src/io.c
index 332539ba5..b28223f36 100644
--- a/mrbgems/mruby-io/src/io.c
+++ b/mrbgems/mruby-io/src/io.c
@@ -1451,14 +1451,25 @@ mrb_io_readchar(mrb_state *mrb, mrb_value self)
mrb_get_args(mrb, "S", &buf);
mrb_assert(RSTRING_PTR(buf) > 0);
+ mrb_str_modify(mrb, RSTRING(buf));
#ifdef MRB_UTF8_STRING
c = RSTRING_PTR(buf)[0];
if (c & 0x80) {
len = mrb_utf8len(RSTRING_PTR(buf), RSTRING_END(buf));
- if (len == 1 && RSTRING_LEN(buf) < 5) { /* partial UTF-8 */
+ if (len == 1 && RSTRING_LEN(buf) < 4) { /* partial UTF-8 */
+ mrb_int blen = RSTRING_LEN(buf);
+ ssize_t n;
+
+ struct mrb_io *fptr = (struct mrb_io*)io_get_open_fptr(mrb, self);
+
+ if (!fptr->readable) {
+ mrb_raise(mrb, E_IO_ERROR, "not opened for reading");
+ }
/* refill the buffer */
- mrb_value b = mrb_io_sysread_common(mrb, mrb_sysread_dummy, self, mrb_nil_value(), 4096, 0);
- mrb_str_concat(mrb, buf, b);
+ mrb_str_resize(mrb, buf, 4096);
+ n = read(fptr->fd, RSTRING_PTR(buf)+blen, 4096-blen);
+ if (n < 0) mrb_sys_fail(mrb, "sysread failed");
+ mrb_str_resize(mrb, buf, blen+n);
}
len = mrb_utf8len(RSTRING_PTR(buf), RSTRING_END(buf));
}