Check the file descriptor with `IO#initialize`; resolve
MODIFY
mrbgems/mruby-io/src/io.c
mrbgems/mruby-io/src/io.c
@@ -645,6 +645,43 @@ mrb_io_initialize_copy(mrb_state *mrb, mrb_value copy)
return copy;
}
+static void
+check_file_descriptor(mrb_state *mrb, mrb_int fd)
+{
+ struct stat sb;
+ int fdi = (int)fd;
+
+#if MRB_INT_MIN < INT_MIN || MRB_INT_MAX > INT_MAX
+ if (fdi != fd) {
+ goto badfd;
+ }
+#endif
+
+#ifdef _WIN32
+ {
+ DWORD err;
+ int len = sizeof(err);
+
+ if (getsockopt(fdi, SOL_SOCKET, SO_ERROR, (char*)&err, &len) == 0) {
+ return;
+ }
+ }
+
+ if (fdi < 0 || fdi > _getmaxstdio()) {
+ goto badfd;
+ }
+#endif /* _WIN32 */
+
+ if (fstat(fdi, &sb) != 0) {
+ goto badfd;
+ }
+
+ return;
+
+badfd:
+ mrb_sys_fail(mrb, "bad file descriptor");
+}
+
mrb_value
mrb_io_initialize(mrb_state *mrb, mrb_value io)
{
@@ -656,6 +693,7 @@ mrb_io_initialize(mrb_state *mrb, mrb_value io)
mode = opt = mrb_nil_value();
mrb_get_args(mrb, "i|oo", &fd, &mode, &opt);
+ check_file_descriptor(mrb, fd);
if (mrb_nil_p(mode)) {
mode = mrb_str_new_cstr(mrb, "r");
}

MODIFY
mrbgems/mruby-io/test/io.rb
mrbgems/mruby-io/test/io.rb
@@ -24,6 +24,10 @@ def assert_io_open(meth)
end
end
io2.close unless meth == :open
+
+ assert_raise(RuntimeError) { IO.__send__(meth, 1023) } # For Windows
+ assert_raise(RuntimeError) { IO.__send__(meth, 1 << 26) }
+ assert_raise(RuntimeError) { IO.__send__(meth, 1 << 32) } if (1 << 32).kind_of?(Integer)
end
end

Check the file descriptor with `IO#initialize`; resolve #4966