summaryrefslogtreecommitdiff
path: root/ext/socket/basicsocket.c
diff options
context:
space:
mode:
authorSamuel Williams <samuel.williams@oriontransfer.co.nz>2021-07-12 16:28:43 +1200
committerSamuel Williams <samuel.williams@oriontransfer.co.nz>2021-07-12 19:16:22 +1200
commit028441d22fee121d129126c55938690be38bd3d9 (patch)
treec7911aaf9fbcd5c895e4ecf516c701e1072a2bc2 /ext/socket/basicsocket.c
parent0895d57d3115f162dcb6cff82da1834a7241633e (diff)
Avoid calling `fstat` on things we already know are valid sockets.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/4645
Diffstat (limited to 'ext/socket/basicsocket.c')
-rw-r--r--ext/socket/basicsocket.c30
1 files changed, 28 insertions, 2 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);