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