Skip to content

Commit b98784e

Browse files
committed
mruby-socket: declare both arguments of IPSocket.ntop
IPSocket.ntop(af, addr) was defined with MRB_ARGS_REQ(1) and reads two arguments. Since the VM started checking a C method's declared arity, every call with two arguments raises "wrong number of arguments (given 2, expected 1)", and a call with one fails in mrb_get_args, so the method can't be called at all. The length check only looked at the two families it knows, before the (int) cast, so (1 << 32) + Socket::AF_INET6 skipped it and then read 16 bytes as AF_INET6 whatever the length of addr. Accept only AF_INET with 4 bytes and AF_INET6 with 16; inet_ntop refused any other family anyway.
1 parent e0cf7fa commit b98784e

2 files changed

Lines changed: 20 additions & 2 deletions

File tree

‎mrbgems/mruby-socket/src/socket.c‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -933,7 +933,7 @@ mrb_ipsocket_ntop(mrb_state *mrb, mrb_value klass)
933933
char buf[50];
934934

935935
mrb_get_args(mrb, "is", &af, &addr, &n);
936-
if ((af == AF_INET && n != 4) || (af == AF_INET6 && n != 16) ||
936+
if (!((af == AF_INET && n == 4) || (af == AF_INET6 && n == 16)) ||
937937
mrb_hal_socket_inet_ntop((int)af, addr, buf, sizeof(buf)) == NULL)
938938
mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid address");
939939
return mrb_str_new_cstr(mrb, buf);
@@ -1431,7 +1431,7 @@ mrb_mruby_socket_gem_init(mrb_state* mrb)
14311431
struct RClass *bsock = mrb_define_class_id(mrb, MRB_SYM(BasicSocket), io);
14321432

14331433
struct RClass *ipsock = mrb_define_class_id(mrb, MRB_SYM(IPSocket), bsock);
1434-
mrb_define_class_method_id(mrb, ipsock, MRB_SYM(ntop), mrb_ipsocket_ntop, MRB_ARGS_REQ(1));
1434+
mrb_define_class_method_id(mrb, ipsock, MRB_SYM(ntop), mrb_ipsocket_ntop, MRB_ARGS_REQ(2));
14351435
mrb_define_class_method_id(mrb, ipsock, MRB_SYM(pton), mrb_ipsocket_pton, MRB_ARGS_REQ(2));
14361436

14371437
struct RClass *tcpsock = mrb_define_class_id(mrb, MRB_SYM(TCPSocket), ipsock);

‎mrbgems/mruby-socket/test/ipsocket.rb‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,24 @@
1414
assert_raise(ArgumentError) { IPSocket.pton(Socket::AF_INET6, "::1\0junk") }
1515
end
1616

17+
assert('IPSocket.ntop') do
18+
assert_equal "1.2.3.4", IPSocket.ntop(Socket::AF_INET, "\x01\x02\x03\x04")
19+
assert_equal "::1", IPSocket.ntop(Socket::AF_INET6, "\0" * 15 + "\x01")
20+
assert_raise(ArgumentError) { IPSocket.ntop(Socket::AF_INET, "\x01\x02\x03") }
21+
assert_raise(ArgumentError) { IPSocket.ntop(Socket::AF_INET6, "\x01\x02\x03\x04") }
22+
assert_raise(ArgumentError) { IPSocket.ntop(Socket::AF_UNSPEC, "\x01\x02\x03\x04") }
23+
24+
# A family past C int is not the family it would be cut down to. Computed, not
25+
# written out, so the file still compiles where mrb_int is 32 bits.
26+
shift = 32
27+
big = begin
28+
1 << shift
29+
rescue RangeError
30+
nil
31+
end
32+
assert_raise(ArgumentError) { IPSocket.ntop(big + Socket::AF_INET6, "\x01") } if big
33+
end
34+
1735
assert('IPSocket.addr') do
1836
localhost = "127.0.0.1"
1937
s = UDPSocket.new

0 commit comments

Comments
 (0)