LCOV - code coverage report
Current view: top level - xpcom/typelib/xpt - xpt_xdr.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 61 83 73.5 %
Date: 2017-07-14 16:53:18 Functions: 10 12 83.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : /* Implementation of XDR primitives. */
       7             : 
       8             : #include "xpt_xdr.h"
       9             : #include "nscore.h"
      10             : #include <string.h>             /* strchr */
      11             : #include "mozilla/EndianUtils.h"
      12             : 
      13             : #define CURS_POOL_OFFSET_RAW(cursor)                                          \
      14             :   ((cursor)->pool == XPT_HEADER                                               \
      15             :    ? (cursor)->offset                                                         \
      16             :    : (XPT_ASSERT((cursor)->state->data_offset),                               \
      17             :       (cursor)->offset + (cursor)->state->data_offset))
      18             : 
      19             : #define CURS_POOL_OFFSET(cursor)                                              \
      20             :   (CURS_POOL_OFFSET_RAW(cursor) - 1)
      21             : 
      22             : /* can be used as lvalue */
      23             : #define CURS_POINT(cursor)                                                    \
      24             :   ((cursor)->state->pool_data[CURS_POOL_OFFSET(cursor)])
      25             : 
      26             : static bool
      27      373254 : CHECK_COUNT(NotNull<XPTCursor*> cursor, uint32_t space)
      28             : {
      29             :     // Fail if we're in the data area and about to exceed the allocation.
      30             :     // XXX Also fail if we're in the data area and !state->data_offset
      31      644352 :     if (cursor->pool == XPT_DATA &&
      32      271098 :         (CURS_POOL_OFFSET(cursor) + space > (cursor)->state->pool_allocated)) {
      33           0 :         XPT_ASSERT(0);
      34           0 :         fprintf(stderr, "FATAL: no room for %d in cursor\n", space);
      35           0 :         return false;
      36             :     }
      37             : 
      38      373254 :     return true;
      39             : }
      40             : 
      41             : XPT_PUBLIC_API(void)
      42         522 : XPT_InitXDRState(XPTState* state, char *data, uint32_t len)
      43             : {
      44         522 :     state->next_cursor[0] = state->next_cursor[1] = 1;
      45         522 :     state->pool_data = data;
      46         522 :     state->pool_allocated = len;
      47         522 : }
      48             : 
      49             : /* All offsets are 1-based */
      50             : XPT_PUBLIC_API(void)
      51         522 : XPT_SetDataOffset(XPTState *state, uint32_t data_offset)
      52             : {
      53         522 :    state->data_offset = data_offset;
      54         522 : }
      55             : 
      56             : XPT_PUBLIC_API(bool)
      57        6924 : XPT_MakeCursor(XPTState *state, XPTPool pool, uint32_t len,
      58             :                NotNull<XPTCursor*> cursor)
      59             : {
      60        6924 :     cursor->state = state;
      61        6924 :     cursor->pool = pool;
      62        6924 :     cursor->bits = 0;
      63        6924 :     cursor->offset = state->next_cursor[pool];
      64             : 
      65        6924 :     if (!(CHECK_COUNT(cursor, len)))
      66           0 :         return false;
      67             : 
      68             :     /* this check should be in CHECK_CURSOR */
      69        6924 :     if (pool == XPT_DATA && !state->data_offset) {
      70           0 :         fprintf(stderr, "no data offset for XPT_DATA cursor!\n");
      71           0 :         return false;
      72             :     }
      73             : 
      74        6924 :     state->next_cursor[pool] += len;
      75             : 
      76        6924 :     return true;
      77             : }
      78             : 
      79             : XPT_PUBLIC_API(bool)
      80         522 : XPT_SeekTo(NotNull<XPTCursor*> cursor, uint32_t offset)
      81             : {
      82             :     /* XXX do some real checking and update len and stuff */
      83         522 :     cursor->offset = offset;
      84         522 :     return true;
      85             : }
      86             : 
      87             : XPT_PUBLIC_API(bool)
      88           0 : XPT_SkipStringInline(NotNull<XPTCursor*> cursor)
      89             : {
      90             :     uint16_t length;
      91           0 :     if (!XPT_Do16(cursor, &length))
      92           0 :         return false;
      93             : 
      94             :     uint8_t byte;
      95           0 :     for (uint16_t i = 0; i < length; i++)
      96           0 :         if (!XPT_Do8(cursor, &byte))
      97           0 :             return false;
      98             : 
      99           0 :     return true;
     100             : }
     101             : 
     102             : XPT_PUBLIC_API(bool)
     103       46113 : XPT_DoCString(XPTArena *arena, NotNull<XPTCursor*> cursor, char **identp,
     104             :               bool ignore)
     105             : {
     106       46113 :     uint32_t offset = 0;
     107       46113 :     if (!XPT_Do32(cursor, &offset))
     108           0 :         return false;
     109             : 
     110       46113 :     if (!offset) {
     111        6402 :         *identp = NULL;
     112        6402 :         return true;
     113             :     }
     114             : 
     115             :     XPTCursor my_cursor;
     116       39711 :     my_cursor.pool = XPT_DATA;
     117       39711 :     my_cursor.offset = offset;
     118       39711 :     my_cursor.state = cursor->state;
     119       39711 :     char* start = &CURS_POINT(&my_cursor);
     120             : 
     121       39711 :     char* end = strchr(start, 0); /* find the end of the string */
     122       39711 :     if (!end) {
     123           0 :         fprintf(stderr, "didn't find end of string on decode!\n");
     124           0 :         return false;
     125             :     }
     126       39711 :     int len = end - start;
     127       39711 :     XPT_ASSERT(len > 0);
     128             : 
     129       39711 :     if (!ignore) {
     130       39711 :         char *ident = (char*)XPT_CALLOC1(arena, len + 1u);
     131       39711 :         if (!ident)
     132           0 :             return false;
     133             : 
     134       39711 :         memcpy(ident, start, (size_t)len);
     135       39711 :         ident[len] = 0;
     136       39711 :         *identp = ident;
     137             :     }
     138             : 
     139       39711 :     return true;
     140             : }
     141             : 
     142             : /*
     143             :  * IIDs are written in struct order, in the usual big-endian way.  From the
     144             :  * typelib file spec:
     145             :  *
     146             :  *   "For example, this IID:
     147             :  *     {00112233-4455-6677-8899-aabbccddeeff}
     148             :  *   is converted to the 128-bit value
     149             :  *     0x00112233445566778899aabbccddeeff
     150             :  *   Note that the byte storage order corresponds to the layout of the nsIID
     151             :  *   C-struct on a big-endian architecture."
     152             :  *
     153             :  * (http://www.mozilla.org/scriptable/typelib_file.html#iid)
     154             :  */
     155             : XPT_PUBLIC_API(bool)
     156        6402 : XPT_DoIID(NotNull<XPTCursor*> cursor, nsID *iidp)
     157             : {
     158             :     int i;
     159             : 
     160       19206 :     if (!XPT_Do32(cursor, &iidp->m0) ||
     161       12804 :         !XPT_Do16(cursor, &iidp->m1) ||
     162        6402 :         !XPT_Do16(cursor, &iidp->m2))
     163           0 :         return false;
     164             : 
     165       57618 :     for (i = 0; i < 8; i++)
     166       51216 :         if (!XPT_Do8(cursor, (uint8_t *)&iidp->m3[i]))
     167           0 :             return false;
     168             : 
     169        6402 :     return true;
     170             : }
     171             : 
     172             : // MSVC apparently cannot handle functions as template parameters very well,
     173             : // so we need to use a macro approach here.
     174             : 
     175             : #define XPT_DOINT(T, func, valuep)                \
     176             :     do {                                          \
     177             :         const size_t sz = sizeof(T);              \
     178             :                                                   \
     179             :         if (!CHECK_COUNT(cursor, sz)) {           \
     180             :             return false;                         \
     181             :         }                                         \
     182             :                                                   \
     183             :         *valuep = func(&CURS_POINT(cursor));      \
     184             :         cursor->offset += sz;                     \
     185             :         return true;                              \
     186             :     } while(0)
     187             : 
     188             : XPT_PUBLIC_API(bool)
     189           0 : XPT_Do64(NotNull<XPTCursor*> cursor, int64_t *u64p)
     190             : {
     191           0 :     XPT_DOINT(int64_t, mozilla::BigEndian::readInt64, u64p);
     192             : }
     193             : 
     194             : /*
     195             :  * When we're handling 32- or 16-bit quantities, we handle a byte at a time to
     196             :  * avoid alignment issues.  Someone could come and optimize this to detect
     197             :  * well-aligned cases and do a single store, if they cared.  I might care
     198             :  * later.
     199             :  */
     200             : XPT_PUBLIC_API(bool)
     201       66471 : XPT_Do32(NotNull<XPTCursor*> cursor, uint32_t *u32p)
     202             : {
     203       66471 :     XPT_DOINT(uint32_t, mozilla::BigEndian::readUint32, u32p);
     204             : }
     205             : 
     206             : XPT_PUBLIC_API(bool)
     207       38868 : XPT_Do16(NotNull<XPTCursor*> cursor, uint16_t *u16p)
     208             : {
     209       38868 :     XPT_DOINT(uint16_t, mozilla::BigEndian::readUint16, u16p);
     210             : }
     211             : 
     212             : #undef XPT_DOINT
     213             : 
     214             : XPT_PUBLIC_API(bool)
     215      260991 : XPT_Do8(NotNull<XPTCursor*> cursor, uint8_t *u8p)
     216             : {
     217      260991 :     if (!CHECK_COUNT(cursor, 1))
     218           0 :         return false;
     219             : 
     220      260991 :     *u8p = CURS_POINT(cursor);
     221             : 
     222      260991 :     cursor->offset++;
     223             : 
     224      260991 :     return true;
     225             : }
     226             : 
     227             : 

Generated by: LCOV version 1.13