diff options
author | David Mitchell <davem@iabyn.com> | 2013-02-24 16:46:19 +0000 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2013-02-24 20:27:17 +0000 |
commit | e5086424505dcbfc5e26aeb984b769ecf5ffed01 (patch) | |
tree | 73f2d799d21fc90042fd92c31e888d7d690d718c | |
parent | 7f5f08b152bb9d0c88efd1dd0f70d45e427efe1c (diff) | |
download | perl-e5086424505dcbfc5e26aeb984b769ecf5ffed01.tar.gz |
Socket::unpack_sockaddr_un heap-buffer-overflow
[perl #111594]
A (fairly harmless) read buffer overflow can occur when copying sockaddr
buffers. Cherry-pick the fix from Socket 2.009 to keep ASAN happy.
-rw-r--r-- | ext/Socket/Socket.xs | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/ext/Socket/Socket.xs b/ext/Socket/Socket.xs index 9214fc15bb..e5abb71912 100644 --- a/ext/Socket/Socket.xs +++ b/ext/Socket/Socket.xs @@ -557,18 +557,22 @@ unpack_sockaddr_un(sun_sv) STRLEN sockaddrlen; char * sun_ad = SvPVbyte(sun_sv,sockaddrlen); int addr_len; -# ifndef __linux__ +# ifdef __linux__ /* On Linux sockaddrlen on sockets returned by accept, recvfrom, getpeername and getsockname is not equal to sizeof(addr). */ - if (sockaddrlen != sizeof(addr)) { - croak("Bad arg length for %s, length is %d, should be %d", - "Socket::unpack_sockaddr_un", - sockaddrlen, sizeof(addr)); + if (sockaddrlen < sizeof(addr)) { + Copy(sun_ad, &addr, sockaddrlen, char); + Zero(((char*)&addr) + sockaddrlen, sizeof(addr) - sockaddrlen, char); + } else { + Copy(sun_ad, &addr, sizeof(addr), char); } +# else + if (sockaddrlen != sizeof(addr)) + croak("Bad arg length for %s, length is %"UVuf", should be %"UVuf, + "Socket::unpack_sockaddr_un", (UV)sockaddrlen, (UV)sizeof(addr)); + Copy(sun_ad, &addr, sizeof(addr), char); # endif - Copy( sun_ad, &addr, sizeof addr, char ); - if ( addr.sun_family != AF_UNIX ) { croak("Bad address family for %s, got %d, should be %d", "Socket::unpack_sockaddr_un", |