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