Problem: Possible buffer overruns related to metadata in various mechanisms (#2683)

* Problem: no test case with CURVE encryption and large identity

Solution: added test case (currently crashing)

* Problem: possible buffer overflow in mechanism_t::add_property

Solution: add target buffer length parameter and check the buffer is sufficiently large

* Problem: test cases accidentally excluded from build

Solution: remove #if/#endif

* Problem: possible buffer overruns related to metadata at various locations

Solution: allocate buffer large enough for actual metadata, reduce code duplication

* Problem: syntax error related to pointer type conversion

Solution: change argument type of make_command_with_basic_properties to const char *

* Problem: large metadata may cause an assertion in produce_initiate

Solution: Allow metadata of arbitrary size in produce_initiate
This commit is contained in:
Simon Giesecke
2017-08-15 19:42:31 +02:00
committed by Luca Boccassi
parent d5e4319edc
commit 4a18f6204c
9 changed files with 162 additions and 132 deletions

View File

@@ -82,11 +82,28 @@ const char *zmq::mechanism_t::socket_type_string (int socket_type) const
return names [socket_type];
}
size_t zmq::mechanism_t::add_property (unsigned char *ptr, const char *name,
const void *value, size_t value_len)
static size_t property_len (size_t name_len, size_t value_len)
{
return 1 + name_len + 4 + value_len;
}
static size_t name_len (const char *name)
{
const size_t name_len = strlen (name);
zmq_assert (name_len <= 255);
return name_len;
}
size_t zmq::mechanism_t::add_property (unsigned char *ptr,
size_t ptr_capacity,
const char *name,
const void *value,
size_t value_len)
{
const size_t name_len = ::name_len (name);
const size_t total_len = ::property_len (name_len, value_len);
zmq_assert (total_len <= ptr_capacity);
*ptr++ = static_cast <unsigned char> (name_len);
memcpy (ptr, name, name_len);
ptr += name_len;
@@ -95,11 +112,66 @@ size_t zmq::mechanism_t::add_property (unsigned char *ptr, const char *name,
ptr += 4;
memcpy (ptr, value, value_len);
return 1 + name_len + 4 + value_len;
return total_len;
}
size_t zmq::mechanism_t::property_len (const char *name, size_t value_len)
{
return ::property_len (name_len (name), value_len);
}
size_t zmq::mechanism_t::add_basic_properties (unsigned char *buf,
size_t buf_capacity) const
{
unsigned char *ptr = buf;
// Add socket type property
const char *socket_type = socket_type_string (options.type);
ptr += add_property (ptr, buf_capacity,
ZMQ_MSG_PROPERTY_SOCKET_TYPE, socket_type,
strlen (socket_type));
// Add identity property
if (options.type == ZMQ_REQ || options.type == ZMQ_DEALER
|| options.type == ZMQ_ROUTER)
ptr += add_property (ptr, buf_capacity - (ptr - buf),
ZMQ_MSG_PROPERTY_IDENTITY, options.identity,
options.identity_size);
return ptr - buf;
}
size_t zmq::mechanism_t::basic_properties_len() const
{
const char *socket_type = socket_type_string (options.type);
return property_len (ZMQ_MSG_PROPERTY_SOCKET_TYPE, strlen (socket_type))
+ ((options.type == ZMQ_REQ || options.type == ZMQ_DEALER
|| options.type == ZMQ_ROUTER)
? property_len (ZMQ_MSG_PROPERTY_IDENTITY,
options.identity_size)
: 0);
}
void zmq::mechanism_t::make_command_with_basic_properties (
msg_t *msg_, const char *prefix, size_t prefix_len) const
{
const size_t command_size = prefix_len + basic_properties_len ();
const int rc = msg_->init_size (command_size);
errno_assert (rc == 0);
unsigned char *ptr = (unsigned char *) msg_->data ();
// Add prefix
memcpy (ptr, prefix, prefix_len);
ptr += prefix_len;
ptr += add_basic_properties (
ptr, command_size - (ptr - (unsigned char *) msg_->data ()));
}
int zmq::mechanism_t::parse_metadata (const unsigned char *ptr_,
size_t length_, bool zap_flag)
size_t length_,
bool zap_flag)
{
size_t bytes_left = length_;