D-Bus 1.12.20
dbus-message-factory.c
1/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2/* dbus-message-factory.c Generator of valid and invalid message data for test suite
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#include <config.h>
24
25#ifndef DOXYGEN_SHOULD_SKIP_THIS
26
27#ifdef DBUS_ENABLE_EMBEDDED_TESTS
28#include "dbus-message-factory.h"
29#include "dbus-message-private.h"
30#include "dbus-signature.h"
31#include "dbus-test.h"
32#include <stdio.h>
33
34typedef enum
35 {
36 CHANGE_TYPE_ADJUST,
37 CHANGE_TYPE_ABSOLUTE
38 } ChangeType;
39
40#define BYTE_ORDER_OFFSET 0
41#define TYPE_OFFSET 1
42#define BODY_LENGTH_OFFSET 4
43#define FIELDS_ARRAY_LENGTH_OFFSET 12
44
45static void
46iter_recurse (DBusMessageDataIter *iter)
47{
48 iter->depth += 1;
49 _dbus_assert (iter->depth < _DBUS_MESSAGE_DATA_MAX_NESTING);
50 _dbus_assert (iter->sequence_nos[iter->depth] >= 0);
51}
52
53static int
54iter_get_sequence (DBusMessageDataIter *iter)
55{
56 _dbus_assert (iter->sequence_nos[iter->depth] >= 0);
57 return iter->sequence_nos[iter->depth];
58}
59
60static void
61iter_set_sequence (DBusMessageDataIter *iter,
62 int sequence)
63{
64 _dbus_assert (sequence >= 0);
65 iter->sequence_nos[iter->depth] = sequence;
66}
67
68static void
69iter_unrecurse (DBusMessageDataIter *iter)
70{
71 iter->depth -= 1;
72 _dbus_assert (iter->depth >= 0);
73}
74
75static void
76iter_next (DBusMessageDataIter *iter)
77{
78 iter->sequence_nos[iter->depth] += 1;
79}
80
81static dbus_bool_t
82iter_first_in_series (DBusMessageDataIter *iter)
83{
84 int i;
85
86 i = iter->depth;
87 while (i < _DBUS_MESSAGE_DATA_MAX_NESTING)
88 {
89 if (iter->sequence_nos[i] != 0)
90 return FALSE;
91 ++i;
92 }
93 return TRUE;
94}
95
96typedef dbus_bool_t (* DBusInnerGeneratorFunc) (DBusMessageDataIter *iter,
97 DBusMessage **message_p);
98typedef dbus_bool_t (* DBusMessageGeneratorFunc) (DBusMessageDataIter *iter,
99 DBusString *data,
100 DBusValidity *expected_validity);
101
102static void
103set_reply_serial (DBusMessage *message)
104{
105 if (message == NULL)
107 if (!dbus_message_set_reply_serial (message, 100))
109}
110
111static dbus_bool_t
112generate_trivial_inner (DBusMessageDataIter *iter,
113 DBusMessage **message_p)
114{
115 DBusMessage *message;
116
117 switch (iter_get_sequence (iter))
118 {
119 case 0:
120 message = dbus_message_new_method_call ("org.freedesktop.TextEditor",
121 "/foo/bar",
122 "org.freedesktop.DocumentFactory",
123 "Create");
124 break;
125 case 1:
127 set_reply_serial (message);
128 break;
129 case 2:
130 message = dbus_message_new_signal ("/foo/bar",
131 "org.freedesktop.DocumentFactory",
132 "Created");
133 break;
134 case 3:
136
137 if (!dbus_message_set_error_name (message,
138 "org.freedesktop.TestErrorName"))
140
141 {
142 DBusMessageIter iter2;
143 const char *v_STRING = "This is an error";
144
145 dbus_message_iter_init_append (message, &iter2);
148 &v_STRING))
150 }
151
152 set_reply_serial (message);
153 break;
154 default:
155 return FALSE;
156 }
157
158 if (message == NULL)
160
161 *message_p = message;
162
163 return TRUE;
164}
165
166static dbus_bool_t
167generate_many_bodies_inner (DBusMessageDataIter *iter,
168 DBusMessage **message_p)
169{
170 DBusMessage *message;
171 DBusString signature;
172 DBusString body;
173 char byte_order;
174
175 /* Keeping this small makes things go faster */
176 message = dbus_message_new_method_call ("o.z.F",
177 "/",
178 "o.z.B",
179 "Nah");
180 if (message == NULL)
182
183 byte_order = _dbus_header_get_byte_order (&message->header);
184
185 set_reply_serial (message);
186
187 if (!_dbus_string_init (&signature) || !_dbus_string_init (&body))
189
190 if (dbus_internal_do_not_use_generate_bodies (iter_get_sequence (iter),
191 byte_order,
192 &signature, &body))
193 {
194 const char *v_SIGNATURE;
195
196 v_SIGNATURE = _dbus_string_get_const_data (&signature);
197 if (!_dbus_header_set_field_basic (&message->header,
200 &v_SIGNATURE))
202
203 if (!_dbus_string_move (&body, 0, &message->body, 0))
205
207 _dbus_string_get_length (&message->body),
208 byte_order);
209
210 *message_p = message;
211 }
212 else
213 {
214 dbus_message_unref (message);
215 *message_p = NULL;
216 }
217
218 _dbus_string_free (&signature);
219 _dbus_string_free (&body);
220
221 return *message_p != NULL;
222}
223
224static void
225generate_from_message (DBusString *data,
226 DBusValidity *expected_validity,
227 DBusMessage *message)
228{
229 dbus_message_set_serial (message, 1);
230 dbus_message_lock (message);
231
232 *expected_validity = DBUS_VALID;
233
234 /* move for efficiency, since we'll nuke the message anyway */
235 if (!_dbus_string_move (&message->header.data, 0,
236 data, 0))
238
239 if (!_dbus_string_copy (&message->body, 0,
240 data, _dbus_string_get_length (data)))
242}
243
244static dbus_bool_t
245generate_outer (DBusMessageDataIter *iter,
246 DBusString *data,
247 DBusValidity *expected_validity,
248 DBusInnerGeneratorFunc func)
249{
250 DBusMessage *message;
251
252 message = NULL;
253 if (!(*func)(iter, &message))
254 return FALSE;
255
256 iter_next (iter);
257
258 _dbus_assert (message != NULL);
259
260 generate_from_message (data, expected_validity, message);
261
262 dbus_message_unref (message);
263
264 return TRUE;
265}
266
267static dbus_bool_t
268generate_trivial (DBusMessageDataIter *iter,
269 DBusString *data,
270 DBusValidity *expected_validity)
271{
272 return generate_outer (iter, data, expected_validity,
273 generate_trivial_inner);
274}
275
276static dbus_bool_t
277generate_many_bodies (DBusMessageDataIter *iter,
278 DBusString *data,
279 DBusValidity *expected_validity)
280{
281 return generate_outer (iter, data, expected_validity,
282 generate_many_bodies_inner);
283}
284
285static DBusMessage*
286simple_method_call (void)
287{
288 DBusMessage *message;
289 /* Keeping this small makes stuff go faster */
290 message = dbus_message_new_method_call ("o.b.Q",
291 "/f/b",
292 "o.b.Z",
293 "Fro");
294 if (message == NULL)
296 return message;
297}
298
299static DBusMessage*
300simple_signal (void)
301{
302 DBusMessage *message;
303 message = dbus_message_new_signal ("/f/b",
304 "o.b.Z",
305 "Fro");
306 if (message == NULL)
308 return message;
309}
310
311static DBusMessage*
312simple_method_return (void)
313{
314 DBusMessage *message;
316 if (message == NULL)
318
319 set_reply_serial (message);
320
321 return message;
322}
323
324static DBusMessage*
325simple_error (void)
326{
327 DBusMessage *message;
329 if (message == NULL)
331
332 if (!dbus_message_set_error_name (message, "foo.bar"))
334
335 set_reply_serial (message);
336
337 return message;
338}
339
340static DBusMessage*
341message_with_nesting_levels (int levels)
342{
343 DBusMessage *message;
344 dbus_int32_t v_INT32;
345 DBusMessageIter *parents;
346 DBusMessageIter *children;
347 int i;
348
349 /* If levels is higher it breaks sig_refcount in DBusMessageRealIter
350 * in dbus-message.c, this assert is just to help you know you need
351 * to fix that if you hit it
352 */
353 _dbus_assert (levels < 256);
354
355 parents = dbus_new(DBusMessageIter, levels + 1);
356 children = dbus_new(DBusMessageIter, levels + 1);
357
358 v_INT32 = 42;
359 message = simple_method_call ();
360
361 i = 0;
362 dbus_message_iter_init_append (message, &parents[i]);
363 while (i < levels)
364 {
366 i == (levels - 1) ?
369 &children[i]))
371 ++i;
372 parents[i] = children[i-1];
373 }
374 --i;
375
376 if (!dbus_message_iter_append_basic (&children[i], DBUS_TYPE_INT32, &v_INT32))
378
379 while (i >= 0)
380 {
381 if (!dbus_message_iter_close_container (&parents[i], &children[i]))
383 --i;
384 }
385
386 dbus_free(parents);
387 dbus_free(children);
388
389 return message;
390}
391
392static dbus_bool_t
393generate_special (DBusMessageDataIter *iter,
394 DBusString *data,
395 DBusValidity *expected_validity)
396{
397 int item_seq;
398 DBusMessage *message;
399 int pos;
400 dbus_int32_t v_INT32;
401
402 _dbus_assert (_dbus_string_get_length (data) == 0);
403
404 message = NULL;
405 pos = -1;
406 v_INT32 = 42;
407 item_seq = iter_get_sequence (iter);
408
409 if (item_seq == 0)
410 {
411 message = simple_method_call ();
412 if (!dbus_message_append_args (message,
413 DBUS_TYPE_INT32, &v_INT32,
414 DBUS_TYPE_INT32, &v_INT32,
415 DBUS_TYPE_INT32, &v_INT32,
418
421 NULL, &pos);
422 generate_from_message (data, expected_validity, message);
423
424 /* set an invalid typecode */
425 _dbus_string_set_byte (data, pos + 1, '$');
426
427 *expected_validity = DBUS_INVALID_UNKNOWN_TYPECODE;
428 }
429 else if (item_seq == 1)
430 {
431 char long_sig[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH+2];
432 const char *v_STRING;
433 int i;
434
435 message = simple_method_call ();
436 if (!dbus_message_append_args (message,
437 DBUS_TYPE_INT32, &v_INT32,
438 DBUS_TYPE_INT32, &v_INT32,
439 DBUS_TYPE_INT32, &v_INT32,
442
443 i = 0;
444 while (i < (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH + 1))
445 {
446 long_sig[i] = DBUS_TYPE_ARRAY;
447 ++i;
448 }
449 long_sig[i] = DBUS_TYPE_INVALID;
450
451 v_STRING = long_sig;
452 if (!_dbus_header_set_field_basic (&message->header,
455 &v_STRING))
457
460 NULL, &pos);
461 generate_from_message (data, expected_validity, message);
462
463 *expected_validity = DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION;
464 }
465 else if (item_seq == 2)
466 {
467 char long_sig[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*2+4];
468 const char *v_STRING;
469 int i;
470
471 message = simple_method_call ();
472 if (!dbus_message_append_args (message,
473 DBUS_TYPE_INT32, &v_INT32,
474 DBUS_TYPE_INT32, &v_INT32,
475 DBUS_TYPE_INT32, &v_INT32,
478
479 i = 0;
480 while (i <= (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH + 1))
481 {
482 long_sig[i] = DBUS_STRUCT_BEGIN_CHAR;
483 ++i;
484 }
485
486 long_sig[i] = DBUS_TYPE_INT32;
487 ++i;
488
489 while (i < (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*2 + 3))
490 {
491 long_sig[i] = DBUS_STRUCT_END_CHAR;
492 ++i;
493 }
494 long_sig[i] = DBUS_TYPE_INVALID;
495
496 v_STRING = long_sig;
497 if (!_dbus_header_set_field_basic (&message->header,
500 &v_STRING))
502
505 NULL, &pos);
506 generate_from_message (data, expected_validity, message);
507
508 *expected_validity = DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION;
509 }
510 else if (item_seq == 3)
511 {
512 message = simple_method_call ();
513 if (!dbus_message_append_args (message,
514 DBUS_TYPE_INT32, &v_INT32,
515 DBUS_TYPE_INT32, &v_INT32,
516 DBUS_TYPE_INT32, &v_INT32,
519
522 NULL, &pos);
523 generate_from_message (data, expected_validity, message);
524
525 _dbus_string_set_byte (data, pos + 1, DBUS_STRUCT_BEGIN_CHAR);
526
527 *expected_validity = DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED;
528 }
529 else if (item_seq == 4)
530 {
531 message = simple_method_call ();
532 if (!dbus_message_append_args (message,
533 DBUS_TYPE_INT32, &v_INT32,
534 DBUS_TYPE_INT32, &v_INT32,
535 DBUS_TYPE_INT32, &v_INT32,
538
541 NULL, &pos);
542 generate_from_message (data, expected_validity, message);
543
544 _dbus_string_set_byte (data, pos + 1, DBUS_STRUCT_END_CHAR);
545
546 *expected_validity = DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED;
547 }
548 else if (item_seq == 5)
549 {
550 message = simple_method_call ();
551 if (!dbus_message_append_args (message,
552 DBUS_TYPE_INT32, &v_INT32,
553 DBUS_TYPE_INT32, &v_INT32,
554 DBUS_TYPE_INT32, &v_INT32,
557
560 NULL, &pos);
561 generate_from_message (data, expected_validity, message);
562
563 _dbus_string_set_byte (data, pos + 1, DBUS_STRUCT_BEGIN_CHAR);
564 _dbus_string_set_byte (data, pos + 2, DBUS_STRUCT_END_CHAR);
565
566 *expected_validity = DBUS_INVALID_STRUCT_HAS_NO_FIELDS;
567 }
568 else if (item_seq == 6)
569 {
570 message = simple_method_call ();
571 generate_from_message (data, expected_validity, message);
572
573 _dbus_string_set_byte (data, TYPE_OFFSET, DBUS_MESSAGE_TYPE_INVALID);
574
575 *expected_validity = DBUS_INVALID_BAD_MESSAGE_TYPE;
576 }
577 else if (item_seq == 7)
578 {
579 /* Messages of unknown type are considered valid */
580 message = simple_method_call ();
581 generate_from_message (data, expected_validity, message);
582
583 _dbus_string_set_byte (data, TYPE_OFFSET, 100);
584
585 *expected_validity = DBUS_VALID;
586 }
587 else if (item_seq == 8)
588 {
589 char byte_order;
590
591 message = simple_method_call ();
592 byte_order = _dbus_header_get_byte_order (&message->header);
593 generate_from_message (data, expected_validity, message);
594
597 byte_order);
600 byte_order);
601 *expected_validity = DBUS_INVALID_MESSAGE_TOO_LONG;
602 }
603 else if (item_seq == 9)
604 {
605 const char *v_STRING = "not a valid bus name";
606 message = simple_method_call ();
607
608 if (!_dbus_header_set_field_basic (&message->header,
610 DBUS_TYPE_STRING, &v_STRING))
612
613 generate_from_message (data, expected_validity, message);
614
615 *expected_validity = DBUS_INVALID_BAD_SENDER;
616 }
617 else if (item_seq == 10)
618 {
619 message = simple_method_call ();
620
623
624 generate_from_message (data, expected_validity, message);
625
626 *expected_validity = DBUS_INVALID_USES_LOCAL_INTERFACE;
627 }
628 else if (item_seq == 11)
629 {
630 message = simple_method_call ();
631
634
635 generate_from_message (data, expected_validity, message);
636
637 *expected_validity = DBUS_INVALID_USES_LOCAL_PATH;
638 }
639 else if (item_seq == 12)
640 {
641 /* Method calls don't have to have interface */
642 message = simple_method_call ();
643
644 if (!dbus_message_set_interface (message, NULL))
646
647 generate_from_message (data, expected_validity, message);
648
649 *expected_validity = DBUS_VALID;
650 }
651 else if (item_seq == 13)
652 {
653 /* Signals require an interface */
654 message = simple_signal ();
655
656 if (!dbus_message_set_interface (message, NULL))
658
659 generate_from_message (data, expected_validity, message);
660
661 *expected_validity = DBUS_INVALID_MISSING_INTERFACE;
662 }
663 else if (item_seq == 14)
664 {
665 message = simple_method_return ();
666
669
670 generate_from_message (data, expected_validity, message);
671
672 *expected_validity = DBUS_INVALID_MISSING_REPLY_SERIAL;
673 }
674 else if (item_seq == 15)
675 {
676 message = simple_error ();
677
678 if (!dbus_message_set_error_name (message, NULL))
680
681 generate_from_message (data, expected_validity, message);
682
683 *expected_validity = DBUS_INVALID_MISSING_ERROR_NAME;
684 }
685 else if (item_seq == 16)
686 {
687 char long_sig[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*4+10];
688 const char *v_STRING;
689 int i;
690 int n_begins;
691
692 message = simple_method_call ();
693 if (!dbus_message_append_args (message,
694 DBUS_TYPE_INT32, &v_INT32,
695 DBUS_TYPE_INT32, &v_INT32,
696 DBUS_TYPE_INT32, &v_INT32,
699
700 i = 0;
701 while (i <= (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*3 + 3))
702 {
703 long_sig[i] = DBUS_TYPE_ARRAY;
704 ++i;
705 long_sig[i] = DBUS_DICT_ENTRY_BEGIN_CHAR;
706 ++i;
707 long_sig[i] = DBUS_TYPE_INT32;
708 ++i;
709 }
710 n_begins = i / 3;
711
712 long_sig[i] = DBUS_TYPE_INT32;
713 ++i;
714
715 while (n_begins > 0)
716 {
717 long_sig[i] = DBUS_DICT_ENTRY_END_CHAR;
718 ++i;
719 n_begins -= 1;
720 }
721 long_sig[i] = DBUS_TYPE_INVALID;
722
723 v_STRING = long_sig;
724 if (!_dbus_header_set_field_basic (&message->header,
727 &v_STRING))
729
732 NULL, &pos);
733 generate_from_message (data, expected_validity, message);
734
735 *expected_validity = DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION;
736 }
737 else if (item_seq == 17)
738 {
739 message = simple_method_call ();
740 if (!dbus_message_append_args (message,
741 DBUS_TYPE_INT32, &v_INT32,
742 DBUS_TYPE_INT32, &v_INT32,
743 DBUS_TYPE_INT32, &v_INT32,
746
749 NULL, &pos);
750 generate_from_message (data, expected_validity, message);
751
752 _dbus_string_set_byte (data, pos + 1, DBUS_TYPE_ARRAY);
753 _dbus_string_set_byte (data, pos + 2, DBUS_DICT_ENTRY_BEGIN_CHAR);
754
755 *expected_validity = DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED;
756 }
757 else if (item_seq == 18)
758 {
759 message = simple_method_call ();
760 if (!dbus_message_append_args (message,
761 DBUS_TYPE_INT32, &v_INT32,
762 DBUS_TYPE_INT32, &v_INT32,
763 DBUS_TYPE_INT32, &v_INT32,
766
769 NULL, &pos);
770 generate_from_message (data, expected_validity, message);
771
772 _dbus_string_set_byte (data, pos + 1, DBUS_DICT_ENTRY_END_CHAR);
773
774 *expected_validity = DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED;
775 }
776 else if (item_seq == 19)
777 {
778 message = simple_method_call ();
779 if (!dbus_message_append_args (message,
780 DBUS_TYPE_INT32, &v_INT32,
781 DBUS_TYPE_INT32, &v_INT32,
782 DBUS_TYPE_INT32, &v_INT32,
785
788 NULL, &pos);
789 generate_from_message (data, expected_validity, message);
790
791 _dbus_string_set_byte (data, pos + 1, DBUS_TYPE_ARRAY);
792 _dbus_string_set_byte (data, pos + 2, DBUS_DICT_ENTRY_BEGIN_CHAR);
793 _dbus_string_set_byte (data, pos + 3, DBUS_DICT_ENTRY_END_CHAR);
794
795 *expected_validity = DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS;
796 }
797 else if (item_seq == 20)
798 {
799 /* 64 levels of nesting is OK */
800 message = message_with_nesting_levels(64);
801
802 generate_from_message (data, expected_validity, message);
803
804 *expected_validity = DBUS_VALID;
805 }
806 else if (item_seq == 21)
807 {
808 /* 65 levels of nesting is not OK */
809 message = message_with_nesting_levels(65);
810
811 generate_from_message (data, expected_validity, message);
812
813 *expected_validity = DBUS_INVALID_NESTED_TOO_DEEPLY;
814 }
815 else
816 {
817 return FALSE;
818 }
819
820 if (message)
821 dbus_message_unref (message);
822
823 iter_next (iter);
824 return TRUE;
825}
826
827static dbus_bool_t
828generate_wrong_length (DBusMessageDataIter *iter,
829 DBusString *data,
830 DBusValidity *expected_validity)
831{
832 int lengths[] = { -42, -17, -16, -15, -9, -8, -7, -6, -5, -4, -3, -2, -1,
833 1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 16, 30 };
834 int adjust;
835 int len_seq;
836
837 restart:
838 len_seq = iter_get_sequence (iter);
839 if (len_seq == _DBUS_N_ELEMENTS (lengths))
840 return FALSE;
841
842 _dbus_assert (len_seq < _DBUS_N_ELEMENTS (lengths));
843
844 iter_recurse (iter);
845 if (!generate_many_bodies (iter, data, expected_validity))
846 {
847 iter_set_sequence (iter, 0); /* reset to first body */
848 iter_unrecurse (iter);
849 iter_next (iter); /* next length adjustment */
850 goto restart;
851 }
852 iter_unrecurse (iter);
853
854 adjust = lengths[len_seq];
855
856 if (adjust < 0)
857 {
858 if ((_dbus_string_get_length (data) + adjust) < DBUS_MINIMUM_HEADER_SIZE)
860 else
861 _dbus_string_shorten (data, - adjust);
862 *expected_validity = DBUS_INVALID_FOR_UNKNOWN_REASON;
863 }
864 else
865 {
866 if (!_dbus_string_lengthen (data, adjust))
868 *expected_validity = DBUS_INVALID_TOO_MUCH_DATA;
869 }
870
871 /* Fixup lengths */
872 {
873 int old_body_len;
874 int new_body_len;
875 int byte_order;
876
877 _dbus_assert (_dbus_string_get_length (data) >= DBUS_MINIMUM_HEADER_SIZE);
878
879 byte_order = _dbus_string_get_byte (data, BYTE_ORDER_OFFSET);
880 old_body_len = _dbus_marshal_read_uint32 (data,
882 byte_order,
883 NULL);
884 _dbus_assert (old_body_len < _dbus_string_get_length (data));
885 new_body_len = old_body_len + adjust;
886 if (new_body_len < 0)
887 {
888 new_body_len = 0;
889 /* we just munged the header, and aren't sure how */
890 *expected_validity = DBUS_VALIDITY_UNKNOWN;
891 }
892
893 _dbus_verbose ("changing body len from %u to %u by adjust %d\n",
894 old_body_len, new_body_len, adjust);
895
897 new_body_len,
898 byte_order);
899 }
900
901 return TRUE;
902}
903
904static dbus_bool_t
905generate_byte_changed (DBusMessageDataIter *iter,
906 DBusString *data,
907 DBusValidity *expected_validity)
908{
909 int byte_seq;
910 int v_BYTE;
911
912 /* This is a little convoluted to make the bodies the
913 * outer loop and each byte of each body the inner
914 * loop
915 */
916
917 restart:
918 if (!generate_many_bodies (iter, data, expected_validity))
919 return FALSE;
920
921 iter_recurse (iter);
922 byte_seq = iter_get_sequence (iter);
923 iter_next (iter);
924 iter_unrecurse (iter);
925
926 if (byte_seq == _dbus_string_get_length (data))
927 {
928 _dbus_string_set_length (data, 0);
929 /* reset byte count */
930 iter_recurse (iter);
931 iter_set_sequence (iter, 0);
932 iter_unrecurse (iter);
933 goto restart;
934 }
935 else
936 {
937 /* Undo the "next" in generate_many_bodies */
938 iter_set_sequence (iter, iter_get_sequence (iter) - 1);
939 }
940
941 _dbus_assert (byte_seq < _dbus_string_get_length (data));
942 v_BYTE = _dbus_string_get_byte (data, byte_seq);
943 v_BYTE += byte_seq; /* arbitrary but deterministic change to the byte */
944 _dbus_string_set_byte (data, byte_seq, v_BYTE);
945 *expected_validity = DBUS_VALIDITY_UNKNOWN;
946
947 return TRUE;
948}
949
950#if 0
951/* This is really expensive and doesn't add too much coverage */
952
953static dbus_bool_t
954find_next_typecode (DBusMessageDataIter *iter,
955 DBusString *data,
956 DBusValidity *expected_validity)
957{
958 int body_seq;
959 int byte_seq;
960 int base_depth;
961
962 base_depth = iter->depth;
963
964 restart:
965 _dbus_assert (iter->depth == (base_depth + 0));
966 _dbus_string_set_length (data, 0);
967
968 body_seq = iter_get_sequence (iter);
969
970 if (!generate_many_bodies (iter, data, expected_validity))
971 return FALSE;
972 /* Undo the "next" in generate_many_bodies */
973 iter_set_sequence (iter, body_seq);
974
975 iter_recurse (iter);
976 while (TRUE)
977 {
978 _dbus_assert (iter->depth == (base_depth + 1));
979
980 byte_seq = iter_get_sequence (iter);
981
982 _dbus_assert (byte_seq <= _dbus_string_get_length (data));
983
984 if (byte_seq == _dbus_string_get_length (data))
985 {
986 /* reset byte count */
987 iter_set_sequence (iter, 0);
988 iter_unrecurse (iter);
989 _dbus_assert (iter->depth == (base_depth + 0));
990 iter_next (iter); /* go to the next body */
991 goto restart;
992 }
993
994 _dbus_assert (byte_seq < _dbus_string_get_length (data));
995
996 if (dbus_type_is_valid (_dbus_string_get_byte (data, byte_seq)))
997 break;
998 else
999 iter_next (iter);
1000 }
1001
1002 _dbus_assert (byte_seq == iter_get_sequence (iter));
1003 _dbus_assert (byte_seq < _dbus_string_get_length (data));
1004
1005 iter_unrecurse (iter);
1006
1007 _dbus_assert (iter->depth == (base_depth + 0));
1008
1009 return TRUE;
1010}
1011
1012static const int typecodes[] = {
1033 255 /* random invalid typecode */
1034};
1035
1036static dbus_bool_t
1037generate_typecode_changed (DBusMessageDataIter *iter,
1038 DBusString *data,
1039 DBusValidity *expected_validity)
1040{
1041 int byte_seq;
1042 int typecode_seq;
1043 int base_depth;
1044
1045 base_depth = iter->depth;
1046
1047 restart:
1048 _dbus_assert (iter->depth == (base_depth + 0));
1049 _dbus_string_set_length (data, 0);
1050
1051 if (!find_next_typecode (iter, data, expected_validity))
1052 return FALSE;
1053
1054 iter_recurse (iter);
1055 byte_seq = iter_get_sequence (iter);
1056
1057 _dbus_assert (byte_seq < _dbus_string_get_length (data));
1058
1059 iter_recurse (iter);
1060 typecode_seq = iter_get_sequence (iter);
1061 iter_next (iter);
1062
1063 _dbus_assert (typecode_seq <= _DBUS_N_ELEMENTS (typecodes));
1064
1065 if (typecode_seq == _DBUS_N_ELEMENTS (typecodes))
1066 {
1067 _dbus_assert (iter->depth == (base_depth + 2));
1068 iter_set_sequence (iter, 0); /* reset typecode sequence */
1069 iter_unrecurse (iter);
1070 _dbus_assert (iter->depth == (base_depth + 1));
1071 iter_next (iter); /* go to the next byte_seq */
1072 iter_unrecurse (iter);
1073 _dbus_assert (iter->depth == (base_depth + 0));
1074 goto restart;
1075 }
1076
1077 _dbus_assert (iter->depth == (base_depth + 2));
1078 iter_unrecurse (iter);
1079 _dbus_assert (iter->depth == (base_depth + 1));
1080 iter_unrecurse (iter);
1081 _dbus_assert (iter->depth == (base_depth + 0));
1082
1083#if 0
1084 printf ("Changing byte %d in message %d to %c\n",
1085 byte_seq, iter_get_sequence (iter), typecodes[typecode_seq]);
1086#endif
1087
1088 _dbus_string_set_byte (data, byte_seq, typecodes[typecode_seq]);
1089 *expected_validity = DBUS_VALIDITY_UNKNOWN;
1090 return TRUE;
1091}
1092#endif
1093
1094typedef struct
1095{
1096 ChangeType type;
1097 dbus_uint32_t value; /* cast to signed for adjusts */
1098} UIntChange;
1099
1100static const UIntChange uint32_changes[] = {
1101 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) -1 },
1102 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) -2 },
1103 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) -3 },
1104 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) 1 },
1105 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) 2 },
1106 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) 3 },
1107 { CHANGE_TYPE_ABSOLUTE, _DBUS_UINT32_MAX },
1108 { CHANGE_TYPE_ABSOLUTE, 0 },
1109 { CHANGE_TYPE_ABSOLUTE, 1 },
1110 { CHANGE_TYPE_ABSOLUTE, _DBUS_UINT32_MAX - 1 },
1111 { CHANGE_TYPE_ABSOLUTE, _DBUS_UINT32_MAX - 5 }
1112};
1113
1114static dbus_bool_t
1115generate_uint32_changed (DBusMessageDataIter *iter,
1116 DBusString *data,
1117 DBusValidity *expected_validity)
1118{
1119 int body_seq;
1120 int byte_seq;
1121 int change_seq;
1122 dbus_uint32_t v_UINT32;
1123 int byte_order;
1124 const UIntChange *change;
1125 int base_depth;
1126
1127 /* Outer loop is each body, next loop is each change,
1128 * inner loop is each change location
1129 */
1130
1131 base_depth = iter->depth;
1132
1133 next_body:
1134 _dbus_assert (iter->depth == (base_depth + 0));
1135 _dbus_string_set_length (data, 0);
1136 body_seq = iter_get_sequence (iter);
1137
1138 if (!generate_many_bodies (iter, data, expected_validity))
1139 return FALSE;
1140
1141 _dbus_assert (iter->depth == (base_depth + 0));
1142
1143 iter_set_sequence (iter, body_seq); /* undo the "next" from generate_many_bodies */
1144 iter_recurse (iter);
1145 next_change:
1146 _dbus_assert (iter->depth == (base_depth + 1));
1147 change_seq = iter_get_sequence (iter);
1148
1149 if (change_seq == _DBUS_N_ELEMENTS (uint32_changes))
1150 {
1151 /* Reset change count */
1152 iter_set_sequence (iter, 0);
1153 iter_unrecurse (iter);
1154 iter_next (iter);
1155 goto next_body;
1156 }
1157
1158 _dbus_assert (iter->depth == (base_depth + 1));
1159
1160 iter_recurse (iter);
1161 _dbus_assert (iter->depth == (base_depth + 2));
1162 byte_seq = iter_get_sequence (iter);
1163 /* skip 4 bytes at a time */
1164 iter_next (iter);
1165 iter_next (iter);
1166 iter_next (iter);
1167 iter_next (iter);
1168 iter_unrecurse (iter);
1169
1170 _dbus_assert (_DBUS_ALIGN_VALUE (byte_seq, 4) == (unsigned) byte_seq);
1171 if (byte_seq >= (_dbus_string_get_length (data) - 4))
1172 {
1173 /* reset byte count */
1174 _dbus_assert (iter->depth == (base_depth + 1));
1175 iter_recurse (iter);
1176 _dbus_assert (iter->depth == (base_depth + 2));
1177 iter_set_sequence (iter, 0);
1178 iter_unrecurse (iter);
1179 _dbus_assert (iter->depth == (base_depth + 1));
1180 iter_next (iter);
1181 goto next_change;
1182 }
1183
1184 _dbus_assert (byte_seq <= (_dbus_string_get_length (data) - 4));
1185
1186 byte_order = _dbus_string_get_byte (data, BYTE_ORDER_OFFSET);
1187
1188 v_UINT32 = _dbus_marshal_read_uint32 (data, byte_seq, byte_order, NULL);
1189
1190 change = &uint32_changes[change_seq];
1191
1192 if (change->type == CHANGE_TYPE_ADJUST)
1193 {
1194 v_UINT32 += (int) change->value;
1195 }
1196 else
1197 {
1198 v_UINT32 = change->value;
1199 }
1200
1201#if 0
1202 printf ("body %d change %d pos %d ",
1203 body_seq, change_seq, byte_seq);
1204
1205 if (change->type == CHANGE_TYPE_ADJUST)
1206 printf ("adjust by %d", (int) change->value);
1207 else
1208 printf ("set to %u", change->value);
1209
1210 printf (" \t%u -> %u\n",
1211 _dbus_marshal_read_uint32 (data, byte_seq, byte_order, NULL),
1212 v_UINT32);
1213#endif
1214
1215 _dbus_marshal_set_uint32 (data, byte_seq, v_UINT32, byte_order);
1216 *expected_validity = DBUS_VALIDITY_UNKNOWN;
1217
1218 _dbus_assert (iter->depth == (base_depth + 1));
1219 iter_unrecurse (iter);
1220 _dbus_assert (iter->depth == (base_depth + 0));
1221
1222 return TRUE;
1223}
1224
1225typedef struct
1226{
1227 const char *name;
1228 DBusMessageGeneratorFunc func;
1229} DBusMessageGenerator;
1230
1231static const DBusMessageGenerator generators[] = {
1232 { "trivial example of each message type", generate_trivial },
1233 { "assorted arguments", generate_many_bodies },
1234 { "assorted special cases", generate_special },
1235 { "each uint32 modified", generate_uint32_changed },
1236 { "wrong body lengths", generate_wrong_length },
1237 { "each byte modified", generate_byte_changed },
1238#if 0
1239 /* This is really expensive and doesn't add too much coverage */
1240 { "change each typecode", generate_typecode_changed }
1241#endif
1242};
1243
1244void
1245_dbus_message_data_free (DBusMessageData *data)
1246{
1247 _dbus_string_free (&data->data);
1248}
1249
1250void
1251_dbus_message_data_iter_init (DBusMessageDataIter *iter)
1252{
1253 int i;
1254
1255 iter->depth = 0;
1256 i = 0;
1257 while (i < _DBUS_MESSAGE_DATA_MAX_NESTING)
1258 {
1259 iter->sequence_nos[i] = 0;
1260 ++i;
1261 }
1262 iter->count = 0;
1263}
1264
1266_dbus_message_data_iter_get_and_next (DBusMessageDataIter *iter,
1267 DBusMessageData *data)
1268{
1269 DBusMessageGeneratorFunc func;
1270 int generator;
1271
1272 restart:
1273 generator = iter_get_sequence (iter);
1274
1275 if (generator == _DBUS_N_ELEMENTS (generators))
1276 return FALSE;
1277
1278 iter_recurse (iter);
1279
1280 if (iter_first_in_series (iter))
1281 {
1282 printf (" testing message loading: %s ", generators[generator].name);
1283 fflush (stdout);
1284 }
1285
1286 func = generators[generator].func;
1287
1288 if (!_dbus_string_init (&data->data))
1290
1291 if ((*func)(iter, &data->data, &data->expected_validity))
1292 ;
1293 else
1294 {
1295 iter_set_sequence (iter, 0);
1296 iter_unrecurse (iter);
1297 iter_next (iter); /* next generator */
1298 _dbus_string_free (&data->data);
1299 printf ("%d test loads cumulative\n", iter->count);
1300 goto restart;
1301 }
1302 iter_unrecurse (iter);
1303
1304 iter->count += 1;
1305 return TRUE;
1306}
1307
1308#endif /* !DOXYGEN_SHOULD_SKIP_THIS */
1309
1310#endif /* DBUS_ENABLE_EMBEDDED_TESTS */
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
#define _DBUS_N_ELEMENTS(array)
Computes the number of elements in a fixed-size array using sizeof().
#define _DBUS_UINT32_MAX
Maximum value of type "uint32".
#define NULL
A null pointer, defined appropriately for C or C++.
#define TRUE
Expands to "1".
#define FALSE
Expands to "0".
DBusValidity
This is primarily used in unit testing, so we can verify that each invalid message is invalid for the...
#define BODY_LENGTH_OFFSET
Offset to body length from start of header.
dbus_bool_t _dbus_header_set_field_basic(DBusHeader *header, int field, int type, const void *value)
Sets the value of a field with basic type.
void _dbus_marshal_set_uint32(DBusString *str, int pos, dbus_uint32_t value, int byte_order)
Sets the 4 bytes at the given offset to a marshaled unsigned integer, replacing anything found there ...
char _dbus_header_get_byte_order(const DBusHeader *header)
Returns the header's byte order.
dbus_uint32_t _dbus_marshal_read_uint32(const DBusString *str, int pos, int byte_order, int *new_pos)
Convenience function to demarshal a 32 bit unsigned integer.
dbus_bool_t _dbus_header_delete_field(DBusHeader *header, int field)
Deletes a field, if it exists.
#define BYTE_ORDER_OFFSET
Offset to byte order from start of header.
#define FIELDS_ARRAY_LENGTH_OFFSET
Offset to fields array length from start of header.
dbus_bool_t _dbus_header_get_field_raw(DBusHeader *header, int field, const DBusString **str, int *pos)
Gets the raw marshaled data for a field.
#define TYPE_OFFSET
Offset to type from start of header.
@ DBUS_INVALID_TOO_MUCH_DATA
trailing junk makes it invalid
@ DBUS_VALID
the data is valid
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:702
#define dbus_new(type, count)
Safe macro for using dbus_malloc().
Definition: dbus-memory.h:57
void dbus_message_set_serial(DBusMessage *message, dbus_uint32_t serial)
Sets the serial number of a message.
Definition: dbus-message.c:277
void dbus_message_lock(DBusMessage *message)
Locks a message.
Definition: dbus-message.c:407
dbus_bool_t dbus_message_set_interface(DBusMessage *message, const char *iface)
Sets the interface this message is being sent to (for DBUS_MESSAGE_TYPE_METHOD_CALL) or the interface...
dbus_bool_t dbus_message_iter_append_basic(DBusMessageIter *iter, int type, const void *value)
Appends a basic-typed value to the message.
dbus_bool_t dbus_message_append_args(DBusMessage *message, int first_arg_type,...)
Appends fields to a message given a variable argument list.
DBusMessage * dbus_message_new_signal(const char *path, const char *iface, const char *name)
Constructs a new message representing a signal emission.
dbus_bool_t dbus_message_set_error_name(DBusMessage *message, const char *error_name)
Sets the name of the error (DBUS_MESSAGE_TYPE_ERROR).
dbus_bool_t dbus_message_iter_open_container(DBusMessageIter *iter, int type, const char *contained_signature, DBusMessageIter *sub)
Appends a container-typed value to the message.
DBusMessage * dbus_message_new_method_call(const char *destination, const char *path, const char *iface, const char *method)
Constructs a new message to invoke a method on a remote object.
dbus_bool_t dbus_message_set_path(DBusMessage *message, const char *object_path)
Sets the object path this message is being sent to (for DBUS_MESSAGE_TYPE_METHOD_CALL) or the one a s...
void dbus_message_unref(DBusMessage *message)
Decrements the reference count of a DBusMessage, freeing the message if the count reaches 0.
DBusMessage * dbus_message_new(int message_type)
Constructs a new message of the given message type.
dbus_bool_t dbus_message_set_reply_serial(DBusMessage *message, dbus_uint32_t reply_serial)
Sets the reply serial of a message (the serial of the message this is a reply to).
dbus_bool_t dbus_message_iter_close_container(DBusMessageIter *iter, DBusMessageIter *sub)
Closes a container-typed value appended to the message; may write out more information to the message...
void dbus_message_iter_init_append(DBusMessage *message, DBusMessageIter *iter)
Initializes a DBusMessageIter for appending arguments to the end of a message.
#define DBUS_HEADER_FIELD_REPLY_SERIAL
Header field code for a reply serial, used to match a DBUS_MESSAGE_TYPE_METHOD_RETURN message with th...
#define DBUS_TYPE_SIGNATURE
Type code marking a D-Bus type signature.
#define DBUS_MAXIMUM_MESSAGE_LENGTH
The maximum total message size including header and body; similar rationale to max array size.
#define DBUS_DICT_ENTRY_END_CHAR
Code marking the end of a dict entry type in a type signature.
#define DBUS_MESSAGE_TYPE_ERROR
Message type of an error reply message, see dbus_message_get_type()
#define DBUS_TYPE_OBJECT_PATH
Type code marking a D-Bus object path.
#define DBUS_TYPE_BYTE
Type code marking an 8-bit unsigned integer.
Definition: dbus-protocol.h:66
#define DBUS_HEADER_FIELD_SENDER
Header field code for the sender of a message; usually initialized by the message bus.
#define DBUS_HEADER_FIELD_SIGNATURE
Header field code for the type signature of a message.
#define DBUS_TYPE_INT16
Type code marking a 16-bit signed integer.
Definition: dbus-protocol.h:74
#define DBUS_MESSAGE_TYPE_METHOD_RETURN
Message type of a method return message, see dbus_message_get_type()
#define DBUS_TYPE_VARIANT
Type code marking a D-Bus variant type.
#define DBUS_TYPE_INT32
Type code marking a 32-bit signed integer.
Definition: dbus-protocol.h:82
#define DBUS_TYPE_UNIX_FD
Type code marking a unix file descriptor.
#define DBUS_TYPE_INT32_AS_STRING
DBUS_TYPE_INT32 as a string literal instead of a int literal
Definition: dbus-protocol.h:84
#define DBUS_TYPE_BOOLEAN
Type code marking a boolean.
Definition: dbus-protocol.h:70
#define DBUS_STRUCT_BEGIN_CHAR
Code marking the start of a struct type in a type signature.
#define DBUS_TYPE_STRING
Type code marking a UTF-8 encoded, nul-terminated Unicode string.
#define DBUS_TYPE_ARRAY
Type code marking a D-Bus array type.
#define DBUS_TYPE_INVALID
Type code that is never equal to a legitimate type code.
Definition: dbus-protocol.h:60
#define DBUS_MAXIMUM_TYPE_RECURSION_DEPTH
Depth of recursion in the type tree.
#define DBUS_TYPE_INT64
Type code marking a 64-bit signed integer.
Definition: dbus-protocol.h:90
#define DBUS_TYPE_DOUBLE
Type code marking an 8-byte double in IEEE 754 format.
Definition: dbus-protocol.h:98
#define DBUS_TYPE_UINT64
Type code marking a 64-bit unsigned integer.
Definition: dbus-protocol.h:94
#define DBUS_TYPE_VARIANT_AS_STRING
DBUS_TYPE_VARIANT as a string literal instead of a int literal
#define DBUS_MESSAGE_TYPE_INVALID
This value is never a valid message type, see dbus_message_get_type()
#define DBUS_DICT_ENTRY_BEGIN_CHAR
Code marking the start of a dict entry type in a type signature.
#define DBUS_TYPE_UINT16
Type code marking a 16-bit unsigned integer.
Definition: dbus-protocol.h:78
#define DBUS_STRUCT_END_CHAR
Code marking the end of a struct type in a type signature.
#define DBUS_TYPE_UINT32
Type code marking a 32-bit unsigned integer.
Definition: dbus-protocol.h:86
#define DBUS_MINIMUM_HEADER_SIZE
The smallest header size that can occur.
#define DBUS_PATH_LOCAL
The object path used in local/in-process-generated messages.
Definition: dbus-shared.h:82
#define DBUS_INTERFACE_LOCAL
This is a special interface whose methods can only be invoked by the local implementation (messages f...
Definition: dbus-shared.h:105
dbus_bool_t dbus_type_is_valid(int typecode)
Return TRUE if the argument is a valid typecode.
dbus_bool_t _dbus_string_set_length(DBusString *str, int length)
Sets the length of a string.
Definition: dbus-string.c:802
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:175
dbus_bool_t _dbus_string_copy(const DBusString *source, int start, DBusString *dest, int insert_at)
Like _dbus_string_move(), but does not delete the section of the source string that's copied to the d...
Definition: dbus-string.c:1283
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init().
Definition: dbus-string.c:259
void _dbus_string_shorten(DBusString *str, int length_to_remove)
Makes a string shorter by the given number of bytes.
Definition: dbus-string.c:780
dbus_bool_t _dbus_string_lengthen(DBusString *str, int additional_length)
Makes a string longer by the given number of bytes.
Definition: dbus-string.c:760
dbus_bool_t _dbus_string_move(DBusString *source, int start, DBusString *dest, int insert_at)
Moves the end of one string into another string.
Definition: dbus-string.c:1259
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:35
int dbus_int32_t
A 32-bit signed integer on all platforms.
unsigned int dbus_uint32_t
A 32-bit unsigned integer on all platforms.
DBusString data
Header network data, stored separately from body so we can independently realloc it.
DBusMessageIter struct; contains no public fields.
Definition: dbus-message.h:62
Internals of DBusMessage.
DBusHeader header
Header network data and associated cache.
DBusString body
Body network data.