diff options
| author | Dhammika Pathirana <dhammika@gmail.com> | 2010-10-23 20:59:54 +0200 | 
|---|---|---|
| committer | Martin Sustrik <sustrik@250bpm.com> | 2010-10-23 20:59:54 +0200 | 
| commit | 71bef330fc9f09ee070c90d174fc0bcb7783b38d (patch) | |
| tree | 831702e8b6a3f8ee18f0a738747fe88b4d44bb96 | |
| parent | 8d6979922efff7183ce03b49715472e5b2a6a1df (diff) | |
handle decoding malformed messages
Signed-off-by: Dhammika Pathirana <dhammika@gmail.com>
| -rw-r--r-- | src/decoder.cpp | 26 | ||||
| -rw-r--r-- | src/decoder.hpp | 23 | ||||
| -rw-r--r-- | src/zmq_engine.cpp | 26 | 
3 files changed, 53 insertions, 22 deletions
| diff --git a/src/decoder.cpp b/src/decoder.cpp index 131ee24..1217193 100644 --- a/src/decoder.cpp +++ b/src/decoder.cpp @@ -54,16 +54,22 @@ bool zmq::decoder_t::one_byte_size_ready ()          next_step (tmpbuf, 8, &decoder_t::eight_byte_size_ready);      else { -        //  TODO:  Handle over-sized message decently. -          //  There has to be at least one byte (the flags) in the message). -        zmq_assert (*tmpbuf > 0); +        if (!*tmpbuf) { +            decoding_error (); +            return false; +        }          //  in_progress is initialised at this point so in theory we should          //  close it before calling zmq_msg_init_size, however, it's a 0-byte          //  message and thus we can treat it as uninitialised...          int rc = zmq_msg_init_size (&in_progress, *tmpbuf - 1); +        if (rc != 0 && errno == ENOMEM) { +            decoding_error (); +            return false; +        }          errno_assert (rc == 0); +          next_step (tmpbuf, 1, &decoder_t::flags_ready);      }      return true; @@ -75,19 +81,23 @@ bool zmq::decoder_t::eight_byte_size_ready ()      //  read the message data into it.      size_t size = (size_t) get_uint64 (tmpbuf); -    //  TODO:  Handle over-sized message decently. -      //  There has to be at least one byte (the flags) in the message). -    zmq_assert (size > 0); - +    if (!size) { +        decoding_error (); +        return false; +    }      //  in_progress is initialised at this point so in theory we should      //  close it before calling zmq_msg_init_size, however, it's a 0-byte      //  message and thus we can treat it as uninitialised...      int rc = zmq_msg_init_size (&in_progress, size - 1); +    if (rc != 0 && errno == ENOMEM) { +        decoding_error (); +        return false; +    }      errno_assert (rc == 0); -    next_step (tmpbuf, 1, &decoder_t::flags_ready); +    next_step (tmpbuf, 1, &decoder_t::flags_ready);      return true;  } diff --git a/src/decoder.hpp b/src/decoder.hpp index 87982a0..ab7d454 100644 --- a/src/decoder.hpp +++ b/src/decoder.hpp @@ -98,9 +98,13 @@ namespace zmq                  read_pos += size_;                  to_read -= size_; -                while (!to_read) -                    if (!(static_cast <T*> (this)->*next) ()) +                while (!to_read) { +                    if (!(static_cast <T*> (this)->*next) ()) { +                        if (unlikely (!(static_cast <T*> (this)->next))) +                            return (size_t) -1;                          return size_; +                    } +                }                  return size_;              } @@ -109,9 +113,13 @@ namespace zmq                  //  Try to get more space in the message to fill in.                  //  If none is available, return. -                while (!to_read) -                    if (!(static_cast <T*> (this)->*next) ()) +                while (!to_read) { +                    if (!(static_cast <T*> (this)->*next) ()) { +                        if (unlikely (!(static_cast <T*> (this)->next))) +                            return (size_t) -1;                          return pos; +                    } +                }                  //  If there are no more data in the buffer, return.                  if (pos == size_) @@ -142,6 +150,13 @@ namespace zmq              next = next_;          } +        //  This function should be called from the derived class to +        //  abort decoder state machine. +        inline void decoding_error () +        { +            next = NULL; +        } +      private:          unsigned char *read_pos; diff --git a/src/zmq_engine.cpp b/src/zmq_engine.cpp index 815697c..761f6fe 100644 --- a/src/zmq_engine.cpp +++ b/src/zmq_engine.cpp @@ -119,18 +119,24 @@ void zmq::zmq_engine_t::in_event ()      //  Push the data to the decoder.      size_t processed = decoder.process_buffer (inpos, insize); -    //  Stop polling for input if we got stuck. -    if (processed < insize) { - -        //  This may happen if queue limits are in effect or when -        //  init object reads all required information from the socket -        //  and rejects to read more data. -        reset_pollin (handle); +    if (unlikely (processed == (size_t) -1)) { +        disconnection = true;      } +    else { + +        //  Stop polling for input if we got stuck. +        if (processed < insize) { -    //  Adjust the buffer. -    inpos += processed; -    insize -= processed; +            //  This may happen if queue limits are in effect or when +            //  init object reads all required information from the socket +            //  and rejects to read more data. +            reset_pollin (handle); +        } + +        //  Adjust the buffer. +        inpos += processed; +        insize -= processed; +    }      //  Flush all messages the decoder may have produced.      inout->flush (); | 
