diff options
author | Martin Hurton <hurtonm@gmail.com> | 2012-05-12 11:28:15 +0200 |
---|---|---|
committer | Martin Sustrik <sustrik@250bpm.com> | 2012-05-12 11:28:15 +0200 |
commit | 17e89e90ce48989cd9454a8a3dcf04532fc50237 (patch) | |
tree | 4291d0be01b6ee39c0f7624db41cd0609ea3aae0 | |
parent | e924381bae58ca828c9691b9d4d772a20a91c717 (diff) |
Fix decoder to properly handle large messages
The decoder did not properly decode large messages
on systems where sizeof (size_t) < sizeof (uint64_t).
-rw-r--r-- | src/decoder.cpp | 38 |
1 files changed, 24 insertions, 14 deletions
diff --git a/src/decoder.cpp b/src/decoder.cpp index dc8e54e..f46cdd2 100644 --- a/src/decoder.cpp +++ b/src/decoder.cpp @@ -21,6 +21,7 @@ #include <stdlib.h> #include <string.h> +#include <limits> #include "decoder.hpp" #include "session_base.hpp" @@ -91,27 +92,36 @@ bool xs::decoder_t::one_byte_size_ready () bool xs::decoder_t::eight_byte_size_ready () { - // 8-byte size is read. Allocate the buffer for message body and - // read the message data into it. - size_t size = (size_t) get_uint64 (tmpbuf); + // 8-byte payload length is read. Allocate the buffer + // for message body and read the message data into it. + const uint64_t payload_length = get_uint64 (tmpbuf); // There has to be at least one byte (the flags) in the message). - if (!size) { + if (unlikely (payload_length == 0)) { decoding_error (); return false; } + // Message size must not exceed the maximum allowed size. + if (unlikely (maxmsgsize >= 0 && payload_length - 1 > maxmsgsize)) { + decoding_error (); + return false; + } + + // Message size must fit within range of size_t data type. + if (unlikely (payload_length - 1 > std::numeric_limits <size_t>::max ())) { + decoding_error (); + return false; + } + + const size_t msg_size = static_cast <size_t> (payload_length - 1); + // in_progress is initialised at this point so in theory we should - // close it before calling xs_msg_init_size, however, it's a 0-byte + // close it before calling init_size, however, it's a 0-byte // message and thus we can treat it as uninitialised... - int rc; - if (maxmsgsize >= 0 && (uint64_t) (size - 1) > maxmsgsize) { - rc = -1; - errno = ENOMEM; - } - else - rc = in_progress.init_size (size - 1); - if (rc != 0 && errno == ENOMEM) { + int rc = in_progress.init_size (msg_size); + if (rc != 0) { + errno_assert (errno == ENOMEM); rc = in_progress.init (); errno_assert (rc == 0); decoding_error (); @@ -130,7 +140,7 @@ bool xs::decoder_t::flags_ready () next_step (in_progress.data (), in_progress.size (), &decoder_t::message_ready); - + return true; } |