Skip to content

Commit

Permalink
Problem: tcp address strings are dependent on locale
Browse files Browse the repository at this point in the history
Solution: use sprintf instead of std::stringstream
Fixes zeromq#3385
  • Loading branch information
sigiesec committed Feb 5, 2019
1 parent 14da2ab commit bcaad01
Showing 1 changed file with 49 additions and 13 deletions.
62 changes: 49 additions & 13 deletions src/tcp_address.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@

#include "precompiled.hpp"
#include <string>
#include <sstream>

#include "macros.hpp"
#include "tcp_address.hpp"
Expand Down Expand Up @@ -113,6 +112,27 @@ int zmq::tcp_address_t::resolve (const char *name_, bool local_, bool ipv6_)
return resolver.resolve (&_address, name_);
}

template <size_t N1, size_t N2>
static std::string make_address_string (const char *hbuf,
in_port_t port,
const char (&ipv6_prefix)[N1],
const char (&ipv6_suffix)[N2])
{
const size_t max_port_str_length = 5;
char buf[NI_MAXHOST + sizeof ipv6_prefix + sizeof ipv6_suffix
+ max_port_str_length];
char *pos = buf;
memcpy (pos, ipv6_prefix, sizeof ipv6_prefix - 1);
pos += sizeof ipv6_prefix - 1;
const int hbuf_len = strlen (hbuf);
memcpy (pos, hbuf, hbuf_len);
pos += hbuf_len;
memcpy (pos, ipv6_suffix, sizeof ipv6_suffix - 1);
pos += sizeof ipv6_suffix - 1;
pos += sprintf (pos, "%d", ntohs (port));
return std::string (buf, pos - buf);
}

int zmq::tcp_address_t::to_string (std::string &addr_) const
{
if (_address.family () != AF_INET && _address.family () != AF_INET6) {
Expand All @@ -130,14 +150,16 @@ int zmq::tcp_address_t::to_string (std::string &addr_) const
return rc;
}

const char ipv4_prefix[] = "tcp://";
const char ipv4_suffix[] = ":";
const char ipv6_prefix[] = "tcp://[";
const char ipv6_suffix[] = "]:";
if (_address.family () == AF_INET6) {
std::stringstream s;
s << "tcp://[" << hbuf << "]:" << ntohs (_address.ipv6.sin6_port);
addr_ = s.str ();
addr_ = make_address_string (hbuf, _address.ipv6.sin6_port, ipv6_prefix,
ipv6_suffix);
} else {
std::stringstream s;
s << "tcp://" << hbuf << ":" << ntohs (_address.ipv4.sin_port);
addr_ = s.str ();
addr_ = make_address_string (hbuf, _address.ipv4.sin_port, ipv4_prefix,
ipv4_suffix);
}
return 0;
}
Expand Down Expand Up @@ -263,15 +285,29 @@ int zmq::tcp_address_mask_t::to_string (std::string &addr_) const
return rc;
}

const size_t max_mask_len = 4;
const char ipv6_prefix[] = "[";
const char ipv6_suffix[] = "]/";
const char ipv4_suffix[] = "/";
char
buf[NI_MAXHOST + sizeof ipv6_prefix + sizeof ipv6_suffix + max_mask_len];
char *pos = buf;
if (_network_address.family () == AF_INET6) {
memcpy (pos, ipv6_prefix, sizeof ipv6_prefix - 1);
pos += sizeof ipv6_prefix - 1;
}
const int hbuf_len = strlen (hbuf);
memcpy (pos, hbuf, hbuf_len);
pos += hbuf_len;
if (_network_address.family () == AF_INET6) {
std::stringstream s;
s << "[" << hbuf << "]/" << _address_mask;
addr_ = s.str ();
memcpy (pos, ipv6_suffix, sizeof ipv6_suffix - 1);
pos += sizeof ipv6_suffix - 1;
} else {
std::stringstream s;
s << hbuf << "/" << _address_mask;
addr_ = s.str ();
memcpy (pos, ipv4_suffix, sizeof ipv4_suffix - 1);
pos += sizeof ipv4_suffix - 1;
}
pos += sprintf (pos, "%d", _address_mask);
addr_.assign (buf, pos - buf);
return 0;
}

Expand Down

0 comments on commit bcaad01

Please sign in to comment.