diff --git a/doc/zmq_msg_close.txt b/doc/zmq_msg_close.txt index 1da353b6..e530e33c 100644 --- a/doc/zmq_msg_close.txt +++ b/doc/zmq_msg_close.txt @@ -35,7 +35,8 @@ it shall return `-1` and set 'errno' to one of the values defined below. ERRORS ------ -No errors are defined. +*EFAULT*:: +Invalid message. SEE ALSO diff --git a/doc/zmq_msg_copy.txt b/doc/zmq_msg_copy.txt index f41a42e2..e393f03a 100644 --- a/doc/zmq_msg_copy.txt +++ b/doc/zmq_msg_copy.txt @@ -37,7 +37,8 @@ shall return `-1` and set 'errno' to one of the values defined below. ERRORS ------ -No errors are defined. +*EFAULT*:: +Invalid message. SEE ALSO diff --git a/doc/zmq_msg_move.txt b/doc/zmq_msg_move.txt index 75c8e74c..f14a28f1 100644 --- a/doc/zmq_msg_move.txt +++ b/doc/zmq_msg_move.txt @@ -32,7 +32,8 @@ shall return `-1` and set 'errno' to one of the values defined below. ERRORS ------ -No errors are defined. +*EFAULT*:: +Invalid message. SEE ALSO diff --git a/doc/zmq_recv.txt b/doc/zmq_recv.txt index fe601ba3..0b6e0e4c 100644 --- a/doc/zmq_recv.txt +++ b/doc/zmq_recv.txt @@ -68,6 +68,8 @@ The provided 'socket' was invalid. *EINTR*:: The operation was interrupted by delivery of a signal before a message was available. +*EFAULT*:: +The message passed to the function was invalid. EXAMPLE diff --git a/doc/zmq_send.txt b/doc/zmq_send.txt index 2a63cc6f..85ac3b7b 100644 --- a/doc/zmq_send.txt +++ b/doc/zmq_send.txt @@ -78,6 +78,8 @@ The provided 'socket' was invalid. *EINTR*:: The operation was interrupted by delivery of a signal before the message was sent. +*EFAULT*:: +Invalid message. EXAMPLE diff --git a/include/zmq.h b/include/zmq.h index e6fb60d3..70197c93 100644 --- a/include/zmq.h +++ b/include/zmq.h @@ -137,6 +137,7 @@ ZMQ_EXPORT const char *zmq_strerror (int errnum); /* allows us to pack the stucture tigher and thus improve performance. */ #define ZMQ_MSG_MORE 1 #define ZMQ_MSG_SHARED 128 +#define ZMQ_MSG_MASK 129 /* Merges all the flags */ /* A message. Note that 'content' is not a pointer to the raw data. */ /* Rather it is pointer to zmq::msg_content_t structure */ diff --git a/src/msg.cpp b/src/msg.cpp index e9d1da7c..e800bd6e 100644 --- a/src/msg.cpp +++ b/src/msg.cpp @@ -26,12 +26,13 @@ #include #include "stdint.hpp" +#include "likely.hpp" #include "err.hpp" int zmq_msg_init (zmq_msg_t *msg_) { msg_->content = (zmq::msg_content_t*) ZMQ_VSM; - msg_->flags = 0; + msg_->flags = (unsigned char) ~ZMQ_MSG_MASK; msg_->vsm_size = 0; return 0; } @@ -40,7 +41,7 @@ int zmq_msg_init_size (zmq_msg_t *msg_, size_t size_) { if (size_ <= ZMQ_MAX_VSM_SIZE) { msg_->content = (zmq::msg_content_t*) ZMQ_VSM; - msg_->flags = 0; + msg_->flags = (unsigned char) ~ZMQ_MSG_MASK; msg_->vsm_size = (uint8_t) size_; } else { @@ -50,7 +51,7 @@ int zmq_msg_init_size (zmq_msg_t *msg_, size_t size_) errno = ENOMEM; return -1; } - msg_->flags = 0; + msg_->flags = (unsigned char) ~ZMQ_MSG_MASK; zmq::msg_content_t *content = (zmq::msg_content_t*) msg_->content; content->data = (void*) (content + 1); @@ -67,7 +68,7 @@ int zmq_msg_init_data (zmq_msg_t *msg_, void *data_, size_t size_, { msg_->content = (zmq::msg_content_t*) malloc (sizeof (zmq::msg_content_t)); alloc_assert (msg_->content); - msg_->flags = 0; + msg_->flags = (unsigned char) ~ZMQ_MSG_MASK; zmq::msg_content_t *content = (zmq::msg_content_t*) msg_->content; content->data = data_; content->size = size_; @@ -79,6 +80,12 @@ int zmq_msg_init_data (zmq_msg_t *msg_, void *data_, size_t size_, int zmq_msg_close (zmq_msg_t *msg_) { + // Check the validity tag. + if (unlikely (msg_->flags | ZMQ_MSG_MASK) != 0xff) { + errno = EFAULT; + return -1; + } + // For VSMs and delimiters there are no resources to free. if (msg_->content != (zmq::msg_content_t*) ZMQ_DELIMITER && msg_->content != (zmq::msg_content_t*) ZMQ_VSM) { @@ -98,17 +105,21 @@ int zmq_msg_close (zmq_msg_t *msg_) } } - // As a safety measure, let's make the deallocated message look like - // an empty message. - msg_->content = (zmq::msg_content_t*) ZMQ_VSM; + // Remove the validity tag from the message. msg_->flags = 0; - msg_->vsm_size = 0; return 0; } int zmq_msg_move (zmq_msg_t *dest_, zmq_msg_t *src_) { + // Check the validity tags. + if (unlikely ((dest_->flags | ZMQ_MSG_MASK) != 0xff || + (src_->flags | ZMQ_MSG_MASK) != 0xff)) { + errno = EFAULT; + return -1; + } + zmq_msg_close (dest_); *dest_ = *src_; zmq_msg_init (src_); @@ -117,6 +128,13 @@ int zmq_msg_move (zmq_msg_t *dest_, zmq_msg_t *src_) int zmq_msg_copy (zmq_msg_t *dest_, zmq_msg_t *src_) { + // Check the validity tags. + if (unlikely ((dest_->flags | ZMQ_MSG_MASK) != 0xff || + (src_->flags | ZMQ_MSG_MASK) != 0xff)) { + errno = EFAULT; + return -1; + } + zmq_msg_close (dest_); // VSMs and delimiters require no special handling. @@ -140,6 +158,9 @@ int zmq_msg_copy (zmq_msg_t *dest_, zmq_msg_t *src_) void *zmq_msg_data (zmq_msg_t *msg_) { + // Check the validity tag. + zmq_assert ((msg_->flags | ZMQ_MSG_MASK) == 0xff); + if (msg_->content == (zmq::msg_content_t*) ZMQ_VSM) return msg_->vsm_data; if (msg_->content == (zmq::msg_content_t*) ZMQ_DELIMITER) @@ -150,6 +171,9 @@ void *zmq_msg_data (zmq_msg_t *msg_) size_t zmq_msg_size (zmq_msg_t *msg_) { + // Check the validity tag. + zmq_assert ((msg_->flags | ZMQ_MSG_MASK) == 0xff); + if (msg_->content == (zmq::msg_content_t*) ZMQ_VSM) return msg_->vsm_size; if (msg_->content == (zmq::msg_content_t*) ZMQ_DELIMITER) diff --git a/src/req.cpp b/src/req.cpp index f4954925..503f2217 100644 --- a/src/req.cpp +++ b/src/req.cpp @@ -49,7 +49,7 @@ int zmq::req_t::xsend (zmq_msg_t *msg_, int flags_) zmq_msg_t prefix; int rc = zmq_msg_init (&prefix); zmq_assert (rc == 0); - prefix.flags = ZMQ_MSG_MORE; + prefix.flags |= ZMQ_MSG_MORE; rc = xreq_t::xsend (&prefix, flags_); if (rc != 0) return rc; diff --git a/src/socket_base.cpp b/src/socket_base.cpp index c9b5c31e..9f3b1f67 100644 --- a/src/socket_base.cpp +++ b/src/socket_base.cpp @@ -466,11 +466,18 @@ int zmq::socket_base_t::connect (const char *addr_) int zmq::socket_base_t::send (::zmq_msg_t *msg_, int flags_) { + // Check whether the library haven't been shut down yet. if (unlikely (ctx_terminated)) { errno = ETERM; return -1; } + // Check whether message passed to the function is valid. + if (unlikely ((msg_->flags | ZMQ_MSG_MASK) != 0xff)) { + errno = EFAULT; + return -1; + } + // Process pending commands, if any. int rc = process_commands (false, true); if (unlikely (rc != 0)) @@ -504,11 +511,18 @@ int zmq::socket_base_t::send (::zmq_msg_t *msg_, int flags_) int zmq::socket_base_t::recv (::zmq_msg_t *msg_, int flags_) { + // Check whether the library haven't been shut down yet. if (unlikely (ctx_terminated)) { errno = ETERM; return -1; } + // Check whether message passed to the function is valid. + if (unlikely ((msg_->flags | ZMQ_MSG_MASK) != 0xff)) { + errno = EFAULT; + return -1; + } + // Get the message. int rc = xrecv (msg_, flags_); int err = errno; diff --git a/src/xrep.cpp b/src/xrep.cpp index 7f0da4de..75dc30e6 100644 --- a/src/xrep.cpp +++ b/src/xrep.cpp @@ -269,7 +269,7 @@ int zmq::xrep_t::xrecv (zmq_msg_t *msg_, int flags_) zmq_assert (rc == 0); memcpy (zmq_msg_data (msg_), inpipes [current_in].identity.data (), zmq_msg_size (msg_)); - msg_->flags = ZMQ_MSG_MORE; + msg_->flags |= ZMQ_MSG_MORE; return 0; }