|
Boost-Commit : |
From: chris_at_[hidden]
Date: 2008-03-12 09:26:41
Author: chris_kohlhoff
Date: 2008-03-12 09:26:41 EDT (Wed, 12 Mar 2008)
New Revision: 43570
URL: http://svn.boost.org/trac/boost/changeset/43570
Log:
Use unions to fix a sockaddr_storage aliasing problem that shows up with
g++ 4.3.0.
Text files modified:
trunk/boost/asio/detail/socket_ops.hpp | 60 ++++++++++----------
trunk/boost/asio/ip/basic_endpoint.hpp | 116 +++++++++++++++------------------------
2 files changed, 73 insertions(+), 103 deletions(-)
Modified: trunk/boost/asio/detail/socket_ops.hpp
==============================================================================
--- trunk/boost/asio/detail/socket_ops.hpp (original)
+++ trunk/boost/asio/detail/socket_ops.hpp 2008-03-12 09:26:41 EDT (Wed, 12 Mar 2008)
@@ -699,40 +699,40 @@
return 0;
}
- sockaddr_storage_type address;
+ union
+ {
+ socket_addr_type base;
+ sockaddr_storage_type storage;
+ sockaddr_in4_type v4;
+ sockaddr_in6_type v6;
+ } address;
DWORD address_length;
if (af == AF_INET)
{
address_length = sizeof(sockaddr_in4_type);
- sockaddr_in4_type* ipv4_address =
- reinterpret_cast<sockaddr_in4_type*>(&address);
- ipv4_address->sin_family = AF_INET;
- ipv4_address->sin_port = 0;
- memcpy(&ipv4_address->sin_addr, src, sizeof(in4_addr_type));
+ address.v4.sin_family = AF_INET;
+ address.v4.sin_port = 0;
+ memcpy(&address.v4.sin_addr, src, sizeof(in4_addr_type));
}
else // AF_INET6
{
address_length = sizeof(sockaddr_in6_type);
- sockaddr_in6_type* ipv6_address =
- reinterpret_cast<sockaddr_in6_type*>(&address);
- ipv6_address->sin6_family = AF_INET6;
- ipv6_address->sin6_port = 0;
- ipv6_address->sin6_flowinfo = 0;
- ipv6_address->sin6_scope_id = scope_id;
- memcpy(&ipv6_address->sin6_addr, src, sizeof(in6_addr_type));
+ address.v6.sin6_family = AF_INET6;
+ address.v6.sin6_port = 0;
+ address.v6.sin6_flowinfo = 0;
+ address.v6.sin6_scope_id = scope_id;
+ memcpy(&address.v6.sin6_addr, src, sizeof(in6_addr_type));
}
DWORD string_length = static_cast<DWORD>(length);
#if defined(BOOST_NO_ANSI_APIS)
LPWSTR string_buffer = (LPWSTR)_alloca(length * sizeof(WCHAR));
- int result = error_wrapper(::WSAAddressToStringW(
- reinterpret_cast<sockaddr*>(&address),
+ int result = error_wrapper(::WSAAddressToStringW(&address.base,
address_length, 0, string_buffer, &string_length), ec);
::WideCharToMultiByte(CP_ACP, 0, string_buffer, -1, dest, length, 0, 0);
#else
int result = error_wrapper(::WSAAddressToStringA(
- reinterpret_cast<sockaddr*>(&address),
- address_length, 0, dest, &string_length), ec);
+ &address.base, address_length, 0, dest, &string_length), ec);
#endif
// Windows may set error code on success.
@@ -775,30 +775,30 @@
return -1;
}
- sockaddr_storage_type address;
+ union
+ {
+ socket_addr_type base;
+ sockaddr_storage_type storage;
+ sockaddr_in4_type v4;
+ sockaddr_in6_type v6;
+ } address;
int address_length = sizeof(sockaddr_storage_type);
#if defined(BOOST_NO_ANSI_APIS)
int num_wide_chars = strlen(src) + 1;
LPWSTR wide_buffer = (LPWSTR)_alloca(num_wide_chars * sizeof(WCHAR));
::MultiByteToWideChar(CP_ACP, 0, src, -1, wide_buffer, num_wide_chars);
int result = error_wrapper(::WSAStringToAddressW(
- wide_buffer, af, 0,
- reinterpret_cast<sockaddr*>(&address),
- &address_length), ec);
+ wide_buffer, af, 0, &address.base, &address_length), ec);
#else
int result = error_wrapper(::WSAStringToAddressA(
- const_cast<char*>(src), af, 0,
- reinterpret_cast<sockaddr*>(&address),
- &address_length), ec);
+ const_cast<char*>(src), af, 0, &address.base, &address_length), ec);
#endif
if (af == AF_INET)
{
if (result != socket_error_retval)
{
- sockaddr_in4_type* ipv4_address =
- reinterpret_cast<sockaddr_in4_type*>(&address);
- memcpy(dest, &ipv4_address->sin_addr, sizeof(in4_addr_type));
+ memcpy(dest, &address.v4.sin_addr, sizeof(in4_addr_type));
clear_error(ec);
}
else if (strcmp(src, "255.255.255.255") == 0)
@@ -811,11 +811,9 @@
{
if (result != socket_error_retval)
{
- sockaddr_in6_type* ipv6_address =
- reinterpret_cast<sockaddr_in6_type*>(&address);
- memcpy(dest, &ipv6_address->sin6_addr, sizeof(in6_addr_type));
+ memcpy(dest, &address.v6.sin6_addr, sizeof(in6_addr_type));
if (scope_id)
- *scope_id = ipv6_address->sin6_scope_id;
+ *scope_id = address.v6.sin6_scope_id;
clear_error(ec);
}
}
Modified: trunk/boost/asio/ip/basic_endpoint.hpp
==============================================================================
--- trunk/boost/asio/ip/basic_endpoint.hpp (original)
+++ trunk/boost/asio/ip/basic_endpoint.hpp 2008-03-12 09:26:41 EDT (Wed, 12 Mar 2008)
@@ -66,11 +66,9 @@
basic_endpoint()
: data_()
{
- boost::asio::detail::sockaddr_in4_type& data
- = reinterpret_cast<boost::asio::detail::sockaddr_in4_type&>(data_);
- data.sin_family = AF_INET;
- data.sin_port = 0;
- data.sin_addr.s_addr = INADDR_ANY;
+ data_.v4.sin_family = AF_INET;
+ data_.v4.sin_port = 0;
+ data_.v4.sin_addr.s_addr = INADDR_ANY;
}
/// Construct an endpoint using a port number, specified in the host's byte
@@ -95,24 +93,20 @@
using namespace std; // For memcpy.
if (protocol.family() == PF_INET)
{
- boost::asio::detail::sockaddr_in4_type& data
- = reinterpret_cast<boost::asio::detail::sockaddr_in4_type&>(data_);
- data.sin_family = AF_INET;
- data.sin_port =
+ data_.v4.sin_family = AF_INET;
+ data_.v4.sin_port =
boost::asio::detail::socket_ops::host_to_network_short(port_num);
- data.sin_addr.s_addr = INADDR_ANY;
+ data_.v4.sin_addr.s_addr = INADDR_ANY;
}
else
{
- boost::asio::detail::sockaddr_in6_type& data
- = reinterpret_cast<boost::asio::detail::sockaddr_in6_type&>(data_);
- data.sin6_family = AF_INET6;
- data.sin6_port =
+ data_.v6.sin6_family = AF_INET6;
+ data_.v6.sin6_port =
boost::asio::detail::socket_ops::host_to_network_short(port_num);
- data.sin6_flowinfo = 0;
+ data_.v6.sin6_flowinfo = 0;
boost::asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT;
- data.sin6_addr = tmp_addr;
- data.sin6_scope_id = 0;
+ data_.v6.sin6_addr = tmp_addr;
+ data_.v6.sin6_scope_id = 0;
}
}
@@ -125,27 +119,23 @@
using namespace std; // For memcpy.
if (addr.is_v4())
{
- boost::asio::detail::sockaddr_in4_type& data
- = reinterpret_cast<boost::asio::detail::sockaddr_in4_type&>(data_);
- data.sin_family = AF_INET;
- data.sin_port =
+ data_.v4.sin_family = AF_INET;
+ data_.v4.sin_port =
boost::asio::detail::socket_ops::host_to_network_short(port_num);
- data.sin_addr.s_addr =
+ data_.v4.sin_addr.s_addr =
boost::asio::detail::socket_ops::host_to_network_long(
addr.to_v4().to_ulong());
}
else
{
- boost::asio::detail::sockaddr_in6_type& data
- = reinterpret_cast<boost::asio::detail::sockaddr_in6_type&>(data_);
- data.sin6_family = AF_INET6;
- data.sin6_port =
+ data_.v6.sin6_family = AF_INET6;
+ data_.v6.sin6_port =
boost::asio::detail::socket_ops::host_to_network_short(port_num);
- data.sin6_flowinfo = 0;
+ data_.v6.sin6_flowinfo = 0;
boost::asio::ip::address_v6 v6_addr = addr.to_v6();
boost::asio::ip::address_v6::bytes_type bytes = v6_addr.to_bytes();
- memcpy(data.sin6_addr.s6_addr, bytes.elems, 16);
- data.sin6_scope_id = v6_addr.scope_id();
+ memcpy(data_.v6.sin6_addr.s6_addr, bytes.elems, 16);
+ data_.v6.sin6_scope_id = v6_addr.scope_id();
}
}
@@ -165,7 +155,7 @@
/// The protocol associated with the endpoint.
protocol_type protocol() const
{
- if (is_v4(data_))
+ if (is_v4())
return InternetProtocol::v4();
return InternetProtocol::v6();
}
@@ -173,19 +163,19 @@
/// Get the underlying endpoint in the native type.
data_type* data()
{
- return reinterpret_cast<data_type*>(&data_);
+ return &data_.base;
}
/// Get the underlying endpoint in the native type.
const data_type* data() const
{
- return reinterpret_cast<const data_type*>(&data_);
+ return &data_.base;
}
/// Get the underlying size of the endpoint in the native type.
std::size_t size() const
{
- if (is_v4(data_))
+ if (is_v4())
return sizeof(boost::asio::detail::sockaddr_in4_type);
else
return sizeof(boost::asio::detail::sockaddr_in6_type);
@@ -194,7 +184,7 @@
/// Set the underlying size of the endpoint in the native type.
void resize(std::size_t size)
{
- if (size > sizeof(data_))
+ if (size > sizeof(boost::asio::detail::sockaddr_storage_type))
{
boost::system::system_error e(boost::asio::error::invalid_argument);
boost::throw_exception(e);
@@ -204,24 +194,22 @@
/// Get the capacity of the endpoint in the native type.
std::size_t capacity() const
{
- return sizeof(data_);
+ return sizeof(boost::asio::detail::sockaddr_storage_type);
}
/// Get the port associated with the endpoint. The port number is always in
/// the host's byte order.
unsigned short port() const
{
- if (is_v4(data_))
+ if (is_v4())
{
return boost::asio::detail::socket_ops::network_to_host_short(
- reinterpret_cast<const boost::asio::detail::sockaddr_in4_type&>(
- data_).sin_port);
+ data_.v4.sin_port);
}
else
{
return boost::asio::detail::socket_ops::network_to_host_short(
- reinterpret_cast<const boost::asio::detail::sockaddr_in6_type&>(
- data_).sin6_port);
+ data_.v6.sin6_port);
}
}
@@ -229,14 +217,14 @@
/// the host's byte order.
void port(unsigned short port_num)
{
- if (is_v4(data_))
+ if (is_v4())
{
- reinterpret_cast<boost::asio::detail::sockaddr_in4_type&>(data_).sin_port
+ data_.v4.sin_port
= boost::asio::detail::socket_ops::host_to_network_short(port_num);
}
else
{
- reinterpret_cast<boost::asio::detail::sockaddr_in6_type&>(data_).sin6_port
+ data_.v6.sin_port
= boost::asio::detail::socket_ops::host_to_network_short(port_num);
}
}
@@ -245,23 +233,17 @@
boost::asio::ip::address address() const
{
using namespace std; // For memcpy.
- if (is_v4(data_))
+ if (is_v4())
{
- const boost::asio::detail::sockaddr_in4_type& data
- = reinterpret_cast<const boost::asio::detail::sockaddr_in4_type&>(
- data_);
return boost::asio::ip::address_v4(
boost::asio::detail::socket_ops::network_to_host_long(
- data.sin_addr.s_addr));
+ data_.v4.sin_addr.s_addr));
}
else
{
- const boost::asio::detail::sockaddr_in6_type& data
- = reinterpret_cast<const boost::asio::detail::sockaddr_in6_type&>(
- data_);
boost::asio::ip::address_v6::bytes_type bytes;
- memcpy(bytes.elems, data.sin6_addr.s6_addr, 16);
- return boost::asio::ip::address_v6(bytes, data.sin6_scope_id);
+ memcpy(bytes.elems, data_.v6.sin6_addr.s6_addr, 16);
+ return boost::asio::ip::address_v6(bytes, data_.v6.sin6_scope_id);
}
}
@@ -299,29 +281,19 @@
private:
// Helper function to determine whether the endpoint is IPv4.
-#if defined(_AIX)
- template <typename T, unsigned char (T::*)> struct is_v4_helper {};
-
- template <typename T>
- static bool is_v4(const T& ss, is_v4_helper<T, &T::ss_family>* = 0)
+ bool is_v4() const
{
- return ss.ss_family == AF_INET;
+ return data_.base.sa_family == AF_INET;
}
- template <typename T>
- static bool is_v4(const T& ss, is_v4_helper<T, &T::__ss_family>* = 0)
- {
- return ss.__ss_family == AF_INET;
- }
-#else
- static bool is_v4(const boost::asio::detail::sockaddr_storage_type& ss)
- {
- return ss.ss_family == AF_INET;
- }
-#endif
-
// The underlying IP socket address.
- boost::asio::detail::sockaddr_storage_type data_;
+ union data_union
+ {
+ boost::asio::detail::socket_addr_type base;
+ boost::asio::detail::sockaddr_storage_type storage;
+ boost::asio::detail::sockaddr_in4_type v4;
+ boost::asio::detail::sockaddr_in6_type v6;
+ } data_;
};
/// Output an endpoint as a string.
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk