Skip to content

Commit 3c1f9b8

Browse files
authored
Avoid direct access to IO internals. (#301)
1 parent 779500b commit 3c1f9b8

File tree

4 files changed

+42
-17
lines changed

4 files changed

+42
-17
lines changed

ext/nio4r/bytebuffer.c

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,26 @@ static VALUE NIO_ByteBuffer_inspect(VALUE self);
3636

3737
#define MARK_UNSET -1
3838

39+
/* Compatibility for Ruby <= 3.1 */
40+
#ifndef HAVE_RB_IO_DESCRIPTOR
41+
static int
42+
io_descriptor_fallback(VALUE io)
43+
{
44+
rb_io_t *fptr;
45+
GetOpenFile(io, fptr);
46+
return fptr->fd;
47+
}
48+
#define rb_io_descriptor io_descriptor_fallback
49+
#endif
50+
51+
static void
52+
io_set_nonblock(VALUE io)
53+
{
54+
rb_io_t *fptr;
55+
GetOpenFile(io, fptr);
56+
rb_io_set_nonblock(fptr);
57+
}
58+
3959
void Init_NIO_ByteBuffer()
4060
{
4161
mNIO = rb_define_module("NIO");
@@ -281,19 +301,19 @@ static VALUE NIO_ByteBuffer_put(VALUE self, VALUE string)
281301
static VALUE NIO_ByteBuffer_read_from(VALUE self, VALUE io)
282302
{
283303
struct NIO_ByteBuffer *buffer;
284-
rb_io_t *fptr;
285304
ssize_t nbytes, bytes_read;
286305

287306
Data_Get_Struct(self, struct NIO_ByteBuffer, buffer);
288-
GetOpenFile(rb_convert_type(io, T_FILE, "IO", "to_io"), fptr);
289-
rb_io_set_nonblock(fptr);
307+
308+
io = rb_convert_type(io, T_FILE, "IO", "to_io");
309+
io_set_nonblock(io);
290310

291311
nbytes = buffer->limit - buffer->position;
292312
if (nbytes == 0) {
293313
rb_raise(cNIO_ByteBuffer_OverflowError, "buffer is full");
294314
}
295315

296-
bytes_read = read(FPTR_TO_FD(fptr), buffer->buffer + buffer->position, nbytes);
316+
bytes_read = read(rb_io_descriptor(io), buffer->buffer + buffer->position, nbytes);
297317

298318
if (bytes_read < 0) {
299319
if (errno == EAGAIN) {
@@ -311,19 +331,18 @@ static VALUE NIO_ByteBuffer_read_from(VALUE self, VALUE io)
311331
static VALUE NIO_ByteBuffer_write_to(VALUE self, VALUE io)
312332
{
313333
struct NIO_ByteBuffer *buffer;
314-
rb_io_t *fptr;
315334
ssize_t nbytes, bytes_written;
316335

317336
Data_Get_Struct(self, struct NIO_ByteBuffer, buffer);
318-
GetOpenFile(rb_convert_type(io, T_FILE, "IO", "to_io"), fptr);
319-
rb_io_set_nonblock(fptr);
337+
io = rb_convert_type(io, T_FILE, "IO", "to_io");
338+
io_set_nonblock(io);
320339

321340
nbytes = buffer->limit - buffer->position;
322341
if (nbytes == 0) {
323342
rb_raise(cNIO_ByteBuffer_UnderflowError, "no data remaining in buffer");
324343
}
325344

326-
bytes_written = write(FPTR_TO_FD(fptr), buffer->buffer + buffer->position, nbytes);
345+
bytes_written = write(rb_io_descriptor(io), buffer->buffer + buffer->position, nbytes);
327346

328347
if (bytes_written < 0) {
329348
if (errno == EAGAIN) {

ext/nio4r/extconf.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
require "mkmf"
1717

1818
have_header("unistd.h")
19+
have_func("rb_io_descriptor")
1920

2021
$defs << "-DEV_USE_LINUXAIO" if have_header("linux/aio_abi.h")
2122
$defs << "-DEV_USE_IOURING" if have_header("linux/io_uring.h")

ext/nio4r/monitor.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,18 @@ static VALUE NIO_Monitor_readiness(VALUE self);
3434
static int NIO_Monitor_symbol2interest(VALUE interests);
3535
static void NIO_Monitor_update_interests(VALUE self, int interests);
3636

37+
/* Compatibility for Ruby <= 3.1 */
38+
#ifndef HAVE_RB_IO_DESCRIPTOR
39+
static int
40+
io_descriptor_fallback(VALUE io)
41+
{
42+
rb_io_t *fptr;
43+
GetOpenFile(io, fptr);
44+
return fptr->fd;
45+
}
46+
#define rb_io_descriptor io_descriptor_fallback
47+
#endif
48+
3749
/* Monitor control how a channel is being waited for by a monitor */
3850
void Init_NIO_Monitor()
3951
{
@@ -81,7 +93,6 @@ static VALUE NIO_Monitor_initialize(VALUE self, VALUE io, VALUE interests, VALUE
8193
struct NIO_Monitor *monitor;
8294
struct NIO_Selector *selector;
8395
ID interests_id;
84-
rb_io_t *fptr;
8596

8697
interests_id = SYM2ID(interests);
8798

@@ -97,8 +108,8 @@ static VALUE NIO_Monitor_initialize(VALUE self, VALUE io, VALUE interests, VALUE
97108
rb_raise(rb_eArgError, "invalid event type %s (must be :r, :w, or :rw)", RSTRING_PTR(rb_funcall(interests, rb_intern("inspect"), 0)));
98109
}
99110

100-
GetOpenFile(rb_convert_type(io, T_FILE, "IO", "to_io"), fptr);
101-
ev_io_init(&monitor->ev_io, NIO_Selector_monitor_callback, FPTR_TO_FD(fptr), monitor->interests);
111+
io = rb_convert_type(io, T_FILE, "IO", "to_io");
112+
ev_io_init(&monitor->ev_io, NIO_Selector_monitor_callback, rb_io_descriptor(io), monitor->interests);
102113

103114
rb_ivar_set(self, rb_intern("io"), io);
104115
rb_ivar_set(self, rb_intern("interests"), interests);

ext/nio4r/nio4r.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,6 @@ struct NIO_ByteBuffer {
4040
int position, limit, capacity, mark;
4141
};
4242

43-
#ifdef GetReadFile
44-
#define FPTR_TO_FD(fptr) (fileno(GetReadFile(fptr)))
45-
#else
46-
#define FPTR_TO_FD(fptr) fptr->fd
47-
#endif /* GetReadFile */
48-
4943
/* Thunk between libev callbacks in NIO::Monitors and NIO::Selectors */
5044
void NIO_Selector_monitor_callback(struct ev_loop *ev_loop, struct ev_io *io, int revents);
5145

0 commit comments

Comments
 (0)