• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
reserve_header_padding(DBusHeader * header)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
correct_header_padding(DBusHeader * header)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
_dbus_header_cache_invalidate_all(DBusHeader * header)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
_dbus_header_cache_one(DBusHeader * header,int field_code,DBusTypeReader * variant_reader)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
_dbus_header_cache_revalidate(DBusHeader * header)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
_dbus_header_cache_check(DBusHeader * header,int field)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
_dbus_header_cache_known_nonexistent(DBusHeader * header,int field)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
write_basic_field(DBusTypeWriter * writer,int field,int type,const void * value)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
set_basic_field(DBusTypeReader * reader,int field,int type,const void * value,const DBusTypeReader * realign_root)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
_dbus_header_get_message_type(DBusHeader * header)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
_dbus_header_set_serial(DBusHeader * header,dbus_uint32_t serial)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
_dbus_header_get_serial(DBusHeader * header)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
_dbus_header_reinit(DBusHeader * header,int byte_order)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
_dbus_header_init(DBusHeader * header,int byte_order)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
_dbus_header_free(DBusHeader * header)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
_dbus_header_copy(const DBusHeader * header,DBusHeader * dest)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
_dbus_header_create(DBusHeader * header,int message_type,const char * destination,const char * path,const char * interface,const char * member,const char * error_name)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
_dbus_header_have_message_untrusted(int max_message_length,DBusValidity * validity,int * byte_order,int * fields_array_len,int * header_len,int * body_len,const DBusString * str,int start,int len)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
check_mandatory_fields(DBusHeader * header)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
load_and_validate_field(DBusHeader * header,int field,DBusTypeReader * variant_reader)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
_dbus_header_load(DBusHeader * header,DBusValidationMode mode,DBusValidity * validity,int byte_order,int fields_array_len,int header_len,int body_len,const DBusString * str,int start,int len)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
_dbus_header_update_lengths(DBusHeader * header,int body_len)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
find_field_for_modification(DBusHeader * header,int field,DBusTypeReader * reader,DBusTypeReader * realign_root)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
_dbus_header_set_field_basic(DBusHeader * header,int field,int type,const void * value)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
_dbus_header_get_field_basic(DBusHeader * header,int field,int type,void * value)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
_dbus_header_get_field_raw(DBusHeader * header,int field,const DBusString ** str,int * pos)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
_dbus_header_delete_field(DBusHeader * header,int field)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
_dbus_header_toggle_flag(DBusHeader * header,dbus_uint32_t flag,dbus_bool_t value)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
_dbus_header_get_flag(DBusHeader * header,dbus_uint32_t flag)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
_dbus_header_byteswap(DBusHeader * header,int new_order)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
_dbus_marshal_header_test(void)1489 _dbus_marshal_header_test (void)
1490 {
1491 
1492   return TRUE;
1493 }
1494 
1495 #endif /* DBUS_BUILD_TESTS */
1496