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