D-Bus  1.4.10
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_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
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
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
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
68 iter_unrecurse (DBusMessageDataIter *iter)
69 {
70  iter->depth -= 1;
71  _dbus_assert (iter->depth >= 0);
72 }
73 
74 static void
75 iter_next (DBusMessageDataIter *iter)
76 {
77  iter->sequence_nos[iter->depth] += 1;
78 }
79 
80 static dbus_bool_t
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
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
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:
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:
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,
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
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,
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 
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
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
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
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
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*
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*
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*
308 simple_method_return (void)
309 {
310  DBusMessage *message;
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*
321 simple_error (void)
322 {
323  DBusMessage *message;
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*
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  {
362  i == (levels - 1) ?
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
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 
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,
408  _dbus_assert_not_reached ("oom");
409 
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,
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,
446  &v_STRING))
447  _dbus_assert_not_reached ("oom");
448 
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,
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,
491  &v_STRING))
492  _dbus_assert_not_reached ("oom");
493 
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,
509  _dbus_assert_not_reached ("oom");
510 
513  NULL, &pos);
514  generate_from_message (data, expected_validity, message);
515 
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,
528  _dbus_assert_not_reached ("oom");
529 
532  NULL, &pos);
533  generate_from_message (data, expected_validity, message);
534 
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,
547  _dbus_assert_not_reached ("oom");
548 
551  NULL, &pos);
552  generate_from_message (data, expected_validity, message);
553 
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 
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 
585  message->byte_order);
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,
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 
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 
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,
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,
715  &v_STRING))
716  _dbus_assert_not_reached ("oom");
717 
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,
733  _dbus_assert_not_reached ("oom");
734 
737  NULL, &pos);
738  generate_from_message (data, expected_validity, message);
739 
740  _dbus_string_set_byte (data, pos + 1, DBUS_TYPE_ARRAY);
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,
753  _dbus_assert_not_reached ("oom");
754 
757  NULL, &pos);
758  generate_from_message (data, expected_validity, message);
759 
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,
772  _dbus_assert_not_reached ("oom");
773 
776  NULL, &pos);
777  generate_from_message (data, expected_validity, message);
778 
779  _dbus_string_set_byte (data, pos + 1, DBUS_TYPE_ARRAY);
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
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)
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 
866 
867  byte_order = _dbus_string_get_byte (data, BYTE_ORDER_OFFSET);
868  old_body_len = _dbus_marshal_read_uint32 (data,
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 
885  new_body_len,
886  byte_order);
887  }
888 
889  return TRUE;
890 }
891 
892 static dbus_bool_t
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
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[] = {
1018  255 /* random invalid typecode */
1019 };
1020 
1021 static dbus_bool_t
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
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
1229 _dbus_message_data_free (DBusMessageData *data)
1230 {
1231  _dbus_string_free (&data->data);
1232 }
1233 
1234 void
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 
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 */