Home | History | Annotate | Download | only in dbus
      1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
      2 /* dbus-signature.c  Routines for reading recursive type signatures
      3  *
      4  * Copyright (C) 2005 Red Hat, Inc.
      5  *
      6  * Licensed under the Academic Free License version 2.1
      7  *
      8  * This program is free software; you can redistribute it and/or modify
      9  * it under the terms of the GNU General Public License as published by
     10  * the Free Software Foundation; either version 2 of the License, or
     11  * (at your option) any later version.
     12  *
     13  * This program is distributed in the hope that it will be useful,
     14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  * GNU General Public License for more details.
     17  *
     18  * You should have received a copy of the GNU General Public License
     19  * along with this program; if not, write to the Free Software
     20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
     21  *
     22  */
     23 
     24 #include <config.h>
     25 
     26 #include "dbus-signature.h"
     27 #include "dbus-marshal-recursive.h"
     28 #include "dbus-marshal-basic.h"
     29 #include "dbus-internals.h"
     30 #include "dbus-test.h"
     31 
     32 /**
     33  * Implementation details of #DBusSignatureIter, all fields are private
     34  */
     35 typedef struct
     36 {
     37   const char *pos;           /**< current position in the signature string */
     38   unsigned int finished : 1; /**< true if we are at the end iter */
     39   unsigned int in_array : 1; /**< true if we are a subiterator pointing to an array's element type */
     40 } DBusSignatureRealIter;
     41 
     42 /** macro that checks whether a typecode is a container type */
     43 #define TYPE_IS_CONTAINER(typecode)             \
     44     ((typecode) == DBUS_TYPE_STRUCT ||          \
     45      (typecode) == DBUS_TYPE_DICT_ENTRY ||      \
     46      (typecode) == DBUS_TYPE_VARIANT ||         \
     47      (typecode) == DBUS_TYPE_ARRAY)
     48 
     49 
     50 /**
     51  * @defgroup DBusSignature Type signature parsing
     52  * @ingroup  DBus
     53  * @brief Parsing D-Bus type signatures
     54  * @{
     55  */
     56 
     57 /**
     58  * Initializes a #DBusSignatureIter for reading a type signature.  This
     59  * function is not safe to use on invalid signatures; be sure to
     60  * validate potentially invalid signatures with dbus_signature_validate
     61  * before using this function.
     62  *
     63  * @param iter pointer to an iterator to initialize
     64  * @param signature the type signature
     65  */
     66 void
     67 dbus_signature_iter_init (DBusSignatureIter *iter,
     68 			  const char        *signature)
     69 {
     70   DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter;
     71 
     72   real_iter->pos = signature;
     73   real_iter->finished = FALSE;
     74   real_iter->in_array = FALSE;
     75 }
     76 
     77 /**
     78  * Returns the current type pointed to by the iterator.
     79  * If the iterator is pointing at a type code such as 's', then
     80  * it will be returned directly.
     81  *
     82  * However, when the parser encounters a container type start
     83  * character such as '(' for a structure, the corresponding type for
     84  * the container will be returned, e.g.  DBUS_TYPE_STRUCT, not '('.
     85  * In this case, you should initialize a sub-iterator with
     86  * dbus_signature_iter_recurse() to parse the container type.
     87  *
     88  * @param iter pointer to an iterator
     89  * @returns current type (e.g. #DBUS_TYPE_STRING, #DBUS_TYPE_ARRAY)
     90  */
     91 int
     92 dbus_signature_iter_get_current_type (const DBusSignatureIter *iter)
     93 {
     94   DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter;
     95 
     96   return _dbus_first_type_in_signature_c_str (real_iter->pos, 0);
     97 }
     98 
     99 /**
    100  * Returns the signature of the single complete type starting at the
    101  * given iterator.
    102  *
    103  * For example, if the iterator is pointing at the start of "(ii)ii"
    104  * (which is "a struct of two ints, followed by an int, followed by an
    105  * int"), then "(ii)" would be returned. If the iterator is pointing at
    106  * one of the "i" then just that "i" would be returned.
    107  *
    108  * @param iter pointer to an iterator
    109  * @returns current signature; or #NULL if no memory.  Should be freed with dbus_free()
    110  */
    111 char *
    112 dbus_signature_iter_get_signature (const DBusSignatureIter *iter)
    113 {
    114   DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter;
    115   DBusString str;
    116   char *ret;
    117   int pos;
    118 
    119   if (!_dbus_string_init (&str))
    120     return NULL;
    121 
    122   pos = 0;
    123   _dbus_type_signature_next (real_iter->pos, &pos);
    124 
    125   if (!_dbus_string_append_len (&str, real_iter->pos, pos))
    126     return NULL;
    127   if (!_dbus_string_steal_data (&str, &ret))
    128     ret = NULL;
    129   _dbus_string_free (&str);
    130 
    131   return ret;
    132 }
    133 
    134 /**
    135  * Convenience function for returning the element type of an array;
    136  * This function allows you to avoid initializing a sub-iterator and
    137  * getting its current type.
    138  *
    139  * Undefined behavior results if you invoke this function when the
    140  * current type of the iterator is not #DBUS_TYPE_ARRAY.
    141  *
    142  * @param iter pointer to an iterator
    143  * @returns current array element type
    144  */
    145 int
    146 dbus_signature_iter_get_element_type (const DBusSignatureIter *iter)
    147 {
    148   DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter;
    149 
    150   _dbus_return_val_if_fail (dbus_signature_iter_get_current_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID);
    151 
    152   return _dbus_first_type_in_signature_c_str (real_iter->pos, 1);
    153 }
    154 
    155 /**
    156  * Skip to the next value on this "level". e.g. the next field in a
    157  * struct, the next value in an array. Returns #FALSE at the end of the
    158  * current container.
    159  *
    160  * @param iter the iterator
    161  * @returns FALSE if nothing more to read at or below this level
    162  */
    163 dbus_bool_t
    164 dbus_signature_iter_next (DBusSignatureIter *iter)
    165 {
    166   DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter;
    167 
    168   if (real_iter->finished)
    169     return FALSE;
    170   else
    171     {
    172       int pos;
    173 
    174       if (real_iter->in_array)
    175 	{
    176 	  real_iter->finished = TRUE;
    177 	  return FALSE;
    178 	}
    179 
    180       pos = 0;
    181       _dbus_type_signature_next (real_iter->pos, &pos);
    182       real_iter->pos += pos;
    183 
    184       if (*real_iter->pos == DBUS_STRUCT_END_CHAR
    185 	  || *real_iter->pos == DBUS_DICT_ENTRY_END_CHAR)
    186 	{
    187 	  real_iter->finished = TRUE;
    188 	  return FALSE;
    189 	}
    190 
    191       return *real_iter->pos != DBUS_TYPE_INVALID;
    192     }
    193 }
    194 
    195 /**
    196  * Initialize a new iterator pointing to the first type in the current
    197  * container.
    198  *
    199  * The results are undefined when calling this if the current type is
    200  * a non-container (i.e. if dbus_type_is_container() returns #FALSE
    201  * for the result of dbus_signature_iter_get_current_type()).
    202  *
    203  * @param iter the current interator
    204  * @param subiter an iterator to initialize pointing to the first child
    205  */
    206 void
    207 dbus_signature_iter_recurse (const DBusSignatureIter *iter,
    208 			     DBusSignatureIter       *subiter)
    209 {
    210   DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter;
    211   DBusSignatureRealIter *real_sub_iter = (DBusSignatureRealIter *) subiter;
    212 
    213   _dbus_return_if_fail (dbus_type_is_container (dbus_signature_iter_get_current_type (iter)));
    214 
    215   *real_sub_iter = *real_iter;
    216   real_sub_iter->in_array = FALSE;
    217   real_sub_iter->pos++;
    218 
    219   if (dbus_signature_iter_get_current_type (iter) == DBUS_TYPE_ARRAY)
    220     real_sub_iter->in_array = TRUE;
    221 }
    222 
    223 /**
    224  * Check a type signature for validity. Remember that #NULL can always
    225  * be passed instead of a DBusError*, if you don't care about having
    226  * an error name and message.
    227  *
    228  * @param signature a potentially invalid type signature
    229  * @param error error return
    230  * @returns #TRUE if signature is valid or #FALSE if an error is set
    231  */
    232 dbus_bool_t
    233 dbus_signature_validate (const char       *signature,
    234 			 DBusError        *error)
    235 
    236 {
    237   DBusString str;
    238   DBusValidity reason;
    239 
    240   _dbus_string_init_const (&str, signature);
    241   reason = _dbus_validate_signature_with_reason (&str, 0, _dbus_string_get_length (&str));
    242 
    243   if (reason == DBUS_VALID)
    244     return TRUE;
    245   else
    246     {
    247       dbus_set_error (error, DBUS_ERROR_INVALID_SIGNATURE, _dbus_validity_to_error_message (reason));
    248       return FALSE;
    249     }
    250 }
    251 
    252 /**
    253  * Check that a type signature is both valid and contains exactly one
    254  * complete type. "One complete type" means a single basic type,
    255  * array, struct, or dictionary, though the struct or array may be
    256  * arbitrarily recursive and complex. More than one complete type
    257  * would mean for example "ii" or two integers in sequence.
    258  *
    259  * @param signature a potentially invalid type signature
    260  * @param error error return
    261  * @returns #TRUE if signature is valid and has exactly one complete type
    262  */
    263 dbus_bool_t
    264 dbus_signature_validate_single (const char       *signature,
    265 				DBusError        *error)
    266 {
    267   DBusSignatureIter iter;
    268 
    269   if (!dbus_signature_validate (signature, error))
    270     return FALSE;
    271 
    272   dbus_signature_iter_init (&iter, signature);
    273   if (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_INVALID)
    274     goto lose;
    275   if (!dbus_signature_iter_next (&iter))
    276     return TRUE;
    277  lose:
    278   dbus_set_error (error, DBUS_ERROR_INVALID_SIGNATURE, "Exactly one complete type required in signature");
    279   return FALSE;
    280 }
    281 
    282 /**
    283  * A "container type" can contain basic types, or nested
    284  * container types. #DBUS_TYPE_INVALID is not a container type.
    285  *
    286  * It is an error to pass an invalid type-code, other than DBUS_TYPE_INVALID,
    287  * to this function. The valid type-codes are defined by dbus-protocol.h
    288  * and can be checked with dbus_type_is_valid().
    289  *
    290  * @param typecode either a valid type-code or DBUS_TYPE_INVALID
    291  * @returns #TRUE if type is a container
    292  */
    293 dbus_bool_t
    294 dbus_type_is_container (int typecode)
    295 {
    296   /* only reasonable (non-line-noise) typecodes are allowed */
    297   _dbus_return_val_if_fail (dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID,
    298 			    FALSE);
    299   return TYPE_IS_CONTAINER (typecode);
    300 }
    301 
    302 /**
    303  * A "basic type" is a somewhat arbitrary concept, but the intent is
    304  * to include those types that are fully-specified by a single
    305  * typecode, with no additional type information or nested values. So
    306  * all numbers and strings are basic types and structs, arrays, and
    307  * variants are not basic types.  #DBUS_TYPE_INVALID is not a basic
    308  * type.
    309  *
    310  * It is an error to pass an invalid type-code, other than DBUS_TYPE_INVALID,
    311  * to this function. The valid type-codes are defined by dbus-protocol.h
    312  * and can be checked with dbus_type_is_valid().
    313  *
    314  * @param typecode either a valid type-code or DBUS_TYPE_INVALID
    315  * @returns #TRUE if type is basic
    316  */
    317 dbus_bool_t
    318 dbus_type_is_basic (int typecode)
    319 {
    320   /* only reasonable (non-line-noise) typecodes are allowed */
    321   _dbus_return_val_if_fail (dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID,
    322 			    FALSE);
    323 
    324   /* everything that isn't invalid or a container */
    325   return !(typecode == DBUS_TYPE_INVALID || TYPE_IS_CONTAINER (typecode));
    326 }
    327 
    328 /**
    329  * Tells you whether values of this type can change length if you set
    330  * them to some other value. For this purpose, you assume that the
    331  * first byte of the old and new value would be in the same location,
    332  * so alignment padding is not a factor.
    333  *
    334  * This function is useful to determine whether
    335  * dbus_message_iter_get_fixed_array() may be used.
    336  *
    337  * Some structs are fixed-size (if they contain only fixed-size types)
    338  * but struct is not considered a fixed type for purposes of this
    339  * function.
    340  *
    341  * It is an error to pass an invalid type-code, other than DBUS_TYPE_INVALID,
    342  * to this function. The valid type-codes are defined by dbus-protocol.h
    343  * and can be checked with dbus_type_is_valid().
    344  *
    345  * @param typecode either a valid type-code or DBUS_TYPE_INVALID
    346  * @returns #FALSE if the type can occupy different lengths
    347  */
    348 dbus_bool_t
    349 dbus_type_is_fixed (int typecode)
    350 {
    351   /* only reasonable (non-line-noise) typecodes are allowed */
    352   _dbus_return_val_if_fail (dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID,
    353 			    FALSE);
    354 
    355   switch (typecode)
    356     {
    357     case DBUS_TYPE_BYTE:
    358     case DBUS_TYPE_BOOLEAN:
    359     case DBUS_TYPE_INT16:
    360     case DBUS_TYPE_UINT16:
    361     case DBUS_TYPE_INT32:
    362     case DBUS_TYPE_UINT32:
    363     case DBUS_TYPE_INT64:
    364     case DBUS_TYPE_UINT64:
    365     case DBUS_TYPE_DOUBLE:
    366     case DBUS_TYPE_UNIX_FD:
    367       return TRUE;
    368     default:
    369       return FALSE;
    370     }
    371 }
    372 
    373 /**
    374  * Return #TRUE if the argument is a valid typecode.
    375  * #DBUS_TYPE_INVALID surprisingly enough is not considered valid, and
    376  * random unknown bytes aren't either. This function is safe with
    377  * untrusted data.
    378  *
    379  * @param typecode a potential type-code
    380  * @returns #TRUE if valid
    381  */
    382 dbus_bool_t
    383 dbus_type_is_valid (int typecode)
    384 {
    385   switch (typecode)
    386     {
    387     case DBUS_TYPE_BYTE:
    388     case DBUS_TYPE_BOOLEAN:
    389     case DBUS_TYPE_INT16:
    390     case DBUS_TYPE_UINT16:
    391     case DBUS_TYPE_INT32:
    392     case DBUS_TYPE_UINT32:
    393     case DBUS_TYPE_INT64:
    394     case DBUS_TYPE_UINT64:
    395     case DBUS_TYPE_DOUBLE:
    396     case DBUS_TYPE_STRING:
    397     case DBUS_TYPE_OBJECT_PATH:
    398     case DBUS_TYPE_SIGNATURE:
    399     case DBUS_TYPE_ARRAY:
    400     case DBUS_TYPE_STRUCT:
    401     case DBUS_TYPE_DICT_ENTRY:
    402     case DBUS_TYPE_VARIANT:
    403     case DBUS_TYPE_UNIX_FD:
    404       return TRUE;
    405 
    406     default:
    407       return FALSE;
    408     }
    409 }
    410 
    411 /** @} */ /* end of DBusSignature group */
    412 
    413 #ifdef DBUS_BUILD_TESTS
    414 
    415 /**
    416  * @ingroup DBusSignatureInternals
    417  * Unit test for DBusSignature.
    418  *
    419  * @returns #TRUE on success.
    420  */
    421 dbus_bool_t
    422 _dbus_signature_test (void)
    423 {
    424   DBusSignatureIter iter;
    425   DBusSignatureIter subiter;
    426   DBusSignatureIter subsubiter;
    427   DBusSignatureIter subsubsubiter;
    428   const char *sig;
    429   dbus_bool_t boolres;
    430 
    431   _dbus_assert (sizeof (DBusSignatureIter) >= sizeof (DBusSignatureRealIter));
    432 
    433   sig = "";
    434   _dbus_assert (dbus_signature_validate (sig, NULL));
    435   _dbus_assert (!dbus_signature_validate_single (sig, NULL));
    436   dbus_signature_iter_init (&iter, sig);
    437   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_INVALID);
    438 
    439   sig = DBUS_TYPE_STRING_AS_STRING;
    440   _dbus_assert (dbus_signature_validate (sig, NULL));
    441   _dbus_assert (dbus_signature_validate_single (sig, NULL));
    442   dbus_signature_iter_init (&iter, sig);
    443   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRING);
    444 
    445   sig = DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_BYTE_AS_STRING;
    446   _dbus_assert (dbus_signature_validate (sig, NULL));
    447   dbus_signature_iter_init (&iter, sig);
    448   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRING);
    449   boolres = dbus_signature_iter_next (&iter);
    450   _dbus_assert (boolres);
    451   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_BYTE);
    452 
    453   sig = DBUS_TYPE_UINT16_AS_STRING
    454     DBUS_STRUCT_BEGIN_CHAR_AS_STRING
    455     DBUS_TYPE_STRING_AS_STRING
    456     DBUS_TYPE_UINT32_AS_STRING
    457     DBUS_TYPE_VARIANT_AS_STRING
    458     DBUS_TYPE_DOUBLE_AS_STRING
    459     DBUS_STRUCT_END_CHAR_AS_STRING;
    460   _dbus_assert (dbus_signature_validate (sig, NULL));
    461   dbus_signature_iter_init (&iter, sig);
    462   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_UINT16);
    463   boolres = dbus_signature_iter_next (&iter);
    464   _dbus_assert (boolres);
    465   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRUCT);
    466   dbus_signature_iter_recurse (&iter, &subiter);
    467   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_STRING);
    468   boolres = dbus_signature_iter_next (&subiter);
    469   _dbus_assert (boolres);
    470   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_UINT32);
    471   boolres = dbus_signature_iter_next (&subiter);
    472   _dbus_assert (boolres);
    473   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_VARIANT);
    474   boolres = dbus_signature_iter_next (&subiter);
    475   _dbus_assert (boolres);
    476   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_DOUBLE);
    477 
    478   sig = DBUS_TYPE_UINT16_AS_STRING
    479     DBUS_STRUCT_BEGIN_CHAR_AS_STRING
    480     DBUS_TYPE_UINT32_AS_STRING
    481     DBUS_TYPE_BYTE_AS_STRING
    482     DBUS_TYPE_ARRAY_AS_STRING
    483     DBUS_TYPE_ARRAY_AS_STRING
    484     DBUS_TYPE_DOUBLE_AS_STRING
    485     DBUS_STRUCT_BEGIN_CHAR_AS_STRING
    486     DBUS_TYPE_BYTE_AS_STRING
    487     DBUS_STRUCT_END_CHAR_AS_STRING
    488     DBUS_STRUCT_END_CHAR_AS_STRING;
    489   _dbus_assert (dbus_signature_validate (sig, NULL));
    490   dbus_signature_iter_init (&iter, sig);
    491   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_UINT16);
    492   boolres = dbus_signature_iter_next (&iter);
    493   _dbus_assert (boolres);
    494   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRUCT);
    495   dbus_signature_iter_recurse (&iter, &subiter);
    496   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_UINT32);
    497   boolres = dbus_signature_iter_next (&subiter);
    498   _dbus_assert (boolres);
    499   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_BYTE);
    500   boolres = dbus_signature_iter_next (&subiter);
    501   _dbus_assert (boolres);
    502   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_ARRAY);
    503   _dbus_assert (dbus_signature_iter_get_element_type (&subiter) == DBUS_TYPE_ARRAY);
    504 
    505   dbus_signature_iter_recurse (&subiter, &subsubiter);
    506   _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_ARRAY);
    507   _dbus_assert (dbus_signature_iter_get_element_type (&subsubiter) == DBUS_TYPE_DOUBLE);
    508 
    509   dbus_signature_iter_recurse (&subsubiter, &subsubsubiter);
    510   _dbus_assert (dbus_signature_iter_get_current_type (&subsubsubiter) == DBUS_TYPE_DOUBLE);
    511   boolres = dbus_signature_iter_next (&subiter);
    512   _dbus_assert (boolres);
    513   _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_STRUCT);
    514   dbus_signature_iter_recurse (&subiter, &subsubiter);
    515   _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_BYTE);
    516 
    517   sig = DBUS_TYPE_ARRAY_AS_STRING
    518     DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
    519     DBUS_TYPE_INT16_AS_STRING
    520     DBUS_TYPE_STRING_AS_STRING
    521     DBUS_DICT_ENTRY_END_CHAR_AS_STRING
    522     DBUS_TYPE_VARIANT_AS_STRING;
    523   _dbus_assert (dbus_signature_validate (sig, NULL));
    524   _dbus_assert (!dbus_signature_validate_single (sig, NULL));
    525   dbus_signature_iter_init (&iter, sig);
    526   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_ARRAY);
    527   _dbus_assert (dbus_signature_iter_get_element_type (&iter) == DBUS_TYPE_DICT_ENTRY);
    528 
    529   dbus_signature_iter_recurse (&iter, &subiter);
    530   dbus_signature_iter_recurse (&subiter, &subsubiter);
    531   _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_INT16);
    532   boolres = dbus_signature_iter_next (&subsubiter);
    533   _dbus_assert (boolres);
    534   _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_STRING);
    535   boolres = dbus_signature_iter_next (&subsubiter);
    536   _dbus_assert (!boolres);
    537 
    538   boolres = dbus_signature_iter_next (&iter);
    539   _dbus_assert (boolres);
    540   _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_VARIANT);
    541   boolres = dbus_signature_iter_next (&iter);
    542   _dbus_assert (!boolres);
    543 
    544   sig = DBUS_TYPE_DICT_ENTRY_AS_STRING;
    545   _dbus_assert (!dbus_signature_validate (sig, NULL));
    546 
    547   sig = DBUS_TYPE_ARRAY_AS_STRING;
    548   _dbus_assert (!dbus_signature_validate (sig, NULL));
    549 
    550   sig = DBUS_TYPE_UINT32_AS_STRING
    551     DBUS_TYPE_ARRAY_AS_STRING;
    552   _dbus_assert (!dbus_signature_validate (sig, NULL));
    553 
    554   sig = DBUS_TYPE_ARRAY_AS_STRING
    555     DBUS_TYPE_DICT_ENTRY_AS_STRING;
    556   _dbus_assert (!dbus_signature_validate (sig, NULL));
    557 
    558   sig = DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING;
    559   _dbus_assert (!dbus_signature_validate (sig, NULL));
    560 
    561   sig = DBUS_DICT_ENTRY_END_CHAR_AS_STRING;
    562   _dbus_assert (!dbus_signature_validate (sig, NULL));
    563 
    564   sig = DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
    565     DBUS_TYPE_INT32_AS_STRING;
    566   _dbus_assert (!dbus_signature_validate (sig, NULL));
    567 
    568   sig = DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
    569     DBUS_TYPE_INT32_AS_STRING
    570     DBUS_TYPE_STRING_AS_STRING;
    571   _dbus_assert (!dbus_signature_validate (sig, NULL));
    572 
    573   sig = DBUS_STRUCT_END_CHAR_AS_STRING
    574     DBUS_STRUCT_BEGIN_CHAR_AS_STRING;
    575   _dbus_assert (!dbus_signature_validate (sig, NULL));
    576 
    577   sig = DBUS_STRUCT_BEGIN_CHAR_AS_STRING
    578     DBUS_TYPE_BOOLEAN_AS_STRING;
    579   _dbus_assert (!dbus_signature_validate (sig, NULL));
    580   return TRUE;
    581 #if 0
    582  oom:
    583   _dbus_assert_not_reached ("out of memory");
    584   return FALSE;
    585 #endif
    586 }
    587 
    588 #endif
    589 
    590