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