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