Home | History | Annotate | Download | only in dbus
      1 /* -*- mode: C; c-file-style: "gnu" -*- */
      2 /* dbus-marshal-header.c  Managing marshaling/demarshaling of message headers
      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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     21  *
     22  */
     23 
     24 #include "dbus/dbus-shared.h"
     25 #include "dbus-marshal-header.h"
     26 #include "dbus-marshal-recursive.h"
     27 #include "dbus-marshal-byteswap.h"
     28 
     29 /**
     30  * @addtogroup DBusMarshal
     31  *
     32  * @{
     33  */
     34 
     35 
     36 /* Not thread locked, but strictly const/read-only so should be OK
     37  */
     38 /** Static #DBusString containing the signature of a message header */
     39 _DBUS_STRING_DEFINE_STATIC(_dbus_header_signature_str, DBUS_HEADER_SIGNATURE);
     40 /** Static #DBusString containing the local interface */
     41 _DBUS_STRING_DEFINE_STATIC(_dbus_local_interface_str,  DBUS_INTERFACE_LOCAL);
     42 /** Static #DBusString containing the local path */
     43 _DBUS_STRING_DEFINE_STATIC(_dbus_local_path_str,       DBUS_PATH_LOCAL);
     44 
     45 /** Offset from start of _dbus_header_signature_str to the signature of the fields array */
     46 #define FIELDS_ARRAY_SIGNATURE_OFFSET 6
     47 /** Offset from start of _dbus_header_signature_str to the signature of an element of the fields array */
     48 #define FIELDS_ARRAY_ELEMENT_SIGNATURE_OFFSET 7
     49 
     50 
     51 /** Offset to byte order from start of header */
     52 #define BYTE_ORDER_OFFSET    0
     53 /** Offset to type from start of header */
     54 #define TYPE_OFFSET          1
     55 /** Offset to flags from start of header */
     56 #define FLAGS_OFFSET         2
     57 /** Offset to version from start of header */
     58 #define VERSION_OFFSET       3
     59 /** Offset to body length from start of header */
     60 #define BODY_LENGTH_OFFSET 4
     61 /** Offset to client serial from start of header */
     62 #define SERIAL_OFFSET 8
     63 /** Offset to fields array length from start of header */
     64 #define FIELDS_ARRAY_LENGTH_OFFSET 12
     65 /** Offset to first field in header */
     66 #define FIRST_FIELD_OFFSET 16
     67 
     68 typedef struct
     69 {
     70   unsigned char code; /**< the field code */
     71   unsigned char type; /**< the value type */
     72 } HeaderFieldType;
     73 
     74 static const HeaderFieldType
     75 _dbus_header_field_types[DBUS_HEADER_FIELD_LAST+1] = {
     76   { DBUS_HEADER_FIELD_INVALID, DBUS_TYPE_INVALID },
     77   { DBUS_HEADER_FIELD_PATH, DBUS_TYPE_OBJECT_PATH },
     78   { DBUS_HEADER_FIELD_INTERFACE, DBUS_TYPE_STRING },
     79   { DBUS_HEADER_FIELD_MEMBER, DBUS_TYPE_STRING },
     80   { DBUS_HEADER_FIELD_ERROR_NAME, DBUS_TYPE_STRING },
     81   { DBUS_HEADER_FIELD_REPLY_SERIAL, DBUS_TYPE_UINT32 },
     82   { DBUS_HEADER_FIELD_DESTINATION, DBUS_TYPE_STRING },
     83   { DBUS_HEADER_FIELD_SENDER, DBUS_TYPE_STRING },
     84   { DBUS_HEADER_FIELD_SIGNATURE, DBUS_TYPE_SIGNATURE }
     85 };
     86 
     87 /** Macro to look up the correct type for a field */
     88 #define EXPECTED_TYPE_OF_FIELD(field) (_dbus_header_field_types[field].type)
     89 
     90 /** The most padding we could ever need for a header */
     91 #define MAX_POSSIBLE_HEADER_PADDING 7
     92 static dbus_bool_t
     93 reserve_header_padding (DBusHeader *header)
     94 {
     95   _dbus_assert (header->padding <= MAX_POSSIBLE_HEADER_PADDING);
     96 
     97   if (!_dbus_string_lengthen (&header->data,
     98                               MAX_POSSIBLE_HEADER_PADDING - header->padding))
     99     return FALSE;
    100   header->padding = MAX_POSSIBLE_HEADER_PADDING;
    101   return TRUE;
    102 }
    103 
    104 static void
    105 correct_header_padding (DBusHeader *header)
    106 {
    107   int unpadded_len;
    108 
    109   _dbus_assert (header->padding == 7);
    110 
    111   _dbus_string_shorten (&header->data, header->padding);
    112   unpadded_len = _dbus_string_get_length (&header->data);
    113 
    114   if (!_dbus_string_align_length (&header->data, 8))
    115     _dbus_assert_not_reached ("couldn't pad header though enough padding was preallocated");
    116 
    117   header->padding = _dbus_string_get_length (&header->data) - unpadded_len;
    118 }
    119 
    120 /** Compute the end of the header, ignoring padding */
    121 #define HEADER_END_BEFORE_PADDING(header) \
    122   (_dbus_string_get_length (&(header)->data) - (header)->padding)
    123 
    124 /**
    125  * Invalidates all fields in the cache. This may be used when the
    126  * cache is totally uninitialized (contains junk) so should not
    127  * look at what's in there now.
    128  *
    129  * @param header the header
    130  */
    131 static void
    132 _dbus_header_cache_invalidate_all (DBusHeader *header)
    133 {
    134   int i;
    135 
    136   i = 0;
    137   while (i <= DBUS_HEADER_FIELD_LAST)
    138     {
    139       header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_UNKNOWN;
    140       ++i;
    141     }
    142 }
    143 
    144 /**
    145  * Caches one field
    146  *
    147  * @param header the header
    148  * @param field_code the field
    149  * @param variant_reader the reader for the variant in the field
    150  */
    151 static void
    152 _dbus_header_cache_one (DBusHeader     *header,
    153                         int             field_code,
    154                         DBusTypeReader *variant_reader)
    155 {
    156   header->fields[field_code].value_pos =
    157     _dbus_type_reader_get_value_pos (variant_reader);
    158 
    159 #if 0
    160   _dbus_verbose ("cached value_pos %d for field %d\n",
    161                  header->fields[field_code].value_pos, field_code)
    162 #endif
    163 }
    164 
    165 /**
    166  * Revalidates the fields cache
    167  *
    168  * @param header the header
    169  */
    170 static void
    171 _dbus_header_cache_revalidate (DBusHeader *header)
    172 {
    173   DBusTypeReader array;
    174   DBusTypeReader reader;
    175   int i;
    176 
    177   i = 0;
    178   while (i <= DBUS_HEADER_FIELD_LAST)
    179     {
    180       header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_NONEXISTENT;
    181       ++i;
    182     }
    183 
    184   _dbus_type_reader_init (&reader,
    185                           header->byte_order,
    186                           &_dbus_header_signature_str,
    187                           FIELDS_ARRAY_SIGNATURE_OFFSET,
    188                           &header->data,
    189                           FIELDS_ARRAY_LENGTH_OFFSET);
    190 
    191   _dbus_type_reader_recurse (&reader, &array);
    192 
    193   while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
    194     {
    195       DBusTypeReader sub;
    196       DBusTypeReader variant;
    197       unsigned char field_code;
    198 
    199       _dbus_type_reader_recurse (&array, &sub);
    200 
    201       _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_BYTE);
    202       _dbus_type_reader_read_basic (&sub, &field_code);
    203 
    204       /* Unknown fields should be ignored */
    205       if (field_code > DBUS_HEADER_FIELD_LAST)
    206         goto next_field;
    207 
    208       _dbus_type_reader_next (&sub);
    209 
    210       _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_VARIANT);
    211       _dbus_type_reader_recurse (&sub, &variant);
    212 
    213       _dbus_header_cache_one (header, field_code, &variant);
    214 
    215     next_field:
    216       _dbus_type_reader_next (&array);
    217     }
    218 }
    219 
    220 /**
    221  * Checks for a field, updating the cache if required.
    222  *
    223  * @param header the header
    224  * @param field the field to check
    225  * @returns #FALSE if the field doesn't exist
    226  */
    227 static dbus_bool_t
    228 _dbus_header_cache_check (DBusHeader    *header,
    229                           int            field)
    230 {
    231   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
    232 
    233   if (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_UNKNOWN)
    234     _dbus_header_cache_revalidate (header);
    235 
    236   if (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_NONEXISTENT)
    237     return FALSE;
    238 
    239   return TRUE;
    240 }
    241 
    242 /**
    243  * Checks whether a field is known not to exist. It may exist
    244  * even if it's not known to exist.
    245  *
    246  * @param header the header
    247  * @param field the field to check
    248  * @returns #FALSE if the field definitely doesn't exist
    249  */
    250 static dbus_bool_t
    251 _dbus_header_cache_known_nonexistent (DBusHeader    *header,
    252                                       int            field)
    253 {
    254   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
    255 
    256   return (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_NONEXISTENT);
    257 }
    258 
    259 /**
    260  * Writes a struct of { byte, variant } with the given basic type.
    261  *
    262  * @param writer the writer (should be ready to write a struct)
    263  * @param type the type of the value
    264  * @param value the value as for _dbus_marshal_set_basic()
    265  * @returns #FALSE if no memory
    266  */
    267 static dbus_bool_t
    268 write_basic_field (DBusTypeWriter *writer,
    269                    int             field,
    270                    int             type,
    271                    const void     *value)
    272 {
    273   DBusTypeWriter sub;
    274   DBusTypeWriter variant;
    275   int start;
    276   int padding;
    277   unsigned char field_byte;
    278   DBusString contained_type;
    279   char buf[2];
    280 
    281   start = writer->value_pos;
    282   padding = _dbus_string_get_length (writer->value_str) - start;
    283 
    284   if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_STRUCT,
    285                                   NULL, 0, &sub))
    286     goto append_failed;
    287 
    288   field_byte = field;
    289   if (!_dbus_type_writer_write_basic (&sub, DBUS_TYPE_BYTE,
    290                                       &field_byte))
    291     goto append_failed;
    292 
    293   buf[0] = type;
    294   buf[1] = '\0';
    295   _dbus_string_init_const_len (&contained_type, buf, 1);
    296 
    297   if (!_dbus_type_writer_recurse (&sub, DBUS_TYPE_VARIANT,
    298                                   &contained_type, 0, &variant))
    299     goto append_failed;
    300 
    301   if (!_dbus_type_writer_write_basic (&variant, type, value))
    302     goto append_failed;
    303 
    304   if (!_dbus_type_writer_unrecurse (&sub, &variant))
    305     goto append_failed;
    306 
    307   if (!_dbus_type_writer_unrecurse (writer, &sub))
    308     goto append_failed;
    309 
    310   return TRUE;
    311 
    312  append_failed:
    313   _dbus_string_delete (writer->value_str,
    314                        start,
    315                        _dbus_string_get_length (writer->value_str) - start - padding);
    316   return FALSE;
    317 }
    318 
    319 /**
    320  * Sets a struct of { byte, variant } with the given basic type.
    321  *
    322  * @param reader the reader (should be iterating over the array pointing at the field to set)
    323  * @param type the type of the value
    324  * @param value the value as for _dbus_marshal_set_basic()
    325  * @param realign_root where to realign from
    326  * @returns #FALSE if no memory
    327  */
    328 static dbus_bool_t
    329 set_basic_field (DBusTypeReader       *reader,
    330                  int                   field,
    331                  int                   type,
    332                  const void           *value,
    333                  const DBusTypeReader *realign_root)
    334 {
    335   DBusTypeReader sub;
    336   DBusTypeReader variant;
    337 
    338   _dbus_type_reader_recurse (reader, &sub);
    339 
    340   _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_BYTE);
    341 #ifndef DBUS_DISABLE_ASSERT
    342  {
    343    unsigned char v_BYTE;
    344    _dbus_type_reader_read_basic (&sub, &v_BYTE);
    345    _dbus_assert (((int) v_BYTE) == field);
    346  }
    347 #endif
    348 
    349   if (!_dbus_type_reader_next (&sub))
    350     _dbus_assert_not_reached ("no variant field?");
    351 
    352   _dbus_type_reader_recurse (&sub, &variant);
    353   _dbus_assert (_dbus_type_reader_get_current_type (&variant) == type);
    354 
    355   if (!_dbus_type_reader_set_basic (&variant, value, realign_root))
    356     return FALSE;
    357 
    358   return TRUE;
    359 }
    360 
    361 /**
    362  * Gets the type of the message.
    363  *
    364  * @param header the header
    365  * @returns the type
    366  */
    367 int
    368 _dbus_header_get_message_type (DBusHeader *header)
    369 {
    370   int type;
    371 
    372   type = _dbus_string_get_byte (&header->data, TYPE_OFFSET);
    373   _dbus_assert (type != DBUS_MESSAGE_TYPE_INVALID);
    374 
    375   return type;
    376 }
    377 
    378 /**
    379  * Sets the serial number of a header.  This can only be done once on
    380  * a header.
    381  *
    382  * @param header the header
    383  * @param serial the serial
    384  */
    385 void
    386 _dbus_header_set_serial (DBusHeader    *header,
    387                          dbus_uint32_t  serial)
    388 {
    389   /* we use this function to set the serial on outgoing
    390    * messages, and to reset the serial in dbus_message_copy;
    391    * this assertion should catch a double-set on outgoing.
    392    */
    393   _dbus_assert (_dbus_header_get_serial (header) == 0 ||
    394                 serial == 0);
    395 
    396   _dbus_marshal_set_uint32 (&header->data,
    397                             SERIAL_OFFSET,
    398 			    serial,
    399                             header->byte_order);
    400 }
    401 
    402 /**
    403  * See dbus_message_get_serial()
    404  *
    405  * @param header the header
    406  * @returns the client serial
    407  */
    408 dbus_uint32_t
    409 _dbus_header_get_serial (DBusHeader *header)
    410 {
    411   return _dbus_marshal_read_uint32 (&header->data,
    412                                     SERIAL_OFFSET,
    413                                     header->byte_order,
    414                                     NULL);
    415 }
    416 
    417 /**
    418  * Re-initializes a header that was previously initialized and never
    419  * freed.  After this, to make the header valid you have to call
    420  * _dbus_header_create().
    421  *
    422  * @param header header to re-initialize
    423  * @param byte_order byte order of the header
    424  */
    425 void
    426 _dbus_header_reinit (DBusHeader *header,
    427                      int         byte_order)
    428 {
    429   _dbus_string_set_length (&header->data, 0);
    430 
    431   header->byte_order = byte_order;
    432   header->padding = 0;
    433 
    434   _dbus_header_cache_invalidate_all (header);
    435 }
    436 
    437 /**
    438  * Initializes a header, but doesn't prepare it for use;
    439  * to make the header valid, you have to call _dbus_header_create().
    440  *
    441  * @param header header to initialize
    442  * @param byte_order byte order of the header
    443  * @returns #FALSE if not enough memory
    444  */
    445 dbus_bool_t
    446 _dbus_header_init (DBusHeader *header,
    447                    int         byte_order)
    448 {
    449   if (!_dbus_string_init_preallocated (&header->data, 32))
    450     return FALSE;
    451 
    452   _dbus_header_reinit (header, byte_order);
    453 
    454   return TRUE;
    455 }
    456 
    457 /**
    458  * Frees a header.
    459  *
    460  * @param header the header
    461  */
    462 void
    463 _dbus_header_free (DBusHeader *header)
    464 {
    465   _dbus_string_free (&header->data);
    466 }
    467 
    468 /**
    469  * Initializes dest with a copy of the given header.
    470  * Resets the message serial to 0 on the copy.
    471  *
    472  * @param header header to copy
    473  * @param dest destination for copy
    474  * @returns #FALSE if not enough memory
    475  */
    476 dbus_bool_t
    477 _dbus_header_copy (const DBusHeader *header,
    478                    DBusHeader       *dest)
    479 {
    480   *dest = *header;
    481 
    482   if (!_dbus_string_init_preallocated (&dest->data,
    483                                        _dbus_string_get_length (&header->data)))
    484     return FALSE;
    485 
    486   if (!_dbus_string_copy (&header->data, 0, &dest->data, 0))
    487     {
    488       _dbus_string_free (&dest->data);
    489       return FALSE;
    490     }
    491 
    492   /* Reset the serial */
    493   _dbus_header_set_serial (dest, 0);
    494 
    495   return TRUE;
    496 }
    497 
    498 /**
    499  * Fills in the primary fields of the header, so the header is ready
    500  * for use. #NULL may be specified for some or all of the fields to
    501  * avoid adding those fields. Some combinations of fields don't make
    502  * sense, and passing them in will trigger an assertion failure.
    503  *
    504  * @param header the header
    505  * @param message_type the message type
    506  * @param destination destination field or #NULL
    507  * @param path path field or #NULL
    508  * @param interface interface field or #NULL
    509  * @param member member field or #NULL
    510  * @param error_name error name or #NULL
    511  * @returns #FALSE if not enough memory
    512  */
    513 dbus_bool_t
    514 _dbus_header_create (DBusHeader  *header,
    515                      int          message_type,
    516                      const char  *destination,
    517                      const char  *path,
    518                      const char  *interface,
    519                      const char  *member,
    520                      const char  *error_name)
    521 {
    522   unsigned char v_BYTE;
    523   dbus_uint32_t v_UINT32;
    524   DBusTypeWriter writer;
    525   DBusTypeWriter array;
    526 
    527   _dbus_assert (((interface || message_type != DBUS_MESSAGE_TYPE_SIGNAL) && member) ||
    528                 (error_name) ||
    529                 !(interface || member || error_name));
    530   _dbus_assert (_dbus_string_get_length (&header->data) == 0);
    531 
    532   if (!reserve_header_padding (header))
    533     return FALSE;
    534 
    535   _dbus_type_writer_init_values_only (&writer, header->byte_order,
    536                                       &_dbus_header_signature_str, 0,
    537                                       &header->data,
    538                                       HEADER_END_BEFORE_PADDING (header));
    539 
    540   v_BYTE = header->byte_order;
    541   if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
    542                                       &v_BYTE))
    543     goto oom;
    544 
    545   v_BYTE = message_type;
    546   if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
    547                                       &v_BYTE))
    548     goto oom;
    549 
    550   v_BYTE = 0; /* flags */
    551   if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
    552                                       &v_BYTE))
    553     goto oom;
    554 
    555   v_BYTE = DBUS_MAJOR_PROTOCOL_VERSION;
    556   if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
    557                                       &v_BYTE))
    558     goto oom;
    559 
    560   v_UINT32 = 0; /* body length */
    561   if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_UINT32,
    562                                       &v_UINT32))
    563     goto oom;
    564 
    565   v_UINT32 = 0; /* serial */
    566   if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_UINT32,
    567                                       &v_UINT32))
    568     goto oom;
    569 
    570   if (!_dbus_type_writer_recurse (&writer, DBUS_TYPE_ARRAY,
    571                                   &_dbus_header_signature_str,
    572                                   FIELDS_ARRAY_SIGNATURE_OFFSET,
    573                                   &array))
    574     goto oom;
    575 
    576   /* Marshal all the fields (Marshall Fields?) */
    577 
    578   if (path != NULL)
    579     {
    580       if (!write_basic_field (&array,
    581                               DBUS_HEADER_FIELD_PATH,
    582                               DBUS_TYPE_OBJECT_PATH,
    583                               &path))
    584         goto oom;
    585     }
    586 
    587   if (destination != NULL)
    588     {
    589       if (!write_basic_field (&array,
    590                               DBUS_HEADER_FIELD_DESTINATION,
    591                               DBUS_TYPE_STRING,
    592                               &destination))
    593         goto oom;
    594     }
    595 
    596   if (interface != NULL)
    597     {
    598       if (!write_basic_field (&array,
    599                               DBUS_HEADER_FIELD_INTERFACE,
    600                               DBUS_TYPE_STRING,
    601                               &interface))
    602         goto oom;
    603     }
    604 
    605   if (member != NULL)
    606     {
    607       if (!write_basic_field (&array,
    608                               DBUS_HEADER_FIELD_MEMBER,
    609                               DBUS_TYPE_STRING,
    610                               &member))
    611         goto oom;
    612     }
    613 
    614   if (error_name != NULL)
    615     {
    616       if (!write_basic_field (&array,
    617                               DBUS_HEADER_FIELD_ERROR_NAME,
    618                               DBUS_TYPE_STRING,
    619                               &error_name))
    620         goto oom;
    621     }
    622 
    623   if (!_dbus_type_writer_unrecurse (&writer, &array))
    624     goto oom;
    625 
    626   correct_header_padding (header);
    627 
    628   return TRUE;
    629 
    630  oom:
    631   _dbus_string_delete (&header->data, 0,
    632                        _dbus_string_get_length (&header->data) - header->padding);
    633   correct_header_padding (header);
    634 
    635   return FALSE;
    636 }
    637 
    638 /**
    639  * Given data long enough to contain the length of the message body
    640  * and the fields array, check whether the data is long enough to
    641  * contain the entire message (assuming the claimed lengths are
    642  * accurate). Also checks that the lengths are in sanity parameters.
    643  *
    644  * @param max_message_length maximum length of a valid message
    645  * @param validity return location for why the data is invalid if it is
    646  * @param byte_order return location for byte order
    647  * @param fields_array_len return location for claimed fields array length
    648  * @param header_len return location for claimed header length
    649  * @param body_len return location for claimed body length
    650  * @param str the data
    651  * @param start start of data, 8-aligned
    652  * @param len length of data
    653  * @returns #TRUE if the data is long enough for the claimed length, and the lengths were valid
    654  */
    655 dbus_bool_t
    656 _dbus_header_have_message_untrusted (int                max_message_length,
    657                                      DBusValidity      *validity,
    658                                      int               *byte_order,
    659                                      int               *fields_array_len,
    660                                      int               *header_len,
    661                                      int               *body_len,
    662                                      const DBusString  *str,
    663                                      int                start,
    664                                      int                len)
    665 
    666 {
    667   dbus_uint32_t header_len_unsigned;
    668   dbus_uint32_t fields_array_len_unsigned;
    669   dbus_uint32_t body_len_unsigned;
    670 
    671   _dbus_assert (start >= 0);
    672   _dbus_assert (start < _DBUS_INT32_MAX / 2);
    673   _dbus_assert (len >= 0);
    674 
    675   _dbus_assert (start == (int) _DBUS_ALIGN_VALUE (start, 8));
    676 
    677   *byte_order = _dbus_string_get_byte (str, start + BYTE_ORDER_OFFSET);
    678 
    679   if (*byte_order != DBUS_LITTLE_ENDIAN && *byte_order != DBUS_BIG_ENDIAN)
    680     {
    681       *validity = DBUS_INVALID_BAD_BYTE_ORDER;
    682       return FALSE;
    683     }
    684 
    685   _dbus_assert (FIELDS_ARRAY_LENGTH_OFFSET + 4 <= len);
    686   fields_array_len_unsigned = _dbus_marshal_read_uint32 (str, start + FIELDS_ARRAY_LENGTH_OFFSET,
    687                                                          *byte_order, NULL);
    688 
    689   if (fields_array_len_unsigned > (unsigned) max_message_length)
    690     {
    691       *validity = DBUS_INVALID_INSANE_FIELDS_ARRAY_LENGTH;
    692       return FALSE;
    693     }
    694 
    695   _dbus_assert (BODY_LENGTH_OFFSET + 4 < len);
    696   body_len_unsigned = _dbus_marshal_read_uint32 (str, start + BODY_LENGTH_OFFSET,
    697                                                  *byte_order, NULL);
    698 
    699   if (body_len_unsigned > (unsigned) max_message_length)
    700     {
    701       *validity = DBUS_INVALID_INSANE_BODY_LENGTH;
    702       return FALSE;
    703     }
    704 
    705   header_len_unsigned = FIRST_FIELD_OFFSET + fields_array_len_unsigned;
    706   header_len_unsigned = _DBUS_ALIGN_VALUE (header_len_unsigned, 8);
    707 
    708   /* overflow should be impossible since the lengths aren't allowed to
    709    * be huge.
    710    */
    711   _dbus_assert (max_message_length < _DBUS_INT32_MAX / 2);
    712   if (body_len_unsigned + header_len_unsigned > (unsigned) max_message_length)
    713     {
    714       *validity = DBUS_INVALID_MESSAGE_TOO_LONG;
    715       return FALSE;
    716     }
    717 
    718   _dbus_assert (body_len_unsigned < (unsigned) _DBUS_INT32_MAX);
    719   _dbus_assert (fields_array_len_unsigned < (unsigned) _DBUS_INT32_MAX);
    720   _dbus_assert (header_len_unsigned < (unsigned) _DBUS_INT32_MAX);
    721 
    722   *body_len = body_len_unsigned;
    723   *fields_array_len = fields_array_len_unsigned;
    724   *header_len = header_len_unsigned;
    725 
    726   *validity = DBUS_VALID;
    727 
    728   _dbus_verbose ("have %d bytes, need body %u + header %u = %u\n",
    729                  len, body_len_unsigned, header_len_unsigned,
    730                  body_len_unsigned + header_len_unsigned);
    731 
    732   return (body_len_unsigned + header_len_unsigned) <= (unsigned) len;
    733 }
    734 
    735 static DBusValidity
    736 check_mandatory_fields (DBusHeader *header)
    737 {
    738 #define REQUIRE_FIELD(name) do { if (header->fields[DBUS_HEADER_FIELD_##name].value_pos < 0) return DBUS_INVALID_MISSING_##name; } while (0)
    739 
    740   switch (_dbus_header_get_message_type (header))
    741     {
    742     case DBUS_MESSAGE_TYPE_SIGNAL:
    743       REQUIRE_FIELD (INTERFACE);
    744       /* FALL THRU - signals also require the path and member */
    745     case DBUS_MESSAGE_TYPE_METHOD_CALL:
    746       REQUIRE_FIELD (PATH);
    747       REQUIRE_FIELD (MEMBER);
    748       break;
    749     case DBUS_MESSAGE_TYPE_ERROR:
    750       REQUIRE_FIELD (ERROR_NAME);
    751       REQUIRE_FIELD (REPLY_SERIAL);
    752       break;
    753     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
    754       REQUIRE_FIELD (REPLY_SERIAL);
    755       break;
    756     default:
    757       /* other message types allowed but ignored */
    758       break;
    759     }
    760 
    761   return DBUS_VALID;
    762 }
    763 
    764 static DBusValidity
    765 load_and_validate_field (DBusHeader     *header,
    766                          int             field,
    767                          DBusTypeReader *variant_reader)
    768 {
    769   int type;
    770   int expected_type;
    771   const DBusString *value_str;
    772   int value_pos;
    773   int str_data_pos;
    774   dbus_uint32_t v_UINT32;
    775   int bad_string_code;
    776   dbus_bool_t (* string_validation_func) (const DBusString *str,
    777                                           int start, int len);
    778 
    779   /* Supposed to have been checked already */
    780   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
    781   _dbus_assert (field != DBUS_HEADER_FIELD_INVALID);
    782 
    783   /* Before we can cache a field, we need to know it has the right type */
    784   type = _dbus_type_reader_get_current_type (variant_reader);
    785 
    786   _dbus_assert (_dbus_header_field_types[field].code == field);
    787 
    788   expected_type = EXPECTED_TYPE_OF_FIELD (field);
    789   if (type != expected_type)
    790     {
    791       _dbus_verbose ("Field %d should have type %d but has %d\n",
    792                      field, expected_type, type);
    793       return DBUS_INVALID_HEADER_FIELD_HAS_WRONG_TYPE;
    794     }
    795 
    796   /* If the field was provided twice, we aren't happy */
    797   if (header->fields[field].value_pos >= 0)
    798     {
    799       _dbus_verbose ("Header field %d seen a second time\n", field);
    800       return DBUS_INVALID_HEADER_FIELD_APPEARS_TWICE;
    801     }
    802 
    803   /* Now we can cache and look at the field content */
    804   _dbus_verbose ("initially caching field %d\n", field);
    805   _dbus_header_cache_one (header, field, variant_reader);
    806 
    807   string_validation_func = NULL;
    808 
    809   /* make compiler happy that all this is initialized */
    810   v_UINT32 = 0;
    811   value_str = NULL;
    812   value_pos = -1;
    813   str_data_pos = -1;
    814   bad_string_code = DBUS_VALID;
    815 
    816   if (expected_type == DBUS_TYPE_UINT32)
    817     {
    818       _dbus_header_get_field_basic (header, field, expected_type,
    819                                     &v_UINT32);
    820     }
    821   else if (expected_type == DBUS_TYPE_STRING ||
    822            expected_type == DBUS_TYPE_OBJECT_PATH ||
    823            expected_type == DBUS_TYPE_SIGNATURE)
    824     {
    825       _dbus_header_get_field_raw (header, field,
    826                                   &value_str, &value_pos);
    827       str_data_pos = _DBUS_ALIGN_VALUE (value_pos, 4) + 4;
    828     }
    829   else
    830     {
    831       _dbus_assert_not_reached ("none of the known fields should have this type");
    832     }
    833 
    834   switch (field)
    835     {
    836     case DBUS_HEADER_FIELD_DESTINATION:
    837       string_validation_func = _dbus_validate_bus_name;
    838       bad_string_code = DBUS_INVALID_BAD_DESTINATION;
    839       break;
    840     case DBUS_HEADER_FIELD_INTERFACE:
    841       string_validation_func = _dbus_validate_interface;
    842       bad_string_code = DBUS_INVALID_BAD_INTERFACE;
    843 
    844       if (_dbus_string_equal_substring (&_dbus_local_interface_str,
    845                                         0,
    846                                         _dbus_string_get_length (&_dbus_local_interface_str),
    847                                         value_str, str_data_pos))
    848         {
    849           _dbus_verbose ("Message is on the local interface\n");
    850           return DBUS_INVALID_USES_LOCAL_INTERFACE;
    851         }
    852       break;
    853 
    854     case DBUS_HEADER_FIELD_MEMBER:
    855       string_validation_func = _dbus_validate_member;
    856       bad_string_code = DBUS_INVALID_BAD_MEMBER;
    857       break;
    858 
    859     case DBUS_HEADER_FIELD_ERROR_NAME:
    860       string_validation_func = _dbus_validate_error_name;
    861       bad_string_code = DBUS_INVALID_BAD_ERROR_NAME;
    862       break;
    863 
    864     case DBUS_HEADER_FIELD_SENDER:
    865       string_validation_func = _dbus_validate_bus_name;
    866       bad_string_code = DBUS_INVALID_BAD_SENDER;
    867       break;
    868 
    869     case DBUS_HEADER_FIELD_PATH:
    870       /* OBJECT_PATH was validated generically due to its type */
    871       string_validation_func = NULL;
    872 
    873       if (_dbus_string_equal_substring (&_dbus_local_path_str,
    874                                         0,
    875                                         _dbus_string_get_length (&_dbus_local_path_str),
    876                                         value_str, str_data_pos))
    877         {
    878           _dbus_verbose ("Message is from the local path\n");
    879           return DBUS_INVALID_USES_LOCAL_PATH;
    880         }
    881       break;
    882 
    883     case DBUS_HEADER_FIELD_REPLY_SERIAL:
    884       /* Can't be 0 */
    885       if (v_UINT32 == 0)
    886         {
    887           return DBUS_INVALID_BAD_SERIAL;
    888         }
    889       break;
    890 
    891     case DBUS_HEADER_FIELD_SIGNATURE:
    892       /* SIGNATURE validated generically due to its type */
    893       string_validation_func = NULL;
    894       break;
    895 
    896     default:
    897       _dbus_assert_not_reached ("unknown field shouldn't be seen here");
    898       break;
    899     }
    900 
    901   if (string_validation_func)
    902     {
    903       dbus_uint32_t len;
    904 
    905       _dbus_assert (bad_string_code != DBUS_VALID);
    906 
    907       len = _dbus_marshal_read_uint32 (value_str, value_pos,
    908                                        header->byte_order, NULL);
    909 
    910 #if 0
    911       _dbus_verbose ("Validating string header field; code %d if fails\n",
    912                      bad_string_code);
    913 #endif
    914       if (!(*string_validation_func) (value_str, str_data_pos, len))
    915         return bad_string_code;
    916     }
    917 
    918   return DBUS_VALID;
    919 }
    920 
    921 /**
    922  * Creates a message header from potentially-untrusted data. The
    923  * return value is #TRUE if there was enough memory and the data was
    924  * valid. If it returns #TRUE, the header will be created. If it
    925  * returns #FALSE and *validity == #DBUS_VALIDITY_UNKNOWN_OOM_ERROR,
    926  * then there wasn't enough memory.  If it returns #FALSE
    927  * and *validity != #DBUS_VALIDITY_UNKNOWN_OOM_ERROR then the data was
    928  * invalid.
    929  *
    930  * The byte_order, fields_array_len, and body_len args should be from
    931  * _dbus_header_have_message_untrusted(). Validation performed in
    932  * _dbus_header_have_message_untrusted() is assumed to have been
    933  * already done.
    934  *
    935  * @param header the header (must be initialized)
    936  * @param mode whether to do validation
    937  * @param validity return location for invalidity reason
    938  * @param byte_order byte order from header
    939  * @param fields_array_len claimed length of fields array
    940  * @param body_len claimed length of body
    941  * @param header_len claimed length of header
    942  * @param str a string
    943  * @param start start of header, 8-aligned
    944  * @param len length of string to look at
    945  * @returns #FALSE if no memory or data was invalid, #TRUE otherwise
    946  */
    947 dbus_bool_t
    948 _dbus_header_load (DBusHeader        *header,
    949                    DBusValidationMode mode,
    950                    DBusValidity      *validity,
    951                    int                byte_order,
    952                    int                fields_array_len,
    953                    int                header_len,
    954                    int                body_len,
    955                    const DBusString  *str,
    956                    int                start,
    957                    int                len)
    958 {
    959   int leftover;
    960   DBusValidity v;
    961   DBusTypeReader reader;
    962   DBusTypeReader array_reader;
    963   unsigned char v_byte;
    964   dbus_uint32_t v_uint32;
    965   dbus_uint32_t serial;
    966   int padding_start;
    967   int padding_len;
    968   int i;
    969 
    970   _dbus_assert (start == (int) _DBUS_ALIGN_VALUE (start, 8));
    971   _dbus_assert (header_len <= len);
    972   _dbus_assert (_dbus_string_get_length (&header->data) == 0);
    973 
    974   if (!_dbus_string_copy_len (str, start, header_len, &header->data, 0))
    975     {
    976       _dbus_verbose ("Failed to copy buffer into new header\n");
    977       *validity = DBUS_VALIDITY_UNKNOWN_OOM_ERROR;
    978       return FALSE;
    979     }
    980 
    981   if (mode == DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
    982     {
    983       leftover = len - header_len - body_len - start;
    984     }
    985   else
    986     {
    987       v = _dbus_validate_body_with_reason (&_dbus_header_signature_str, 0,
    988                                            byte_order,
    989                                            &leftover,
    990                                            str, start, len);
    991 
    992       if (v != DBUS_VALID)
    993         {
    994           *validity = v;
    995           goto invalid;
    996         }
    997     }
    998 
    999   _dbus_assert (leftover < len);
   1000 
   1001   padding_len = header_len - (FIRST_FIELD_OFFSET + fields_array_len);
   1002   padding_start = start + FIRST_FIELD_OFFSET + fields_array_len;
   1003   _dbus_assert (start + header_len == (int) _DBUS_ALIGN_VALUE (padding_start, 8));
   1004   _dbus_assert (start + header_len == padding_start + padding_len);
   1005 
   1006   if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
   1007     {
   1008       if (!_dbus_string_validate_nul (str, padding_start, padding_len))
   1009         {
   1010           *validity = DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
   1011           goto invalid;
   1012         }
   1013     }
   1014 
   1015   header->padding = padding_len;
   1016 
   1017   if (mode == DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
   1018     {
   1019       *validity = DBUS_VALID;
   1020       return TRUE;
   1021     }
   1022 
   1023   /* We now know the data is well-formed, but we have to check that
   1024    * it's valid.
   1025    */
   1026 
   1027   _dbus_type_reader_init (&reader,
   1028                           byte_order,
   1029                           &_dbus_header_signature_str, 0,
   1030                           str, start);
   1031 
   1032   /* BYTE ORDER */
   1033   _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
   1034   _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == BYTE_ORDER_OFFSET);
   1035   _dbus_type_reader_read_basic (&reader, &v_byte);
   1036   _dbus_type_reader_next (&reader);
   1037 
   1038   _dbus_assert (v_byte == byte_order);
   1039   header->byte_order = byte_order;
   1040 
   1041   /* MESSAGE TYPE */
   1042   _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
   1043   _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == TYPE_OFFSET);
   1044   _dbus_type_reader_read_basic (&reader, &v_byte);
   1045   _dbus_type_reader_next (&reader);
   1046 
   1047   /* unknown message types are supposed to be ignored, so only validation here is
   1048    * that it isn't invalid
   1049    */
   1050   if (v_byte == DBUS_MESSAGE_TYPE_INVALID)
   1051     {
   1052       *validity = DBUS_INVALID_BAD_MESSAGE_TYPE;
   1053       goto invalid;
   1054     }
   1055 
   1056   /* FLAGS */
   1057   _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
   1058   _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == FLAGS_OFFSET);
   1059   _dbus_type_reader_read_basic (&reader, &v_byte);
   1060   _dbus_type_reader_next (&reader);
   1061 
   1062   /* unknown flags should be ignored */
   1063 
   1064   /* PROTOCOL VERSION */
   1065   _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
   1066   _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == VERSION_OFFSET);
   1067   _dbus_type_reader_read_basic (&reader, &v_byte);
   1068   _dbus_type_reader_next (&reader);
   1069 
   1070   if (v_byte != DBUS_MAJOR_PROTOCOL_VERSION)
   1071     {
   1072       *validity = DBUS_INVALID_BAD_PROTOCOL_VERSION;
   1073       goto invalid;
   1074     }
   1075 
   1076   /* BODY LENGTH */
   1077   _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_UINT32);
   1078   _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == BODY_LENGTH_OFFSET);
   1079   _dbus_type_reader_read_basic (&reader, &v_uint32);
   1080   _dbus_type_reader_next (&reader);
   1081 
   1082   _dbus_assert (body_len == (signed) v_uint32);
   1083 
   1084   /* SERIAL */
   1085   _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_UINT32);
   1086   _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == SERIAL_OFFSET);
   1087   _dbus_type_reader_read_basic (&reader, &serial);
   1088   _dbus_type_reader_next (&reader);
   1089 
   1090   if (serial == 0)
   1091     {
   1092       *validity = DBUS_INVALID_BAD_SERIAL;
   1093       goto invalid;
   1094     }
   1095 
   1096   _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_ARRAY);
   1097   _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == FIELDS_ARRAY_LENGTH_OFFSET);
   1098 
   1099   _dbus_type_reader_recurse (&reader, &array_reader);
   1100   while (_dbus_type_reader_get_current_type (&array_reader) != DBUS_TYPE_INVALID)
   1101     {
   1102       DBusTypeReader struct_reader;
   1103       DBusTypeReader variant_reader;
   1104       unsigned char field_code;
   1105 
   1106       _dbus_assert (_dbus_type_reader_get_current_type (&array_reader) == DBUS_TYPE_STRUCT);
   1107 
   1108       _dbus_type_reader_recurse (&array_reader, &struct_reader);
   1109 
   1110       _dbus_assert (_dbus_type_reader_get_current_type (&struct_reader) == DBUS_TYPE_BYTE);
   1111       _dbus_type_reader_read_basic (&struct_reader, &field_code);
   1112       _dbus_type_reader_next (&struct_reader);
   1113 
   1114       if (field_code == DBUS_HEADER_FIELD_INVALID)
   1115         {
   1116           _dbus_verbose ("invalid header field code\n");
   1117           *validity = DBUS_INVALID_HEADER_FIELD_CODE;
   1118           goto invalid;
   1119         }
   1120 
   1121       if (field_code > DBUS_HEADER_FIELD_LAST)
   1122         {
   1123           _dbus_verbose ("unknown header field code %d, skipping\n",
   1124                          field_code);
   1125           goto next_field;
   1126         }
   1127 
   1128       _dbus_assert (_dbus_type_reader_get_current_type (&struct_reader) == DBUS_TYPE_VARIANT);
   1129       _dbus_type_reader_recurse (&struct_reader, &variant_reader);
   1130 
   1131       v = load_and_validate_field (header, field_code, &variant_reader);
   1132       if (v != DBUS_VALID)
   1133         {
   1134           _dbus_verbose ("Field %d was invalid\n", field_code);
   1135           *validity = v;
   1136           goto invalid;
   1137         }
   1138 
   1139     next_field:
   1140       _dbus_type_reader_next (&array_reader);
   1141     }
   1142 
   1143   /* Anything we didn't fill in is now known not to exist */
   1144   i = 0;
   1145   while (i <= DBUS_HEADER_FIELD_LAST)
   1146     {
   1147       if (header->fields[i].value_pos == _DBUS_HEADER_FIELD_VALUE_UNKNOWN)
   1148         header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_NONEXISTENT;
   1149       ++i;
   1150     }
   1151 
   1152   v = check_mandatory_fields (header);
   1153   if (v != DBUS_VALID)
   1154     {
   1155       _dbus_verbose ("Mandatory fields were missing, code %d\n", v);
   1156       *validity = v;
   1157       goto invalid;
   1158     }
   1159 
   1160   *validity = DBUS_VALID;
   1161   return TRUE;
   1162 
   1163  invalid:
   1164   _dbus_string_set_length (&header->data, 0);
   1165   return FALSE;
   1166 }
   1167 
   1168 /**
   1169  * Fills in the correct body length.
   1170  *
   1171  * @param header the header
   1172  * @param body_len the length of the body
   1173  */
   1174 void
   1175 _dbus_header_update_lengths (DBusHeader *header,
   1176                              int         body_len)
   1177 {
   1178   _dbus_marshal_set_uint32 (&header->data,
   1179                             BODY_LENGTH_OFFSET,
   1180                             body_len,
   1181                             header->byte_order);
   1182 }
   1183 
   1184 static dbus_bool_t
   1185 find_field_for_modification (DBusHeader     *header,
   1186                              int             field,
   1187                              DBusTypeReader *reader,
   1188                              DBusTypeReader *realign_root)
   1189 {
   1190   dbus_bool_t retval;
   1191 
   1192   retval = FALSE;
   1193 
   1194   _dbus_type_reader_init (realign_root,
   1195                           header->byte_order,
   1196                           &_dbus_header_signature_str,
   1197                           FIELDS_ARRAY_SIGNATURE_OFFSET,
   1198                           &header->data,
   1199                           FIELDS_ARRAY_LENGTH_OFFSET);
   1200 
   1201   _dbus_type_reader_recurse (realign_root, reader);
   1202 
   1203   while (_dbus_type_reader_get_current_type (reader) != DBUS_TYPE_INVALID)
   1204     {
   1205       DBusTypeReader sub;
   1206       unsigned char field_code;
   1207 
   1208       _dbus_type_reader_recurse (reader, &sub);
   1209 
   1210       _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_BYTE);
   1211       _dbus_type_reader_read_basic (&sub, &field_code);
   1212 
   1213       if (field_code == (unsigned) field)
   1214         {
   1215           _dbus_assert (_dbus_type_reader_get_current_type (reader) == DBUS_TYPE_STRUCT);
   1216           retval = TRUE;
   1217           goto done;
   1218         }
   1219 
   1220       _dbus_type_reader_next (reader);
   1221     }
   1222 
   1223  done:
   1224   return retval;
   1225 }
   1226 
   1227 /**
   1228  * Sets the value of a field with basic type. If the value is a string
   1229  * value, it isn't allowed to be #NULL. If the field doesn't exist,
   1230  * it will be created.
   1231  *
   1232  * @param header the header
   1233  * @param field the field to set
   1234  * @param type the type of the value
   1235  * @param value the value as for _dbus_marshal_set_basic()
   1236  * @returns #FALSE if no memory
   1237  */
   1238 dbus_bool_t
   1239 _dbus_header_set_field_basic (DBusHeader       *header,
   1240                               int               field,
   1241                               int               type,
   1242                               const void       *value)
   1243 {
   1244   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
   1245 
   1246   if (!reserve_header_padding (header))
   1247     return FALSE;
   1248 
   1249   /* If the field exists we set, otherwise we append */
   1250   if (_dbus_header_cache_check (header, field))
   1251     {
   1252       DBusTypeReader reader;
   1253       DBusTypeReader realign_root;
   1254 
   1255       if (!find_field_for_modification (header, field,
   1256                                         &reader, &realign_root))
   1257         _dbus_assert_not_reached ("field was marked present in cache but wasn't found");
   1258 
   1259       if (!set_basic_field (&reader, field, type, value, &realign_root))
   1260         return FALSE;
   1261     }
   1262   else
   1263     {
   1264       DBusTypeWriter writer;
   1265       DBusTypeWriter array;
   1266 
   1267       _dbus_type_writer_init_values_only (&writer,
   1268                                           header->byte_order,
   1269                                           &_dbus_header_signature_str,
   1270                                           FIELDS_ARRAY_SIGNATURE_OFFSET,
   1271                                           &header->data,
   1272                                           FIELDS_ARRAY_LENGTH_OFFSET);
   1273 
   1274       /* recurse into array without creating a new length, and jump to
   1275        * end of array.
   1276        */
   1277       if (!_dbus_type_writer_append_array (&writer,
   1278                                            &_dbus_header_signature_str,
   1279                                            FIELDS_ARRAY_ELEMENT_SIGNATURE_OFFSET,
   1280                                            &array))
   1281         _dbus_assert_not_reached ("recurse into ARRAY should not have used memory");
   1282 
   1283       _dbus_assert (array.u.array.len_pos == FIELDS_ARRAY_LENGTH_OFFSET);
   1284       _dbus_assert (array.u.array.start_pos == FIRST_FIELD_OFFSET);
   1285       _dbus_assert (array.value_pos == HEADER_END_BEFORE_PADDING (header));
   1286 
   1287       if (!write_basic_field (&array,
   1288                               field, type, value))
   1289         return FALSE;
   1290 
   1291       if (!_dbus_type_writer_unrecurse (&writer, &array))
   1292         _dbus_assert_not_reached ("unrecurse from ARRAY should not have used memory");
   1293     }
   1294 
   1295   correct_header_padding (header);
   1296 
   1297   /* We could be smarter about this (only invalidate fields after the
   1298    * one we modified, or even only if the one we modified changed
   1299    * length). But this hack is a start.
   1300    */
   1301   _dbus_header_cache_invalidate_all (header);
   1302 
   1303   return TRUE;
   1304 }
   1305 
   1306 /**
   1307  * Gets the value of a field with basic type. If the field
   1308  * doesn't exist, returns #FALSE, otherwise returns #TRUE.
   1309  *
   1310  * @param header the header
   1311  * @param field the field to get
   1312  * @param type the type of the value
   1313  * @param value the value as for _dbus_marshal_read_basic()
   1314  * @returns #FALSE if the field doesn't exist
   1315  */
   1316 dbus_bool_t
   1317 _dbus_header_get_field_basic (DBusHeader    *header,
   1318                               int            field,
   1319                               int            type,
   1320                               void          *value)
   1321 {
   1322   _dbus_assert (field != DBUS_HEADER_FIELD_INVALID);
   1323   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
   1324   _dbus_assert (_dbus_header_field_types[field].code == field);
   1325   /* in light of this you might ask why the type is passed in;
   1326    * the only rationale I can think of is so the caller has
   1327    * to specify its expectation and breaks if we change it
   1328    */
   1329   _dbus_assert (type == EXPECTED_TYPE_OF_FIELD (field));
   1330 
   1331   if (!_dbus_header_cache_check (header, field))
   1332     return FALSE;
   1333 
   1334   _dbus_assert (header->fields[field].value_pos >= 0);
   1335 
   1336   _dbus_marshal_read_basic (&header->data,
   1337                             header->fields[field].value_pos,
   1338                             type, value, header->byte_order,
   1339                             NULL);
   1340 
   1341   return TRUE;
   1342 }
   1343 
   1344 /**
   1345  * Gets the raw marshaled data for a field. If the field doesn't
   1346  * exist, returns #FALSE, otherwise returns #TRUE.  Returns the start
   1347  * of the marshaled data, i.e. usually the byte where the length
   1348  * starts (for strings and arrays) or for basic types just the value
   1349  * itself.
   1350  *
   1351  * @param header the header
   1352  * @param field the field to get
   1353  * @param str return location for the data string
   1354  * @param pos return location for start of field value
   1355  * @returns #FALSE if the field doesn't exist
   1356  */
   1357 dbus_bool_t
   1358 _dbus_header_get_field_raw (DBusHeader        *header,
   1359                             int                field,
   1360                             const DBusString **str,
   1361                             int               *pos)
   1362 {
   1363   if (!_dbus_header_cache_check (header, field))
   1364     return FALSE;
   1365 
   1366   if (str)
   1367     *str = &header->data;
   1368   if (pos)
   1369     *pos = header->fields[field].value_pos;
   1370 
   1371   return TRUE;
   1372 }
   1373 
   1374 /**
   1375  * Deletes a field, if it exists.
   1376  *
   1377  * @param header the header
   1378  * @param field the field to delete
   1379  * @returns #FALSE if no memory
   1380  */
   1381 dbus_bool_t
   1382 _dbus_header_delete_field (DBusHeader *header,
   1383                            int         field)
   1384 {
   1385   DBusTypeReader reader;
   1386   DBusTypeReader realign_root;
   1387 
   1388   if (_dbus_header_cache_known_nonexistent (header, field))
   1389     return TRUE; /* nothing to do */
   1390 
   1391   /* Scan to the field we want, delete and realign, reappend
   1392    * padding. Field may turn out not to exist.
   1393    */
   1394   if (!find_field_for_modification (header, field,
   1395                                     &reader, &realign_root))
   1396     return TRUE; /* nothing to do */
   1397 
   1398   if (!reserve_header_padding (header))
   1399     return FALSE;
   1400 
   1401   if (!_dbus_type_reader_delete (&reader,
   1402                                  &realign_root))
   1403     return FALSE;
   1404 
   1405   correct_header_padding (header);
   1406 
   1407   _dbus_header_cache_invalidate_all (header);
   1408 
   1409   _dbus_assert (!_dbus_header_cache_check (header, field)); /* Expensive assertion ... */
   1410 
   1411   return TRUE;
   1412 }
   1413 
   1414 /**
   1415  * Toggles a message flag bit, turning on the bit if value = TRUE and
   1416  * flipping it off if value = FALSE.
   1417  *
   1418  * @param header the header
   1419  * @param flag the message flag to toggle
   1420  * @param value toggle on or off
   1421  */
   1422 void
   1423 _dbus_header_toggle_flag (DBusHeader   *header,
   1424                           dbus_uint32_t flag,
   1425                           dbus_bool_t   value)
   1426 {
   1427   unsigned char *flags_p;
   1428 
   1429   flags_p = _dbus_string_get_data_len (&header->data, FLAGS_OFFSET, 1);
   1430 
   1431   if (value)
   1432     *flags_p |= flag;
   1433   else
   1434     *flags_p &= ~flag;
   1435 }
   1436 
   1437 /**
   1438  * Gets a message flag bit, returning TRUE if the bit is set.
   1439  *
   1440  * @param header the header
   1441  * @param flag the message flag to get
   1442  * @returns #TRUE if the flag is set
   1443  */
   1444 dbus_bool_t
   1445 _dbus_header_get_flag (DBusHeader   *header,
   1446                        dbus_uint32_t flag)
   1447 {
   1448   const unsigned char *flags_p;
   1449 
   1450   flags_p = _dbus_string_get_const_data_len (&header->data, FLAGS_OFFSET, 1);
   1451 
   1452   return (*flags_p & flag) != 0;
   1453 }
   1454 
   1455 /**
   1456  * Swaps the header into the given order if required.
   1457  *
   1458  * @param header the header
   1459  * @param new_order the new byte order
   1460  */
   1461 void
   1462 _dbus_header_byteswap (DBusHeader *header,
   1463                        int         new_order)
   1464 {
   1465   if (header->byte_order == new_order)
   1466     return;
   1467 
   1468   _dbus_marshal_byteswap (&_dbus_header_signature_str,
   1469                           0, header->byte_order,
   1470                           new_order,
   1471                           &header->data, 0);
   1472 
   1473   header->byte_order = new_order;
   1474 }
   1475 
   1476 /** @} */
   1477 
   1478 #ifdef DBUS_BUILD_TESTS
   1479 #include "dbus-test.h"
   1480 #include <stdio.h>
   1481 
   1482 dbus_bool_t
   1483 _dbus_marshal_header_test (void)
   1484 {
   1485 
   1486   return TRUE;
   1487 }
   1488 
   1489 #endif /* DBUS_BUILD_TESTS */
   1490