Skip to content

Commit c650fa8

Browse files
authored
Merge pull request #486 from spolack/socket-fix-fd-on-64bit-big-endian
socket: fix the file descriptor on 64-bit big-endian
2 parents fa288dd + a18924e commit c650fa8

3 files changed

Lines changed: 52 additions & 5 deletions

File tree

‎lib/socket.c‎

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ args_get_(uc_vm_t *vm, size_t nargs, int *fdptr, ...)
181181
uc_value_t **ptr, *arg;
182182
uc_type_t type, t;
183183
size_t index = 0;
184-
int *sockfd;
184+
intptr_t *sockfd;
185185
va_list ap;
186186
bool opt;
187187

@@ -943,9 +943,9 @@ static bool
943943
uv_to_fileno(uc_vm_t *vm, uc_value_t *val, int *fileno)
944944
{
945945
uc_value_t *fn;
946-
int *fdptr;
946+
intptr_t *fdptr;
947947

948-
fdptr = (int *)ucv_resource_dataptr(val, "socket");
948+
fdptr = (intptr_t *)ucv_resource_dataptr(val, "socket");
949949

950950
if (fdptr) {
951951
if (*fdptr < 0)
@@ -5078,12 +5078,16 @@ uc_socket_inst_sockname(uc_vm_t *vm, size_t nargs)
50785078
static uc_value_t *
50795079
uc_socket_inst_close(uc_vm_t *vm, size_t nargs)
50805080
{
5081-
int *sockfd = uc_fn_this("socket");
5081+
intptr_t *sockfd = uc_fn_this("socket");
5082+
int fd;
50825083

50835084
if (!sockfd || *sockfd == -1)
50845085
err_return(EBADF, "Invalid socket context");
50855086

5086-
if (!xclose(sockfd))
5087+
fd = *sockfd;
5088+
*sockfd = -1;
5089+
5090+
if (!xclose(&fd))
50875091
err_return(errno, "close()");
50885092

50895093
ok_return(ucv_boolean_new(true));
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
Test that a socket reports and closes its own file descriptor.
2+
3+
The descriptor is stored in the data pointer of the socket resource and
4+
was read back through an `int *`. On 64-bit big-endian systems that
5+
yields the upper half of the pointer: `fileno()` returned 0 for every
6+
socket and `close()` closed descriptor 0 instead of the socket.
7+
8+
The failure only shows on a 64-bit big-endian build, on other systems
9+
this test passes regardless of the fix.
10+
11+
-- Testcase --
12+
{%
13+
import * as socket from 'socket';
14+
import * as fs from 'fs';
15+
16+
let s1 = socket.create(socket.AF_INET, socket.SOCK_DGRAM, 0);
17+
let s2 = socket.create(socket.AF_INET, socket.SOCK_DGRAM, 0);
18+
let fd1 = s1.fileno(), fd2 = s2.fileno();
19+
20+
printf("fds_valid=%s fds_distinct=%s\n",
21+
(fd1 > 2 && fd2 > 2) ? "yes" : "no",
22+
(fd1 != fd2) ? "yes" : "no");
23+
24+
printf("close=%s\n", s1.close());
25+
printf("fd_released=%s\n", fs.stat(`/proc/self/fd/${fd1}`) == null ? "yes" : "no");
26+
printf("stdin_open=%s\n", fs.stat("/proc/self/fd/0") != null ? "yes" : "no");
27+
28+
printf("fileno_after_close=%J error=%s\n", s1.fileno(), socket.error());
29+
printf("close_after_close=%J error=%s\n", s1.close(), socket.error());
30+
31+
printf("other_socket_intact=%s\n", s2.fileno() == fd2 ? "yes" : "no");
32+
%}
33+
-- End --
34+
35+
-- Expect stdout --
36+
fds_valid=yes fds_distinct=yes
37+
close=true
38+
fd_released=yes
39+
stdin_open=yes
40+
fileno_after_close=null error=Invalid socket context: Bad file descriptor
41+
close_after_close=null error=Invalid socket context: Bad file descriptor
42+
other_socket_intact=yes
43+
-- End --
File renamed without changes.

0 commit comments

Comments
 (0)