LCOV - code coverage report
Current view: top level - ipc/chromium/src/third_party/libevent - event_tagging.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 205 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 29 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2003-2009 Niels Provos <provos@citi.umich.edu>
       3             :  * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson
       4             :  *
       5             :  * Redistribution and use in source and binary forms, with or without
       6             :  * modification, are permitted provided that the following conditions
       7             :  * are met:
       8             :  * 1. Redistributions of source code must retain the above copyright
       9             :  *    notice, this list of conditions and the following disclaimer.
      10             :  * 2. Redistributions in binary form must reproduce the above copyright
      11             :  *    notice, this list of conditions and the following disclaimer in the
      12             :  *    documentation and/or other materials provided with the distribution.
      13             :  * 3. The name of the author may not be used to endorse or promote products
      14             :  *    derived from this software without specific prior written permission.
      15             :  *
      16             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
      17             :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      18             :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      19             :  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
      20             :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      21             :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      22             :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      23             :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      24             :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      25             :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      26             :  */
      27             : 
      28             : #include "event2/event-config.h"
      29             : #include "evconfig-private.h"
      30             : 
      31             : #ifdef EVENT__HAVE_SYS_TYPES_H
      32             : #include <sys/types.h>
      33             : #endif
      34             : #ifdef EVENT__HAVE_SYS_PARAM_H
      35             : #include <sys/param.h>
      36             : #endif
      37             : 
      38             : #ifdef _WIN32
      39             : #define WIN32_LEAN_AND_MEAN
      40             : #include <winsock2.h>
      41             : #include <windows.h>
      42             : #undef WIN32_LEAN_AND_MEAN
      43             : #endif
      44             : 
      45             : #ifdef EVENT__HAVE_SYS_IOCTL_H
      46             : #include <sys/ioctl.h>
      47             : #endif
      48             : #include <sys/queue.h>
      49             : #ifdef EVENT__HAVE_SYS_TIME_H
      50             : #include <sys/time.h>
      51             : #endif
      52             : 
      53             : #include <errno.h>
      54             : #include <stdio.h>
      55             : #include <stdlib.h>
      56             : #include <string.h>
      57             : #ifndef _WIN32
      58             : #include <syslog.h>
      59             : #endif
      60             : #ifdef EVENT__HAVE_UNISTD_H
      61             : #include <unistd.h>
      62             : #endif
      63             : #include <limits.h>
      64             : 
      65             : #include "event2/event.h"
      66             : #include "event2/tag.h"
      67             : #include "event2/buffer.h"
      68             : #include "log-internal.h"
      69             : #include "mm-internal.h"
      70             : #include "util-internal.h"
      71             : 
      72             : /*
      73             :   Here's our wire format:
      74             : 
      75             :   Stream = TaggedData*
      76             : 
      77             :   TaggedData = Tag Length Data
      78             :        where the integer value of 'Length' is the length of 'data'.
      79             : 
      80             :   Tag = HByte* LByte
      81             :        where HByte is a byte with the high bit set, and LByte is a byte
      82             :        with the high bit clear. The integer value of the tag is taken
      83             :        by concatenating the lower 7 bits from all the tags.  So for example,
      84             :        the tag 0x66 is encoded as [66], whereas the tag 0x166 is encoded as
      85             :        [82 66]
      86             : 
      87             :   Length = Integer
      88             : 
      89             :   Integer = NNibbles Nibble* Padding?
      90             :        where NNibbles is a 4-bit value encoding the number of nibbles-1,
      91             :        and each Nibble is 4 bits worth of encoded integer, in big-endian
      92             :        order.  If the total encoded integer size is an odd number of nibbles,
      93             :        a final padding nibble with value 0 is appended.
      94             : */
      95             : 
      96             : int evtag_decode_int(ev_uint32_t *pnumber, struct evbuffer *evbuf);
      97             : int evtag_decode_int64(ev_uint64_t *pnumber, struct evbuffer *evbuf);
      98             : int evtag_encode_tag(struct evbuffer *evbuf, ev_uint32_t tag);
      99             : int evtag_decode_tag(ev_uint32_t *ptag, struct evbuffer *evbuf);
     100             : 
     101             : void
     102           0 : evtag_init(void)
     103             : {
     104           0 : }
     105             : 
     106             : /*
     107             :  * We encode integers by nibbles; the first nibble contains the number
     108             :  * of significant nibbles - 1;  this allows us to encode up to 64-bit
     109             :  * integers.  This function is byte-order independent.
     110             :  *
     111             :  * @param number a 32-bit unsigned integer to encode
     112             :  * @param data a pointer to where the data should be written.  Must
     113             :  *    have at least 5 bytes free.
     114             :  * @return the number of bytes written into data.
     115             :  */
     116             : 
     117             : #define ENCODE_INT_INTERNAL(data, number) do {                          \
     118             :         int off = 1, nibbles = 0;                                       \
     119             :                                                                         \
     120             :         memset(data, 0, sizeof(number)+1);                              \
     121             :         while (number) {                                                \
     122             :                 if (off & 0x1)                                              \
     123             :                         data[off/2] = (data[off/2] & 0xf0) | (number & 0x0f); \
     124             :                 else                                                    \
     125             :                         data[off/2] = (data[off/2] & 0x0f) |                \
     126             :                             ((number & 0x0f) << 4);                   \
     127             :                 number >>= 4;                                             \
     128             :                 off++;                                                  \
     129             :         }                                                               \
     130             :                                                                         \
     131             :         if (off > 2)                                                 \
     132             :                 nibbles = off - 2;                                      \
     133             :                                                                         \
     134             :         /* Off - 1 is the number of encoded nibbles */                  \
     135             :         data[0] = (data[0] & 0x0f) | ((nibbles & 0x0f) << 4);             \
     136             :                                                                         \
     137             :         return ((off + 1) / 2);                                         \
     138             : } while (0)
     139             : 
     140             : static inline int
     141           0 : encode_int_internal(ev_uint8_t *data, ev_uint32_t number)
     142             : {
     143           0 :         ENCODE_INT_INTERNAL(data, number);
     144             : }
     145             : 
     146             : static inline int
     147           0 : encode_int64_internal(ev_uint8_t *data, ev_uint64_t number)
     148             : {
     149           0 :         ENCODE_INT_INTERNAL(data, number);
     150             : }
     151             : 
     152             : void
     153           0 : evtag_encode_int(struct evbuffer *evbuf, ev_uint32_t number)
     154             : {
     155             :         ev_uint8_t data[5];
     156           0 :         int len = encode_int_internal(data, number);
     157           0 :         evbuffer_add(evbuf, data, len);
     158           0 : }
     159             : 
     160             : void
     161           0 : evtag_encode_int64(struct evbuffer *evbuf, ev_uint64_t number)
     162             : {
     163             :         ev_uint8_t data[9];
     164           0 :         int len = encode_int64_internal(data, number);
     165           0 :         evbuffer_add(evbuf, data, len);
     166           0 : }
     167             : 
     168             : /*
     169             :  * Support variable length encoding of tags; we use the high bit in each
     170             :  * octet as a continuation signal.
     171             :  */
     172             : 
     173             : int
     174           0 : evtag_encode_tag(struct evbuffer *evbuf, ev_uint32_t tag)
     175             : {
     176           0 :         int bytes = 0;
     177             :         ev_uint8_t data[5];
     178             : 
     179           0 :         memset(data, 0, sizeof(data));
     180             :         do {
     181           0 :                 ev_uint8_t lower = tag & 0x7f;
     182           0 :                 tag >>= 7;
     183             : 
     184           0 :                 if (tag)
     185           0 :                         lower |= 0x80;
     186             : 
     187           0 :                 data[bytes++] = lower;
     188           0 :         } while (tag);
     189             : 
     190           0 :         if (evbuf != NULL)
     191           0 :                 evbuffer_add(evbuf, data, bytes);
     192             : 
     193           0 :         return (bytes);
     194             : }
     195             : 
     196             : static int
     197           0 : decode_tag_internal(ev_uint32_t *ptag, struct evbuffer *evbuf, int dodrain)
     198             : {
     199           0 :         ev_uint32_t number = 0;
     200           0 :         size_t len = evbuffer_get_length(evbuf);
     201             :         ev_uint8_t *data;
     202           0 :         size_t count = 0;
     203           0 :         int  shift = 0, done = 0;
     204             : 
     205             :         /*
     206             :          * the encoding of a number is at most one byte more than its
     207             :          * storage size.  however, it may also be much smaller.
     208             :          */
     209           0 :         data = evbuffer_pullup(
     210           0 :                 evbuf, len < sizeof(number) + 1 ? len : sizeof(number) + 1);
     211           0 :         if (!data)
     212           0 :                 return (-1);
     213             : 
     214           0 :         while (count++ < len) {
     215           0 :                 ev_uint8_t lower = *data++;
     216           0 :                 if (shift >= 28) {
     217             :                         /* Make sure it fits into 32 bits */
     218           0 :                         if (shift > 28)
     219           0 :                                 return (-1);
     220           0 :                         if ((lower & 0x7f) > 15)
     221           0 :                                 return (-1);
     222             :                 }
     223           0 :                 number |= (lower & (unsigned)0x7f) << shift;
     224           0 :                 shift += 7;
     225             : 
     226           0 :                 if (!(lower & 0x80)) {
     227           0 :                         done = 1;
     228           0 :                         break;
     229             :                 }
     230             :         }
     231             : 
     232           0 :         if (!done)
     233           0 :                 return (-1);
     234             : 
     235           0 :         if (dodrain)
     236           0 :                 evbuffer_drain(evbuf, count);
     237             : 
     238           0 :         if (ptag != NULL)
     239           0 :                 *ptag = number;
     240             : 
     241           0 :         return count > INT_MAX ? INT_MAX : (int)(count);
     242             : }
     243             : 
     244             : int
     245           0 : evtag_decode_tag(ev_uint32_t *ptag, struct evbuffer *evbuf)
     246             : {
     247           0 :         return (decode_tag_internal(ptag, evbuf, 1 /* dodrain */));
     248             : }
     249             : 
     250             : /*
     251             :  * Marshal a data type, the general format is as follows:
     252             :  *
     253             :  * tag number: one byte; length: var bytes; payload: var bytes
     254             :  */
     255             : 
     256             : void
     257           0 : evtag_marshal(struct evbuffer *evbuf, ev_uint32_t tag,
     258             :     const void *data, ev_uint32_t len)
     259             : {
     260           0 :         evtag_encode_tag(evbuf, tag);
     261           0 :         evtag_encode_int(evbuf, len);
     262           0 :         evbuffer_add(evbuf, (void *)data, len);
     263           0 : }
     264             : 
     265             : void
     266           0 : evtag_marshal_buffer(struct evbuffer *evbuf, ev_uint32_t tag,
     267             :     struct evbuffer *data)
     268             : {
     269           0 :         evtag_encode_tag(evbuf, tag);
     270             :         /* XXX support more than UINT32_MAX data */
     271           0 :         evtag_encode_int(evbuf, (ev_uint32_t)evbuffer_get_length(data));
     272           0 :         evbuffer_add_buffer(evbuf, data);
     273           0 : }
     274             : 
     275             : /* Marshaling for integers */
     276             : void
     277           0 : evtag_marshal_int(struct evbuffer *evbuf, ev_uint32_t tag, ev_uint32_t integer)
     278             : {
     279             :         ev_uint8_t data[5];
     280           0 :         int len = encode_int_internal(data, integer);
     281             : 
     282           0 :         evtag_encode_tag(evbuf, tag);
     283           0 :         evtag_encode_int(evbuf, len);
     284           0 :         evbuffer_add(evbuf, data, len);
     285           0 : }
     286             : 
     287             : void
     288           0 : evtag_marshal_int64(struct evbuffer *evbuf, ev_uint32_t tag,
     289             :     ev_uint64_t integer)
     290             : {
     291             :         ev_uint8_t data[9];
     292           0 :         int len = encode_int64_internal(data, integer);
     293             : 
     294           0 :         evtag_encode_tag(evbuf, tag);
     295           0 :         evtag_encode_int(evbuf, len);
     296           0 :         evbuffer_add(evbuf, data, len);
     297           0 : }
     298             : 
     299             : void
     300           0 : evtag_marshal_string(struct evbuffer *buf, ev_uint32_t tag, const char *string)
     301             : {
     302             :         /* TODO support strings longer than UINT32_MAX ? */
     303           0 :         evtag_marshal(buf, tag, string, (ev_uint32_t)strlen(string));
     304           0 : }
     305             : 
     306             : void
     307           0 : evtag_marshal_timeval(struct evbuffer *evbuf, ev_uint32_t tag, struct timeval *tv)
     308             : {
     309             :         ev_uint8_t data[10];
     310           0 :         int len = encode_int_internal(data, tv->tv_sec);
     311           0 :         len += encode_int_internal(data + len, tv->tv_usec);
     312           0 :         evtag_marshal(evbuf, tag, data, len);
     313           0 : }
     314             : 
     315             : #define DECODE_INT_INTERNAL(number, maxnibbles, pnumber, evbuf, offset) \
     316             : do {                                                                    \
     317             :         ev_uint8_t *data;                                               \
     318             :         ev_ssize_t len = evbuffer_get_length(evbuf) - offset;           \
     319             :         int nibbles = 0;                                                \
     320             :                                                                         \
     321             :         if (len <= 0)                                                        \
     322             :                 return (-1);                                            \
     323             :                                                                         \
     324             :         /* XXX(niels): faster? */                                       \
     325             :         data = evbuffer_pullup(evbuf, offset + 1) + offset;             \
     326             :         if (!data)                                                      \
     327             :                 return (-1);                                            \
     328             :                                                                         \
     329             :         nibbles = ((data[0] & 0xf0) >> 4) + 1;                                \
     330             :         if (nibbles > maxnibbles || (nibbles >> 1) + 1 > len)               \
     331             :                 return (-1);                                            \
     332             :         len = (nibbles >> 1) + 1;                                 \
     333             :                                                                         \
     334             :         data = evbuffer_pullup(evbuf, offset + len) + offset;           \
     335             :         if (!data)                                                      \
     336             :                 return (-1);                                            \
     337             :                                                                         \
     338             :         while (nibbles > 0) {                                                \
     339             :                 number <<= 4;                                             \
     340             :                 if (nibbles & 0x1)                                  \
     341             :                         number |= data[nibbles >> 1] & 0x0f;          \
     342             :                 else                                                    \
     343             :                         number |= (data[nibbles >> 1] & 0xf0) >> 4;     \
     344             :                 nibbles--;                                              \
     345             :         }                                                               \
     346             :                                                                         \
     347             :         *pnumber = number;                                              \
     348             :                                                                         \
     349             :         return (int)(len);                                              \
     350             : } while (0)
     351             : 
     352             : /* Internal: decode an integer from an evbuffer, without draining it.
     353             :  *  Only integers up to 32-bits are supported.
     354             :  *
     355             :  * @param evbuf the buffer to read from
     356             :  * @param offset an index into the buffer at which we should start reading.
     357             :  * @param pnumber a pointer to receive the integer.
     358             :  * @return The length of the number as encoded, or -1 on error.
     359             :  */
     360             : 
     361             : static int
     362           0 : decode_int_internal(ev_uint32_t *pnumber, struct evbuffer *evbuf, int offset)
     363             : {
     364           0 :         ev_uint32_t number = 0;
     365           0 :         DECODE_INT_INTERNAL(number, 8, pnumber, evbuf, offset);
     366             : }
     367             : 
     368             : static int
     369           0 : decode_int64_internal(ev_uint64_t *pnumber, struct evbuffer *evbuf, int offset)
     370             : {
     371           0 :         ev_uint64_t number = 0;
     372           0 :         DECODE_INT_INTERNAL(number, 16, pnumber, evbuf, offset);
     373             : }
     374             : 
     375             : int
     376           0 : evtag_decode_int(ev_uint32_t *pnumber, struct evbuffer *evbuf)
     377             : {
     378           0 :         int res = decode_int_internal(pnumber, evbuf, 0);
     379           0 :         if (res != -1)
     380           0 :                 evbuffer_drain(evbuf, res);
     381             : 
     382           0 :         return (res == -1 ? -1 : 0);
     383             : }
     384             : 
     385             : int
     386           0 : evtag_decode_int64(ev_uint64_t *pnumber, struct evbuffer *evbuf)
     387             : {
     388           0 :         int res = decode_int64_internal(pnumber, evbuf, 0);
     389           0 :         if (res != -1)
     390           0 :                 evbuffer_drain(evbuf, res);
     391             : 
     392           0 :         return (res == -1 ? -1 : 0);
     393             : }
     394             : 
     395             : int
     396           0 : evtag_peek(struct evbuffer *evbuf, ev_uint32_t *ptag)
     397             : {
     398           0 :         return (decode_tag_internal(ptag, evbuf, 0 /* dodrain */));
     399             : }
     400             : 
     401             : int
     402           0 : evtag_peek_length(struct evbuffer *evbuf, ev_uint32_t *plength)
     403             : {
     404             :         int res, len;
     405             : 
     406           0 :         len = decode_tag_internal(NULL, evbuf, 0 /* dodrain */);
     407           0 :         if (len == -1)
     408           0 :                 return (-1);
     409             : 
     410           0 :         res = decode_int_internal(plength, evbuf, len);
     411           0 :         if (res == -1)
     412           0 :                 return (-1);
     413             : 
     414           0 :         *plength += res + len;
     415             : 
     416           0 :         return (0);
     417             : }
     418             : 
     419             : int
     420           0 : evtag_payload_length(struct evbuffer *evbuf, ev_uint32_t *plength)
     421             : {
     422             :         int res, len;
     423             : 
     424           0 :         len = decode_tag_internal(NULL, evbuf, 0 /* dodrain */);
     425           0 :         if (len == -1)
     426           0 :                 return (-1);
     427             : 
     428           0 :         res = decode_int_internal(plength, evbuf, len);
     429           0 :         if (res == -1)
     430           0 :                 return (-1);
     431             : 
     432           0 :         return (0);
     433             : }
     434             : 
     435             : /* just unmarshals the header and returns the length of the remaining data */
     436             : 
     437             : int
     438           0 : evtag_unmarshal_header(struct evbuffer *evbuf, ev_uint32_t *ptag)
     439             : {
     440             :         ev_uint32_t len;
     441             : 
     442           0 :         if (decode_tag_internal(ptag, evbuf, 1 /* dodrain */) == -1)
     443           0 :                 return (-1);
     444           0 :         if (evtag_decode_int(&len, evbuf) == -1)
     445           0 :                 return (-1);
     446             : 
     447           0 :         if (evbuffer_get_length(evbuf) < len)
     448           0 :                 return (-1);
     449             : 
     450           0 :         return (len);
     451             : }
     452             : 
     453             : int
     454           0 : evtag_consume(struct evbuffer *evbuf)
     455             : {
     456             :         int len;
     457           0 :         if ((len = evtag_unmarshal_header(evbuf, NULL)) == -1)
     458           0 :                 return (-1);
     459           0 :         evbuffer_drain(evbuf, len);
     460             : 
     461           0 :         return (0);
     462             : }
     463             : 
     464             : /* Reads the data type from an event buffer */
     465             : 
     466             : int
     467           0 : evtag_unmarshal(struct evbuffer *src, ev_uint32_t *ptag, struct evbuffer *dst)
     468             : {
     469             :         int len;
     470             : 
     471           0 :         if ((len = evtag_unmarshal_header(src, ptag)) == -1)
     472           0 :                 return (-1);
     473             : 
     474           0 :         if (evbuffer_add(dst, evbuffer_pullup(src, len), len) == -1)
     475           0 :                 return (-1);
     476             : 
     477           0 :         evbuffer_drain(src, len);
     478             : 
     479           0 :         return (len);
     480             : }
     481             : 
     482             : /* Marshaling for integers */
     483             : 
     484             : int
     485           0 : evtag_unmarshal_int(struct evbuffer *evbuf, ev_uint32_t need_tag,
     486             :     ev_uint32_t *pinteger)
     487             : {
     488             :         ev_uint32_t tag;
     489             :         ev_uint32_t len;
     490             :         int result;
     491             : 
     492           0 :         if (decode_tag_internal(&tag, evbuf, 1 /* dodrain */) == -1)
     493           0 :                 return (-1);
     494           0 :         if (need_tag != tag)
     495           0 :                 return (-1);
     496           0 :         if (evtag_decode_int(&len, evbuf) == -1)
     497           0 :                 return (-1);
     498             : 
     499           0 :         if (evbuffer_get_length(evbuf) < len)
     500           0 :                 return (-1);
     501             : 
     502           0 :         result = decode_int_internal(pinteger, evbuf, 0);
     503           0 :         evbuffer_drain(evbuf, len);
     504           0 :         if (result < 0 || (size_t)result > len) /* XXX Should this be != rather than > ?*/
     505           0 :                 return (-1);
     506             :         else
     507           0 :                 return result;
     508             : }
     509             : 
     510             : int
     511           0 : evtag_unmarshal_int64(struct evbuffer *evbuf, ev_uint32_t need_tag,
     512             :     ev_uint64_t *pinteger)
     513             : {
     514             :         ev_uint32_t tag;
     515             :         ev_uint32_t len;
     516             :         int result;
     517             : 
     518           0 :         if (decode_tag_internal(&tag, evbuf, 1 /* dodrain */) == -1)
     519           0 :                 return (-1);
     520           0 :         if (need_tag != tag)
     521           0 :                 return (-1);
     522           0 :         if (evtag_decode_int(&len, evbuf) == -1)
     523           0 :                 return (-1);
     524             : 
     525           0 :         if (evbuffer_get_length(evbuf) < len)
     526           0 :                 return (-1);
     527             : 
     528           0 :         result = decode_int64_internal(pinteger, evbuf, 0);
     529           0 :         evbuffer_drain(evbuf, len);
     530           0 :         if (result < 0 || (size_t)result > len) /* XXX Should this be != rather than > ?*/
     531           0 :                 return (-1);
     532             :         else
     533           0 :                 return result;
     534             : }
     535             : 
     536             : /* Unmarshal a fixed length tag */
     537             : 
     538             : int
     539           0 : evtag_unmarshal_fixed(struct evbuffer *src, ev_uint32_t need_tag, void *data,
     540             :     size_t len)
     541             : {
     542             :         ev_uint32_t tag;
     543             :         int tag_len;
     544             : 
     545             :         /* Now unmarshal a tag and check that it matches the tag we want */
     546           0 :         if ((tag_len = evtag_unmarshal_header(src, &tag)) < 0 ||
     547           0 :             tag != need_tag)
     548           0 :                 return (-1);
     549             : 
     550           0 :         if ((size_t)tag_len != len)
     551           0 :                 return (-1);
     552             : 
     553           0 :         evbuffer_remove(src, data, len);
     554           0 :         return (0);
     555             : }
     556             : 
     557             : int
     558           0 : evtag_unmarshal_string(struct evbuffer *evbuf, ev_uint32_t need_tag,
     559             :     char **pstring)
     560             : {
     561             :         ev_uint32_t tag;
     562             :         int tag_len;
     563             : 
     564           0 :         if ((tag_len = evtag_unmarshal_header(evbuf, &tag)) == -1 ||
     565           0 :             tag != need_tag)
     566           0 :                 return (-1);
     567             : 
     568           0 :         *pstring = mm_malloc(tag_len + 1);
     569           0 :         if (*pstring == NULL) {
     570           0 :                 event_warn("%s: malloc", __func__);
     571           0 :                 return -1;
     572             :         }
     573           0 :         evbuffer_remove(evbuf, *pstring, tag_len);
     574           0 :         (*pstring)[tag_len] = '\0';
     575             : 
     576           0 :         return (0);
     577             : }
     578             : 
     579             : int
     580           0 : evtag_unmarshal_timeval(struct evbuffer *evbuf, ev_uint32_t need_tag,
     581             :     struct timeval *ptv)
     582             : {
     583             :         ev_uint32_t tag;
     584             :         ev_uint32_t integer;
     585             :         int len, offset, offset2;
     586           0 :         int result = -1;
     587             : 
     588           0 :         if ((len = evtag_unmarshal_header(evbuf, &tag)) == -1)
     589           0 :                 return (-1);
     590           0 :         if (tag != need_tag)
     591           0 :                 goto done;
     592           0 :         if ((offset = decode_int_internal(&integer, evbuf, 0)) == -1)
     593           0 :                 goto done;
     594           0 :         ptv->tv_sec = integer;
     595           0 :         if ((offset2 = decode_int_internal(&integer, evbuf, offset)) == -1)
     596           0 :                 goto done;
     597           0 :         ptv->tv_usec = integer;
     598           0 :         if (offset + offset2 > len) /* XXX Should this be != instead of > ? */
     599           0 :                 goto done;
     600             : 
     601           0 :         result = 0;
     602             :  done:
     603           0 :         evbuffer_drain(evbuf, len);
     604           0 :         return result;
     605             : }

Generated by: LCOV version 1.13