From 028441d22fee121d129126c55938690be38bd3d9 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Mon, 12 Jul 2021 16:28:43 +1200 Subject: [PATCH] Avoid calling `fstat` on things we already know are valid sockets. --- ext/socket/basicsocket.c | 30 ++++++++++++++++++++++++++++-- ext/socket/init.c | 18 ------------------ 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/ext/socket/basicsocket.c b/ext/socket/basicsocket.c index 05172100c8..8477a37a6d 100644 --- a/ext/socket/basicsocket.c +++ b/ext/socket/basicsocket.c @@ -10,6 +10,28 @@ #include "rubysocket.h" +#ifdef _WIN32 +#define is_socket(fd) rb_w32_is_socket(fd) +#else +static int +is_socket(int fd) +{ + struct stat sbuf; + + if (fstat(fd, &sbuf) < 0) + rb_sys_fail("fstat(2)"); + return S_ISSOCK(sbuf.st_mode); +} +#endif + +static void +rsock_validate_descriptor(int descriptor) +{ + if (!is_socket(descriptor) || rb_reserved_fd_p(descriptor)) { + rb_syserr_fail(EBADF, "not a socket file descriptor"); + } +} + /* * call-seq: * BasicSocket.for_fd(fd) => basicsocket @@ -22,10 +44,14 @@ * */ static VALUE -bsock_s_for_fd(VALUE klass, VALUE fd) +bsock_s_for_fd(VALUE klass, VALUE _descriptor) { rb_io_t *fptr; - VALUE sock = rsock_init_sock(rb_obj_alloc(klass), NUM2INT(fd)); + + int descriptor = RB_NUM2INT(_descriptor); + rsock_validate_descriptor(descriptor); + + VALUE sock = rsock_init_sock(rb_obj_alloc(klass), descriptor); GetOpenFile(sock, fptr); diff --git a/ext/socket/init.c b/ext/socket/init.c index 5859c33e29..359696e626 100644 --- a/ext/socket/init.c +++ b/ext/socket/init.c @@ -54,20 +54,6 @@ rsock_raise_socket_error(const char *reason, int error) #endif } -#ifdef _WIN32 -#define is_socket(fd) rb_w32_is_socket(fd) -#else -static int -is_socket(int fd) -{ - struct stat sbuf; - - if (fstat(fd, &sbuf) < 0) - rb_sys_fail("fstat(2)"); - return S_ISSOCK(sbuf.st_mode); -} -#endif - #if defined __APPLE__ # define do_write_retry(code) do {ret = code;} while (ret == -1 && errno == EPROTOTYPE) #else @@ -79,10 +65,6 @@ rsock_init_sock(VALUE sock, int fd) { rb_io_t *fp; - if (!is_socket(fd) || rb_reserved_fd_p(fd)) { - rb_syserr_fail(EBADF, "not a socket file descriptor"); - } - rb_update_max_fd(fd); MakeOpenFile(sock, fp); fp->fd = fd;