Skip Menu |

This queue is for tickets about the Socket CPAN distribution.

Report information
The Basics
Id: 116699
Status: resolved
Priority: 0/
Queue: Socket

People
Owner: Nobody in particular
Requestors: justincase [...] yopmail.com
Cc:
AdminCc:

Bug Information
Severity: Critical
Broken in:
  • 2.022
  • 2.023
Fixed in: 2.024



Subject: 2.022+ breaks usage of undef port
Using an undef port is supposed to return a random available port. After 2.022, using an undef port results in an exception, at least on OS X: # <= 2.021 $ perl -MSocket=pack_sockaddr_in -E 'pack_sockaddr_in undef, 127.0.0.1; say "ok"' ok # 2.022, 2.023 $ perl -MSocket=pack_sockaddr_in -E 'pack_sockaddr_in undef, 127.0.0.1; say "ok"' Undefined port for Socket::pack_sockaddr_in at -e line 1.
On Wed Aug 03 14:58:49 2016, justincase wrote: Show quoted text
> Using an undef port is supposed to return a random available port.
As the sockaddr_in* structures contain simple C-level 'int' fields, there is no such thing as 'undef' at the kernel level. Setting a port to 0 is the way you request the kernel to allocate an ephemeral port. Use 0 instead. -- Paul Evans
From: justincase [...] yopmail.com
On Wed Aug 03 16:05:29 2016, PEVANS wrote: Show quoted text
> On Wed Aug 03 14:58:49 2016, justincase wrote:
> > Using an undef port is supposed to return a random available port.
> > As the sockaddr_in* structures contain simple C-level 'int' fields, > there is no such thing as 'undef' at the kernel level. Setting a port > to 0 is the way you request the kernel to allocate an ephemeral port. > > Use 0 instead.
In the name of backwards-compatibility, can you support undef to mean 0 inside Socket? It has worked that way for a very long time and would require code to be changed in many places and even other cpan modules.
On Wed Aug 03 17:15:17 2016, justincase wrote: Show quoted text
> In the name of backwards-compatibility, can you support undef to mean > 0 inside Socket? It has worked that way for a very long time and would > require code to be changed in many places and even other cpan modules.
Yes; annoyingly it seems that there is a lot of code around that presumes it can pass undef when it means 0. I guess I'll have to accept that as a synonym then. -- Paul Evans
Patched. -- Paul Evans
Subject: rt116699.patch
=== modified file 'Socket.pm' --- Socket.pm 2016-08-02 13:52:01 +0000 +++ Socket.pm 2016-08-10 15:39:04 +0000 @@ -184,6 +184,9 @@ this structure is normally what you need for the arguments in bind(), connect(), and send(). +An undefined $port argument is taken as zero; an undefined $ip_address is +considered a fatal error. + =head2 ($port, $ip_address) = unpack_sockaddr_in $sockaddr Takes a C<sockaddr_in> structure (as returned by pack_sockaddr_in(), @@ -213,6 +216,9 @@ number. Returns the C<sockaddr_in6> structure with those arguments packed in and C<AF_INET6> filled in. IPv6 equivalent of pack_sockaddr_in(). +An undefined $port argument is taken as zero; an undefined $ip6_address is +considered a fatal error. + =head2 ($port, $ip6_address, $scope_id, $flowinfo) = unpack_sockaddr_in6 $sockaddr Takes a C<sockaddr_in6> structure. Returns a list of four elements: the port === modified file 'Socket.xs' --- Socket.xs 2016-08-01 14:32:19 +0000 +++ Socket.xs 2016-08-10 15:39:04 +0000 @@ -945,11 +945,10 @@ struct sockaddr_in sin; struct in_addr addr; STRLEN addrlen; - unsigned short port; + unsigned short port = 0; char * ip_address; - if (!SvOK(port_sv)) - croak("Undefined port for %s", "Socket::pack_sockaddr_in"); - port = SvUV(port_sv); + if (SvOK(port_sv)) + port = SvUV(port_sv); if (!SvOK(ip_address_sv)) croak("Undefined address for %s", "Socket::pack_sockaddr_in"); if (DO_UTF8(ip_address_sv) && !sv_utf8_downgrade(ip_address_sv, 1)) @@ -1017,13 +1016,12 @@ CODE: { #ifdef HAS_SOCKADDR_IN6 - unsigned short port; + unsigned short port = 0; struct sockaddr_in6 sin6; char * addrbytes; STRLEN addrlen; - if (!SvOK(port_sv)) - croak("Undefined port for %s", "Socket::pack_sockaddr_in6"); - port = SvUV(port_sv); + if (SvOK(port_sv)) + port = SvUV(port_sv); if (!SvOK(sin6_addr)) croak("Undefined address for %s", "Socket::pack_sockaddr_in6"); if (DO_UTF8(sin6_addr) && !sv_utf8_downgrade(sin6_addr, 1)) === modified file 't/sockaddr.t' --- t/sockaddr.t 2016-08-02 13:48:33 +0000 +++ t/sockaddr.t 2016-08-10 15:39:04 +0000 @@ -83,13 +83,14 @@ my $warnings = 0; local $SIG{__WARN__} = sub { $warnings++ }; - ok( !eval { pack_sockaddr_in undef, ""; 1 }, - 'pack_sockaddr_in undef port is fatal' ); ok( !eval { pack_sockaddr_in 0, undef; 1 }, 'pack_sockaddr_in undef addr is fatal' ); ok( !eval { unpack_sockaddr_in undef; 1 }, 'unpack_sockaddr_in undef is fatal' ); + ok( eval { pack_sockaddr_in undef, "\0\0\0\0"; 1 }, + 'pack_sockaddr_in undef port is allowed' ); + is( $warnings, 0, 'undefined values produced no warnings' ); } @@ -118,13 +119,14 @@ my $warnings = 0; local $SIG{__WARN__} = sub { $warnings++ }; - ok( !eval { Socket::pack_sockaddr_in6( undef, "" ); 1 }, - 'pack_sockaddr_in6 undef port is fatal' ); ok( !eval { Socket::pack_sockaddr_in6( 0, undef ); 1 }, 'pack_sockaddr_in6 undef addr is fatal' ); ok( !eval { Socket::unpack_sockaddr_in6( undef ); 1 }, 'unpack_sockaddr_in6 undef is fatal' ); + ok( eval { Socket::pack_sockaddr_in6( undef, "\0"x16 ); 1 }, + 'pack_sockaddr_in6 undef port is allowed' ); + is( $warnings, 0, 'undefined values produced no warnings' ); }
Was released in 2.024 -- Paul Evans