LCOV - code coverage report
Current view: top level - xpcom/typelib/xpt - xpt_struct.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 138 197 70.1 %
Date: 2017-07-14 16:53:18 Functions: 10 10 100.0 %
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 routines for typelib structures. */
       7             : 
       8             : #include "xpt_xdr.h"
       9             : #include "xpt_struct.h"
      10             : #include <string.h>
      11             : #include <stdio.h>
      12             : 
      13             : using mozilla::WrapNotNull;
      14             : 
      15             : /***************************************************************************/
      16             : /* Forward declarations. */
      17             : 
      18             : static bool
      19             : DoInterfaceDirectoryEntry(XPTArena *arena, NotNull<XPTCursor*> cursor,
      20             :                           XPTInterfaceDirectoryEntry *ide);
      21             : 
      22             : static bool
      23             : DoConstDescriptor(XPTArena *arena, NotNull<XPTCursor*> cursor,
      24             :                   XPTConstDescriptor *cd, XPTInterfaceDescriptor *id);
      25             : 
      26             : static bool
      27             : DoMethodDescriptor(XPTArena *arena, NotNull<XPTCursor*> cursor,
      28             :                    XPTMethodDescriptor *md, XPTInterfaceDescriptor *id);
      29             : 
      30             : static bool
      31             : SkipAnnotation(NotNull<XPTCursor*> cursor, bool *isLast);
      32             : 
      33             : static bool
      34             : DoInterfaceDescriptor(XPTArena *arena, NotNull<XPTCursor*> outer,
      35             :                       XPTInterfaceDescriptor **idp);
      36             : 
      37             : static bool
      38             : DoTypeDescriptorPrefix(XPTArena *arena, NotNull<XPTCursor*> cursor,
      39             :                        XPTTypeDescriptorPrefix *tdp);
      40             : 
      41             : static bool
      42             : DoTypeDescriptor(XPTArena *arena, NotNull<XPTCursor*> cursor,
      43             :                  XPTTypeDescriptor *td, XPTInterfaceDescriptor *id);
      44             : 
      45             : static bool
      46             : DoParamDescriptor(XPTArena *arena, NotNull<XPTCursor*> cursor,
      47             :                   XPTParamDescriptor *pd, XPTInterfaceDescriptor *id);
      48             : 
      49             : /***************************************************************************/
      50             : 
      51             : XPT_PUBLIC_API(bool)
      52         522 : XPT_DoHeader(XPTArena *arena, NotNull<XPTCursor*> cursor, XPTHeader **headerp)
      53             : {
      54             :     unsigned int i;
      55         522 :     uint32_t file_length = 0;
      56             :     uint32_t ide_offset;
      57             : 
      58         522 :     XPTHeader* header = XPT_NEWZAP(arena, XPTHeader);
      59         522 :     if (!header)
      60           0 :         return false;
      61         522 :     *headerp = header;
      62             : 
      63             :     uint8_t magic[16];
      64        8874 :     for (i = 0; i < sizeof(magic); i++) {
      65        8352 :         if (!XPT_Do8(cursor, &magic[i]))
      66           0 :             return false;
      67             :     }
      68             : 
      69         522 :     if (strncmp((const char*)magic, XPT_MAGIC, 16) != 0) {
      70             :         /* Require that the header contain the proper magic */
      71             :         fprintf(stderr,
      72             :                 "libxpt: bad magic header in input file; "
      73             :                 "found '%s', expected '%s'\n",
      74           0 :                 magic, XPT_MAGIC_STRING);
      75           0 :         return false;
      76             :     }
      77             : 
      78        1044 :     if (!XPT_Do8(cursor, &header->major_version) ||
      79         522 :         !XPT_Do8(cursor, &header->minor_version)) {
      80           0 :         return false;
      81             :     }
      82             : 
      83         522 :     if (header->major_version >= XPT_MAJOR_INCOMPATIBLE_VERSION) {
      84             :         /* This file is newer than we are and set to an incompatible version
      85             :          * number. We must set the header state thusly and return.
      86             :          */
      87           0 :         header->num_interfaces = 0;
      88           0 :         return true;
      89             :     }
      90             : 
      91        1566 :     if (!XPT_Do16(cursor, &header->num_interfaces) ||
      92        1044 :         !XPT_Do32(cursor, &file_length) ||
      93         522 :         !XPT_Do32(cursor, &ide_offset)) {
      94           0 :         return false;
      95             :     }
      96             : 
      97             :     /*
      98             :      * Make sure the file length reported in the header is the same size as
      99             :      * as our buffer unless it is zero (not set)
     100             :      */
     101        1044 :     if (file_length != 0 &&
     102         522 :         cursor->state->pool_allocated < file_length) {
     103             :         fputs("libxpt: File length in header does not match actual length. File may be corrupt\n",
     104           0 :             stderr);
     105           0 :         return false;
     106             :     }
     107             : 
     108             :     uint32_t data_pool;
     109         522 :     if (!XPT_Do32(cursor, &data_pool))
     110           0 :         return false;
     111             : 
     112         522 :     XPT_SetDataOffset(cursor->state, data_pool);
     113             : 
     114         522 :     if (header->num_interfaces) {
     115         483 :         size_t n = header->num_interfaces * sizeof(XPTInterfaceDirectoryEntry);
     116         483 :         header->interface_directory =
     117         483 :             static_cast<XPTInterfaceDirectoryEntry*>(XPT_CALLOC8(arena, n));
     118         483 :         if (!header->interface_directory)
     119           0 :             return false;
     120             :     }
     121             : 
     122             :     /*
     123             :      * Iterate through the annotations rather than recurring, to avoid blowing
     124             :      * the stack on large xpt files. We don't actually store annotations, we
     125             :      * just skip over them.
     126             :      */
     127             :     bool isLast;
     128           0 :     do {
     129         522 :         if (!SkipAnnotation(cursor, &isLast))
     130           0 :             return false;
     131         522 :     } while (!isLast);
     132             : 
     133             :     /* shouldn't be necessary now, but maybe later */
     134         522 :     XPT_SeekTo(cursor, ide_offset);
     135             : 
     136        6924 :     for (i = 0; i < header->num_interfaces; i++) {
     137        6402 :         if (!DoInterfaceDirectoryEntry(arena, cursor,
     138        6402 :                                        &header->interface_directory[i]))
     139           0 :             return false;
     140             :     }
     141             : 
     142         522 :     return true;
     143             : }
     144             : 
     145             : /* InterfaceDirectoryEntry records go in the header */
     146             : bool
     147        6402 : DoInterfaceDirectoryEntry(XPTArena *arena, NotNull<XPTCursor*> cursor,
     148             :                           XPTInterfaceDirectoryEntry *ide)
     149             : {
     150             :     char* dummy_name_space;
     151             : 
     152             :     /* write the IID in our cursor space */
     153       19206 :     if (!XPT_DoIID(cursor, &(ide->iid)) ||
     154             : 
     155             :         /* write the name string in the data pool, and the offset in our
     156             :            cursor space */
     157       12804 :         !XPT_DoCString(arena, cursor, &(ide->name)) ||
     158             : 
     159             :         /* don't write the name_space string in the data pool, because we don't
     160             :          * need it. Do write the offset in our cursor space */
     161       19206 :         !XPT_DoCString(arena, cursor, &dummy_name_space, /* ignore = */ true) ||
     162             : 
     163             :         /* do InterfaceDescriptors */
     164        6402 :         !DoInterfaceDescriptor(arena, cursor, &ide->interface_descriptor)) {
     165           0 :         return false;
     166             :     }
     167             : 
     168        6402 :     return true;
     169             : }
     170             : 
     171             : static bool
     172         759 : InterfaceDescriptorAddTypes(XPTArena *arena, XPTInterfaceDescriptor *id,
     173             :                             uint16_t num)
     174             : {
     175         759 :     XPTTypeDescriptor *old = id->additional_types;
     176             :     XPTTypeDescriptor *new_;
     177         759 :     size_t old_size = id->num_additional_types * sizeof(XPTTypeDescriptor);
     178         759 :     size_t new_size = (num * sizeof(XPTTypeDescriptor)) + old_size;
     179             : 
     180             :     /* XXX should grow in chunks to minimize alloc overhead */
     181         759 :     new_ = static_cast<XPTTypeDescriptor*>(XPT_CALLOC8(arena, new_size));
     182         759 :     if (!new_)
     183           0 :         return false;
     184         759 :     if (old) {
     185         432 :         memcpy(new_, old, old_size);
     186             :     }
     187         759 :     id->additional_types = new_;
     188             : 
     189         759 :     if (num + uint16_t(id->num_additional_types) > 256)
     190           0 :         return false;
     191             : 
     192         759 :     id->num_additional_types += num;
     193         759 :     return true;
     194             : }
     195             : 
     196             : bool
     197        6402 : DoInterfaceDescriptor(XPTArena *arena, NotNull<XPTCursor*> outer,
     198             :                       XPTInterfaceDescriptor **idp)
     199             : {
     200             :     XPTInterfaceDescriptor *id;
     201             :     XPTCursor curs;
     202        6402 :     NotNull<XPTCursor*> cursor = WrapNotNull(&curs);
     203        6402 :     uint32_t i, id_sz = 0;
     204             : 
     205        6402 :     id = XPT_NEWZAP(arena, XPTInterfaceDescriptor);
     206        6402 :     if (!id)
     207           0 :         return false;
     208        6402 :     *idp = id;
     209             : 
     210        6402 :     if (!XPT_MakeCursor(outer->state, XPT_DATA, id_sz, cursor))
     211           0 :         return false;
     212             : 
     213        6402 :     if (!XPT_Do32(outer, &cursor->offset))
     214           0 :         return false;
     215        6402 :     if (!cursor->offset) {
     216        2520 :         *idp = NULL;
     217        2520 :         return true;
     218             :     }
     219        7764 :     if(!XPT_Do16(cursor, &id->parent_interface) ||
     220        3882 :        !XPT_Do16(cursor, &id->num_methods)) {
     221           0 :         return false;
     222             :     }
     223             : 
     224        3882 :     if (id->num_methods) {
     225        3732 :         size_t n = id->num_methods * sizeof(XPTMethodDescriptor);
     226        3732 :         id->method_descriptors =
     227        3732 :             static_cast<XPTMethodDescriptor*>(XPT_CALLOC8(arena, n));
     228        3732 :         if (!id->method_descriptors)
     229           0 :             return false;
     230             :     }
     231             : 
     232       29610 :     for (i = 0; i < id->num_methods; i++) {
     233       25728 :         if (!DoMethodDescriptor(arena, cursor, &id->method_descriptors[i], id))
     234           0 :             return false;
     235             :     }
     236             : 
     237        3882 :     if (!XPT_Do16(cursor, &id->num_constants)) {
     238           0 :         return false;
     239             :     }
     240             : 
     241        3882 :     if (id->num_constants) {
     242         786 :         size_t n = id->num_constants * sizeof(XPTConstDescriptor);
     243         786 :         id->const_descriptors =
     244         786 :             static_cast<XPTConstDescriptor*>(XPT_CALLOC8(arena, n));
     245         786 :         if (!id->const_descriptors)
     246           0 :             return false;
     247             :     }
     248             : 
     249       11463 :     for (i = 0; i < id->num_constants; i++) {
     250        7581 :         if (!DoConstDescriptor(arena, cursor, &id->const_descriptors[i], id)) {
     251           0 :             return false;
     252             :         }
     253             :     }
     254             : 
     255        3882 :     if (!XPT_Do8(cursor, &id->flags)) {
     256           0 :         return false;
     257             :     }
     258             : 
     259        3882 :     return true;
     260             : }
     261             : 
     262             : bool
     263        7581 : DoConstDescriptor(XPTArena *arena, NotNull<XPTCursor*> cursor,
     264             :                   XPTConstDescriptor *cd, XPTInterfaceDescriptor *id)
     265             : {
     266        7581 :     bool ok = false;
     267             : 
     268       15162 :     if (!XPT_DoCString(arena, cursor, &cd->name) ||
     269        7581 :         !DoTypeDescriptor(arena, cursor, &cd->type, id)) {
     270             : 
     271           0 :         return false;
     272             :     }
     273             : 
     274        7581 :     switch(XPT_TDP_TAG(cd->type.prefix)) {
     275             :       case TD_INT8:
     276           0 :         ok = XPT_Do8(cursor, (uint8_t*) &cd->value.i8);
     277           0 :         break;
     278             :       case TD_INT16:
     279         762 :         ok = XPT_Do16(cursor, (uint16_t*) &cd->value.i16);
     280         762 :         break;
     281             :       case TD_INT32:
     282        1278 :         ok = XPT_Do32(cursor, (uint32_t*) &cd->value.i32);
     283        1278 :         break;
     284             :       case TD_INT64:
     285           0 :         ok = XPT_Do64(cursor, &cd->value.i64);
     286           0 :         break;
     287             :       case TD_UINT8:
     288           0 :         ok = XPT_Do8(cursor, &cd->value.ui8);
     289           0 :         break;
     290             :       case TD_UINT16:
     291         831 :         ok = XPT_Do16(cursor, &cd->value.ui16);
     292         831 :         break;
     293             :       case TD_UINT32:
     294        4710 :         ok = XPT_Do32(cursor, &cd->value.ui32);
     295        4710 :         break;
     296             :       case TD_UINT64:
     297           0 :         ok = XPT_Do64(cursor, (int64_t *)&cd->value.ui64);
     298           0 :         break;
     299             :       case TD_CHAR:
     300           0 :         ok = XPT_Do8(cursor, (uint8_t*) &cd->value.ch);
     301           0 :         break;
     302             :       case TD_WCHAR:
     303           0 :         ok = XPT_Do16(cursor, &cd->value.wch);
     304           0 :         break;
     305             :         /* fall-through */
     306             :       default:
     307           0 :         fprintf(stderr, "illegal type!\n");
     308           0 :         break;
     309             :     }
     310             : 
     311        7581 :     return ok;
     312             : 
     313             : }
     314             : 
     315             : bool
     316       25728 : DoMethodDescriptor(XPTArena *arena, NotNull<XPTCursor*> cursor,
     317             :                    XPTMethodDescriptor *md, XPTInterfaceDescriptor *id)
     318             : {
     319             :     int i;
     320             : 
     321       77184 :     if (!XPT_Do8(cursor, &md->flags) ||
     322       51456 :         !XPT_DoCString(arena, cursor, &md->name) ||
     323       25728 :         !XPT_Do8(cursor, &md->num_args))
     324           0 :         return false;
     325             : 
     326       25728 :     if (md->num_args) {
     327       23832 :         size_t n = md->num_args * sizeof(XPTParamDescriptor);
     328       23832 :         md->params = static_cast<XPTParamDescriptor*>(XPT_CALLOC8(arena, n));
     329       23832 :         if (!md->params)
     330           0 :             return false;
     331             :     }
     332             : 
     333       67218 :     for(i = 0; i < md->num_args; i++) {
     334       41490 :         if (!DoParamDescriptor(arena, cursor, &md->params[i], id))
     335           0 :             return false;
     336             :     }
     337             : 
     338       25728 :     if (!DoParamDescriptor(arena, cursor, &md->result, id))
     339           0 :         return false;
     340             : 
     341       25728 :     return true;
     342             : }
     343             : 
     344             : bool
     345       67218 : DoParamDescriptor(XPTArena *arena, NotNull<XPTCursor*> cursor,
     346             :                   XPTParamDescriptor *pd, XPTInterfaceDescriptor *id)
     347             : {
     348      134436 :     if (!XPT_Do8(cursor, &pd->flags) ||
     349       67218 :         !DoTypeDescriptor(arena, cursor, &pd->type, id))
     350           0 :         return false;
     351             : 
     352       67218 :     return true;
     353             : }
     354             : 
     355             : bool
     356       75558 : DoTypeDescriptorPrefix(XPTArena *arena, NotNull<XPTCursor*> cursor,
     357             :                        XPTTypeDescriptorPrefix *tdp)
     358             : {
     359       75558 :     return XPT_Do8(cursor, &tdp->flags);
     360             : }
     361             : 
     362             : bool
     363       75558 : DoTypeDescriptor(XPTArena *arena, NotNull<XPTCursor*> cursor,
     364             :                  XPTTypeDescriptor *td, XPTInterfaceDescriptor *id)
     365             : {
     366       75558 :     if (!DoTypeDescriptorPrefix(arena, cursor, &td->prefix)) {
     367           0 :         return false;
     368             :     }
     369             : 
     370       75558 :     switch (XPT_TDP_TAG(td->prefix)) {
     371             :       case TD_INTERFACE_TYPE:
     372             :         uint16_t iface;
     373       12303 :         if (!XPT_Do16(cursor, &iface))
     374           0 :             return false;
     375       12303 :         td->u.iface.iface_hi8 = (iface >> 8) & 0xff;
     376       12303 :         td->u.iface.iface_lo8 = iface & 0xff;
     377       87861 :         break;
     378             :       case TD_INTERFACE_IS_TYPE:
     379          99 :         if (!XPT_Do8(cursor, &td->u.interface_is.argnum))
     380           0 :             return false;
     381          99 :         break;
     382             :       case TD_ARRAY: {
     383             :         // argnum2 appears in the on-disk format but it isn't used.
     384         759 :         uint8_t argnum2 = 0;
     385        1518 :         if (!XPT_Do8(cursor, &td->u.array.argnum) ||
     386         759 :             !XPT_Do8(cursor, &argnum2))
     387           0 :             return false;
     388             : 
     389         759 :         if (!InterfaceDescriptorAddTypes(arena, id, 1))
     390           0 :             return false;
     391         759 :         td->u.array.additional_type = id->num_additional_types - 1;
     392             : 
     393         759 :         if (!DoTypeDescriptor(arena, cursor,
     394         759 :                               &id->additional_types[td->u.array.additional_type],
     395             :                               id))
     396           0 :             return false;
     397         759 :         break;
     398             :       }
     399             :       case TD_PSTRING_SIZE_IS:
     400             :       case TD_PWSTRING_SIZE_IS: {
     401             :         // argnum2 appears in the on-disk format but it isn't used.
     402          63 :         uint8_t argnum2 = 0;
     403         126 :         if (!XPT_Do8(cursor, &td->u.pstring_is.argnum) ||
     404          63 :             !XPT_Do8(cursor, &argnum2))
     405           0 :             return false;
     406          63 :         break;
     407             :       }
     408             :       default:
     409             :         /* nothing special */
     410       62334 :         break;
     411             :     }
     412       75558 :     return true;
     413             : }
     414             : 
     415             : bool
     416         522 : SkipAnnotation(NotNull<XPTCursor*> cursor, bool *isLast)
     417             : {
     418             :     uint8_t flags;
     419         522 :     if (!XPT_Do8(cursor, &flags))
     420           0 :         return false;
     421             : 
     422         522 :     *isLast = XPT_ANN_IS_LAST(flags);
     423             : 
     424         522 :     if (XPT_ANN_IS_PRIVATE(flags)) {
     425           0 :         if (!XPT_SkipStringInline(cursor) ||
     426           0 :             !XPT_SkipStringInline(cursor))
     427           0 :             return false;
     428             :     }
     429             : 
     430         522 :     return true;
     431             : }
     432             : 

Generated by: LCOV version 1.13