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