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