D-Bus  1.12.28
dbus-message-util.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-message-util.c Would be in dbus-message.c, but only used by bus/tests
3  *
4  * Copyright (C) 2002, 2003, 2004, 2005 Red Hat Inc.
5  * Copyright (C) 2002, 2003 CodeFactory AB
6  *
7  * Licensed under the Academic Free License version 2.1
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  *
23  */
24 
25 #include <config.h>
26 #include "dbus-internals.h"
27 #include "dbus-test.h"
28 #include "dbus-message-private.h"
29 #include "dbus-marshal-recursive.h"
30 #include "dbus-string.h"
31 #ifdef HAVE_UNIX_FD_PASSING
32 #include "dbus-sysdeps-unix.h"
33 #endif
34 
35 #ifdef __linux__
36 /* Necessary for the Linux-specific fd leak checking code only */
37 #include <sys/types.h>
38 #include <dirent.h>
39 #include <stdlib.h>
40 #include <errno.h>
41 #endif
42 
54 unsigned int
56 {
57 #ifdef HAVE_UNIX_FD_PASSING
58  return message->n_unix_fds;
59 #else
60  return 0;
61 #endif
62 }
63 
64 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
77 static dbus_bool_t
78 dbus_message_iter_get_args (DBusMessageIter *iter,
79  DBusError *error,
80  int first_arg_type,
81  ...)
82 {
83  dbus_bool_t retval;
84  va_list var_args;
85 
86  _dbus_return_val_if_fail (iter != NULL, FALSE);
87  _dbus_return_val_if_error_is_set (error, FALSE);
88 
89  va_start (var_args, first_arg_type);
90  retval = _dbus_message_iter_get_args_valist (iter, error, first_arg_type, var_args);
91  va_end (var_args);
92 
93  return retval;
94 }
95 #endif /* DBUS_ENABLE_EMBEDDED_TESTS */
96 
99 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
100 #include "dbus-test.h"
101 #include "dbus-message-factory.h"
102 #include <stdio.h>
103 #include <stdlib.h>
104 
105 static int validities_seen[DBUS_VALIDITY_LAST + _DBUS_NEGATIVE_VALIDITY_COUNT];
106 
107 static void
108 reset_validities_seen (void)
109 {
110  int i;
111  i = 0;
112  while (i < _DBUS_N_ELEMENTS (validities_seen))
113  {
114  validities_seen[i] = 0;
115  ++i;
116  }
117 }
118 
119 static void
120 record_validity_seen (DBusValidity validity)
121 {
122  validities_seen[validity + _DBUS_NEGATIVE_VALIDITY_COUNT] += 1;
123 }
124 
125 static void
126 print_validities_seen (dbus_bool_t not_seen)
127 {
128  int i;
129  i = 0;
130  while (i < _DBUS_N_ELEMENTS (validities_seen))
131  {
132  if ((i - _DBUS_NEGATIVE_VALIDITY_COUNT) == DBUS_VALIDITY_UNKNOWN ||
133  (i - _DBUS_NEGATIVE_VALIDITY_COUNT) == DBUS_INVALID_FOR_UNKNOWN_REASON)
134  ;
135  else if ((not_seen && validities_seen[i] == 0) ||
136  (!not_seen && validities_seen[i] > 0))
137  printf ("validity %3d seen %d times\n",
138  i - _DBUS_NEGATIVE_VALIDITY_COUNT,
139  validities_seen[i]);
140  ++i;
141  }
142 }
143 
144 static void
145 check_memleaks (void)
146 {
147  dbus_shutdown ();
148 
149  if (_dbus_get_malloc_blocks_outstanding () != 0)
150  {
151  _dbus_warn ("%d dbus_malloc blocks were not freed in %s",
152  _dbus_get_malloc_blocks_outstanding (), __FILE__);
153  _dbus_assert_not_reached ("memleaks");
154  }
155 }
156 
157 #ifdef __linux__
158 struct DBusInitialFDs {
159  fd_set set;
160 };
161 #endif
162 
163 DBusInitialFDs *
164 _dbus_check_fdleaks_enter (void)
165 {
166 #ifdef __linux__
167  DIR *d;
168  DBusInitialFDs *fds;
169 
170  /* this is plain malloc so it won't interfere with leak checking */
171  fds = malloc (sizeof (DBusInitialFDs));
172  _dbus_assert (fds != NULL);
173 
174  /* This works on Linux only */
175 
176  if ((d = opendir ("/proc/self/fd")))
177  {
178  struct dirent *de;
179 
180  while ((de = readdir(d)))
181  {
182  long l;
183  char *e = NULL;
184  int fd;
185 
186  if (de->d_name[0] == '.')
187  continue;
188 
189  errno = 0;
190  l = strtol (de->d_name, &e, 10);
191  _dbus_assert (errno == 0 && e && !*e);
192 
193  fd = (int) l;
194 
195  if (fd < 3)
196  continue;
197 
198  if (fd == dirfd (d))
199  continue;
200 
201  if (fd >= FD_SETSIZE)
202  {
203  _dbus_verbose ("FD %d unexpectedly large; cannot track whether "
204  "it is leaked\n", fd);
205  continue;
206  }
207 
208  FD_SET (fd, &fds->set);
209  }
210 
211  closedir (d);
212  }
213 
214  return fds;
215 #else
216  return NULL;
217 #endif
218 }
219 
220 void
221 _dbus_check_fdleaks_leave (DBusInitialFDs *fds)
222 {
223 #ifdef __linux__
224  DIR *d;
225 
226  /* This works on Linux only */
227 
228  if ((d = opendir ("/proc/self/fd")))
229  {
230  struct dirent *de;
231 
232  while ((de = readdir(d)))
233  {
234  long l;
235  char *e = NULL;
236  int fd;
237 
238  if (de->d_name[0] == '.')
239  continue;
240 
241  errno = 0;
242  l = strtol (de->d_name, &e, 10);
243  _dbus_assert (errno == 0 && e && !*e);
244 
245  fd = (int) l;
246 
247  if (fd < 3)
248  continue;
249 
250  if (fd == dirfd (d))
251  continue;
252 
253  if (fd >= FD_SETSIZE)
254  {
255  _dbus_verbose ("FD %d unexpectedly large; cannot track whether "
256  "it is leaked\n", fd);
257  continue;
258  }
259 
260  if (FD_ISSET (fd, &fds->set))
261  continue;
262 
263  _dbus_warn ("file descriptor %i leaked in %s.", fd, __FILE__);
264  _dbus_assert_not_reached ("fdleaks");
265  }
266 
267  closedir (d);
268  }
269 
270  free (fds);
271 #else
272  _dbus_assert (fds == NULL);
273 #endif
274 }
275 
276 static dbus_bool_t
277 check_have_valid_message (DBusMessageLoader *loader)
278 {
279  DBusMessage *message;
280  dbus_bool_t retval;
281 
282  message = NULL;
283  retval = FALSE;
284 
286  {
287  _dbus_warn ("loader corrupted on message that was expected to be valid; invalid reason %d",
288  loader->corruption_reason);
289  goto failed;
290  }
291 
292  message = _dbus_message_loader_pop_message (loader);
293  if (message == NULL)
294  {
295  _dbus_warn ("didn't load message that was expected to be valid (message not popped)");
296  goto failed;
297  }
298 
299  if (_dbus_string_get_length (&loader->data) > 0)
300  {
301  _dbus_warn ("had leftover bytes from expected-to-be-valid single message");
302  goto failed;
303  }
304 
305 #if 0
306  /* FIXME */
307  /* Verify that we're able to properly deal with the message.
308  * For example, this would detect improper handling of messages
309  * in nonstandard byte order.
310  */
311  if (!check_message_handling (message))
312  goto failed;
313 #endif
314 
315  record_validity_seen (DBUS_VALID);
316 
317  retval = TRUE;
318 
319  failed:
320  if (message)
321  dbus_message_unref (message);
322 
323  return retval;
324 }
325 
326 static dbus_bool_t
327 check_invalid_message (DBusMessageLoader *loader,
328  DBusValidity expected_validity)
329 {
330  dbus_bool_t retval;
331 
332  retval = FALSE;
333 
335  {
336  _dbus_warn ("loader not corrupted on message that was expected to be invalid");
337  goto failed;
338  }
339 
340  record_validity_seen (loader->corruption_reason);
341 
342  if (expected_validity != DBUS_INVALID_FOR_UNKNOWN_REASON &&
343  loader->corruption_reason != expected_validity)
344  {
345  _dbus_warn ("expected message to be corrupted for reason %d and was corrupted for %d instead",
346  expected_validity, loader->corruption_reason);
347  goto failed;
348  }
349 
350  retval = TRUE;
351 
352  failed:
353  return retval;
354 }
355 
356 static dbus_bool_t
357 check_incomplete_message (DBusMessageLoader *loader)
358 {
359  DBusMessage *message;
360  dbus_bool_t retval;
361 
362  message = NULL;
363  retval = FALSE;
364 
366  {
367  _dbus_warn ("loader corrupted on message that was expected to be valid (but incomplete), corruption reason %d",
368  loader->corruption_reason);
369  goto failed;
370  }
371 
372  message = _dbus_message_loader_pop_message (loader);
373  if (message != NULL)
374  {
375  _dbus_warn ("loaded message that was expected to be incomplete");
376  goto failed;
377  }
378 
379  record_validity_seen (DBUS_VALID_BUT_INCOMPLETE);
380  retval = TRUE;
381 
382  failed:
383  if (message)
384  dbus_message_unref (message);
385  return retval;
386 }
387 
388 static dbus_bool_t
389 check_loader_results (DBusMessageLoader *loader,
390  DBusValidity expected_validity)
391 {
393  _dbus_assert_not_reached ("no memory to queue messages");
394 
395  if (expected_validity == DBUS_VALID)
396  return check_have_valid_message (loader);
397  else if (expected_validity == DBUS_VALID_BUT_INCOMPLETE)
398  return check_incomplete_message (loader);
399  else if (expected_validity == DBUS_VALIDITY_UNKNOWN)
400  {
401  /* here we just know we didn't segfault and that was the
402  * only test. Also, we record that we got coverage
403  * for the validity reason.
404  */
406  record_validity_seen (loader->corruption_reason);
407 
408  return TRUE;
409  }
410  else
411  return check_invalid_message (loader, expected_validity);
412 }
413 
422 dbus_internal_do_not_use_load_message_file (const DBusString *filename,
423  DBusString *data)
424 {
425  dbus_bool_t retval;
426  DBusError error = DBUS_ERROR_INIT;
427 
428  retval = FALSE;
429 
430  _dbus_verbose ("Loading raw %s\n", _dbus_string_get_const_data (filename));
431  if (!_dbus_file_get_contents (data, filename, &error))
432  {
433  _dbus_warn ("Could not load message file %s: %s",
434  _dbus_string_get_const_data (filename),
435  error.message);
436  dbus_error_free (&error);
437  goto failed;
438  }
439 
440  retval = TRUE;
441 
442  failed:
443 
444  return retval;
445 }
446 
456 dbus_internal_do_not_use_try_message_file (const DBusString *filename,
457  DBusValidity expected_validity)
458 {
459  DBusString data;
460  dbus_bool_t retval;
461 
462  retval = FALSE;
463 
464  if (!_dbus_string_init (&data))
465  _dbus_assert_not_reached ("could not allocate string");
466 
467  if (!dbus_internal_do_not_use_load_message_file (filename, &data))
468  goto failed;
469 
470  retval = dbus_internal_do_not_use_try_message_data (&data, expected_validity);
471 
472  failed:
473 
474  if (!retval)
475  {
476  if (_dbus_string_get_length (&data) > 0)
478  _dbus_string_get_length (&data));
479 
480  _dbus_warn ("Failed message loader test on %s",
481  _dbus_string_get_const_data (filename));
482  }
483 
484  _dbus_string_free (&data);
485 
486  return retval;
487 }
488 
498 dbus_internal_do_not_use_try_message_data (const DBusString *data,
499  DBusValidity expected_validity)
500 {
501  DBusMessageLoader *loader;
502  dbus_bool_t retval;
503  int len;
504  int i;
505 
506  loader = NULL;
507  retval = FALSE;
508 
509  /* Write the data one byte at a time */
510 
511  loader = _dbus_message_loader_new ();
512  if (loader == NULL)
513  goto failed;
514 
515  /* check some trivial loader functions */
516  _dbus_message_loader_ref (loader);
518 
519  len = _dbus_string_get_length (data);
520  for (i = 0; i < len; i++)
521  {
522  DBusString *buffer;
523 
524  _dbus_message_loader_get_buffer (loader, &buffer, NULL, NULL);
525  if (!_dbus_string_append_byte (buffer,
526  _dbus_string_get_byte (data, i)))
527  goto failed;
528  _dbus_message_loader_return_buffer (loader, buffer);
529  }
530 
531  if (!check_loader_results (loader, expected_validity))
532  goto failed;
533 
535  loader = NULL;
536 
537  /* Write the data all at once */
538 
539  loader = _dbus_message_loader_new ();
540  if (loader == NULL)
541  goto failed;
542 
543  {
544  DBusString *buffer;
545 
546  _dbus_message_loader_get_buffer (loader, &buffer, NULL, NULL);
547  if (!_dbus_string_copy (data, 0, buffer,
548  _dbus_string_get_length (buffer)))
549  goto failed;
550  _dbus_message_loader_return_buffer (loader, buffer);
551  }
552 
553  if (!check_loader_results (loader, expected_validity))
554  goto failed;
555 
557  loader = NULL;
558 
559  /* Write the data 2 bytes at a time */
560 
561  loader = _dbus_message_loader_new ();
562  if (loader == NULL)
563  goto failed;
564 
565  len = _dbus_string_get_length (data);
566  for (i = 0; i < len; i += 2)
567  {
568  DBusString *buffer;
569 
570  _dbus_message_loader_get_buffer (loader, &buffer, NULL, NULL);
571  if (!_dbus_string_append_byte (buffer,
572  _dbus_string_get_byte (data, i)))
573  goto failed;
574 
575  if ((i+1) < len)
576  {
577  if (!_dbus_string_append_byte (buffer,
578  _dbus_string_get_byte (data, i+1)))
579  goto failed;
580  }
581 
582  _dbus_message_loader_return_buffer (loader, buffer);
583  }
584 
585  if (!check_loader_results (loader, expected_validity))
586  goto failed;
587 
589  loader = NULL;
590 
591  retval = TRUE;
592 
593  failed:
594 
595  if (loader)
597 
598  return retval;
599 }
600 
601 static dbus_bool_t
602 process_test_subdir (const DBusString *test_base_dir,
603  const char *subdir,
604  DBusValidity expected_validity,
605  DBusForeachMessageFileFunc function,
606  void *user_data)
607 {
608  DBusString test_directory;
609  DBusString filename;
610  DBusDirIter *dir;
611  dbus_bool_t retval;
612  DBusError error = DBUS_ERROR_INIT;
613 
614  retval = FALSE;
615  dir = NULL;
616 
617  if (!_dbus_string_init (&test_directory))
618  _dbus_assert_not_reached ("didn't allocate test_directory");
619 
620  _dbus_string_init_const (&filename, subdir);
621 
622  if (!_dbus_string_copy (test_base_dir, 0,
623  &test_directory, 0))
624  _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
625 
626  if (!_dbus_concat_dir_and_file (&test_directory, &filename))
627  _dbus_assert_not_reached ("couldn't allocate full path");
628 
629  _dbus_string_free (&filename);
630  if (!_dbus_string_init (&filename))
631  _dbus_assert_not_reached ("didn't allocate filename string");
632 
633  dir = _dbus_directory_open (&test_directory, &error);
634  if (dir == NULL)
635  {
636  _dbus_warn ("Could not open %s: %s",
637  _dbus_string_get_const_data (&test_directory),
638  error.message);
639  dbus_error_free (&error);
640  goto failed;
641  }
642 
643  printf ("Testing %s:\n", subdir);
644 
645  next:
646  while (_dbus_directory_get_next_file (dir, &filename, &error))
647  {
648  DBusString full_path;
649 
650  if (!_dbus_string_init (&full_path))
651  _dbus_assert_not_reached ("couldn't init string");
652 
653  if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
654  _dbus_assert_not_reached ("couldn't copy dir to full_path");
655 
656  if (!_dbus_concat_dir_and_file (&full_path, &filename))
657  _dbus_assert_not_reached ("couldn't concat file to dir");
658 
659  if (_dbus_string_ends_with_c_str (&filename, ".message-raw"))
660  ;
661  else
662  {
663  if (_dbus_string_ends_with_c_str (&filename, ".message"))
664  {
665  printf ("SKIP: Could not load %s, message builder language no longer supported\n",
666  _dbus_string_get_const_data (&filename));
667  }
668 
669  _dbus_verbose ("Skipping non-.message file %s\n",
670  _dbus_string_get_const_data (&filename));
671  _dbus_string_free (&full_path);
672  goto next;
673  }
674 
675  printf (" %s\n",
676  _dbus_string_get_const_data (&filename));
677 
678  if (! (*function) (&full_path,
679  expected_validity, user_data))
680  {
681  _dbus_string_free (&full_path);
682  goto failed;
683  }
684  else
685  _dbus_string_free (&full_path);
686  }
687 
688  if (dbus_error_is_set (&error))
689  {
690  _dbus_warn ("Could not get next file in %s: %s",
691  _dbus_string_get_const_data (&test_directory),
692  error.message);
693  dbus_error_free (&error);
694  goto failed;
695  }
696 
697  retval = TRUE;
698 
699  failed:
700 
701  if (dir)
702  _dbus_directory_close (dir);
703  _dbus_string_free (&test_directory);
704  _dbus_string_free (&filename);
705 
706  return retval;
707 }
708 
719 dbus_internal_do_not_use_foreach_message_file (const char *test_data_dir,
720  DBusForeachMessageFileFunc func,
721  void *user_data)
722 {
723  DBusString test_directory;
724  dbus_bool_t retval;
725 
726  retval = FALSE;
727 
728  _dbus_string_init_const (&test_directory, test_data_dir);
729 
730  if (!process_test_subdir (&test_directory, "valid-messages",
731  DBUS_VALID, func, user_data))
732  goto failed;
733 
734  check_memleaks ();
735 
736  if (!process_test_subdir (&test_directory, "invalid-messages",
737  DBUS_INVALID_FOR_UNKNOWN_REASON, func, user_data))
738  goto failed;
739 
740  check_memleaks ();
741 
742  if (!process_test_subdir (&test_directory, "incomplete-messages",
743  DBUS_VALID_BUT_INCOMPLETE, func, user_data))
744  goto failed;
745 
746  check_memleaks ();
747 
748  retval = TRUE;
749 
750  failed:
751 
752  _dbus_string_free (&test_directory);
753 
754  return retval;
755 }
756 
757 #if 0
758 #define GET_AND_CHECK(iter, typename, literal) \
759  do { \
760  if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_##typename) \
761  _dbus_assert_not_reached ("got wrong argument type from message iter"); \
762  dbus_message_iter_get_basic (&iter, &v_##typename); \
763  if (v_##typename != literal) \
764  _dbus_assert_not_reached ("got wrong value from message iter"); \
765  } while (0)
766 
767 #define GET_AND_CHECK_STRCMP(iter, typename, literal) \
768  do { \
769  if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_##typename) \
770  _dbus_assert_not_reached ("got wrong argument type from message iter"); \
771  dbus_message_iter_get_basic (&iter, &v_##typename); \
772  if (strcmp (v_##typename, literal) != 0) \
773  _dbus_assert_not_reached ("got wrong value from message iter"); \
774  } while (0)
775 
776 #define GET_AND_CHECK_AND_NEXT(iter, typename, literal) \
777  do { \
778  GET_AND_CHECK(iter, typename, literal); \
779  if (!dbus_message_iter_next (&iter)) \
780  _dbus_assert_not_reached ("failed to move iter to next"); \
781  } while (0)
782 
783 #define GET_AND_CHECK_STRCMP_AND_NEXT(iter, typename, literal) \
784  do { \
785  GET_AND_CHECK_STRCMP(iter, typename, literal); \
786  if (!dbus_message_iter_next (&iter)) \
787  _dbus_assert_not_reached ("failed to move iter to next"); \
788  } while (0)
789 
790 static void
791 message_iter_test (DBusMessage *message)
792 {
793  DBusMessageIter iter, array, array2;
794  const char *v_STRING;
795  double v_DOUBLE;
796  dbus_int16_t v_INT16;
797  dbus_uint16_t v_UINT16;
798  dbus_int32_t v_INT32;
799  dbus_uint32_t v_UINT32;
800  dbus_int64_t v_INT64;
801  dbus_uint64_t v_UINT64;
802  unsigned char v_BYTE;
803  dbus_bool_t v_BOOLEAN;
804 
805  const dbus_int32_t *our_int_array;
806  int len;
807 
808  dbus_message_iter_init (message, &iter);
809 
810  GET_AND_CHECK_STRCMP_AND_NEXT (iter, STRING, "Test string");
811  GET_AND_CHECK_AND_NEXT (iter, INT32, -0x12345678);
812  GET_AND_CHECK_AND_NEXT (iter, UINT32, 0xedd1e);
813  GET_AND_CHECK_AND_NEXT (iter, DOUBLE, 3.14159);
814 
816  _dbus_assert_not_reached ("Argument type not an array");
817 
819  _dbus_assert_not_reached ("Array type not double");
820 
821  dbus_message_iter_recurse (&iter, &array);
822 
823  GET_AND_CHECK_AND_NEXT (array, DOUBLE, 1.5);
824  GET_AND_CHECK (array, DOUBLE, 2.5);
825 
826  if (dbus_message_iter_next (&array))
827  _dbus_assert_not_reached ("Didn't reach end of array");
828 
829  if (!dbus_message_iter_next (&iter))
830  _dbus_assert_not_reached ("Reached end of arguments");
831 
832  GET_AND_CHECK_AND_NEXT (iter, BYTE, 0xF0);
833 
835  _dbus_assert_not_reached ("no array");
836 
838  _dbus_assert_not_reached ("Array type not int32");
839 
840  /* Empty array */
841  dbus_message_iter_recurse (&iter, &array);
842 
843  if (dbus_message_iter_next (&array))
844  _dbus_assert_not_reached ("Didn't reach end of array");
845 
846  if (!dbus_message_iter_next (&iter))
847  _dbus_assert_not_reached ("Reached end of arguments");
848 
849  GET_AND_CHECK (iter, BYTE, 0xF0);
850 
851  if (dbus_message_iter_next (&iter))
852  _dbus_assert_not_reached ("Didn't reach end of arguments");
853 }
854 #endif
855 
856 static void
857 verify_test_message (DBusMessage *message)
858 {
859  DBusMessageIter iter;
860  DBusError error = DBUS_ERROR_INIT;
861  dbus_int16_t our_int16;
862  dbus_uint16_t our_uint16;
863  dbus_int32_t our_int;
864  dbus_uint32_t our_uint;
865  const char *our_str;
866  double our_double;
867  double v_DOUBLE;
868  dbus_bool_t our_bool;
869  unsigned char our_byte_1, our_byte_2;
870  const dbus_uint32_t *our_uint32_array = (void*)0xdeadbeef;
871  int our_uint32_array_len;
872  dbus_int32_t *our_int32_array = (void*)0xdeadbeef;
873  int our_int32_array_len;
874  dbus_int64_t our_int64;
875  dbus_uint64_t our_uint64;
876  dbus_int64_t *our_uint64_array = (void*)0xdeadbeef;
877  int our_uint64_array_len;
878  const dbus_int64_t *our_int64_array = (void*)0xdeadbeef;
879  int our_int64_array_len;
880  const double *our_double_array = (void*)0xdeadbeef;
881  int our_double_array_len;
882  const unsigned char *our_byte_array = (void*)0xdeadbeef;
883  int our_byte_array_len;
884  const dbus_bool_t *our_boolean_array = (void*)0xdeadbeef;
885  int our_boolean_array_len;
886  char **our_string_array;
887  int our_string_array_len;
888 
889  dbus_message_iter_init (message, &iter);
890 
891  if (!dbus_message_iter_get_args (&iter, &error,
892  DBUS_TYPE_INT16, &our_int16,
893  DBUS_TYPE_UINT16, &our_uint16,
894  DBUS_TYPE_INT32, &our_int,
895  DBUS_TYPE_UINT32, &our_uint,
896  DBUS_TYPE_INT64, &our_int64,
897  DBUS_TYPE_UINT64, &our_uint64,
898  DBUS_TYPE_STRING, &our_str,
899  DBUS_TYPE_DOUBLE, &our_double,
900  DBUS_TYPE_BOOLEAN, &our_bool,
901  DBUS_TYPE_BYTE, &our_byte_1,
902  DBUS_TYPE_BYTE, &our_byte_2,
904  &our_uint32_array, &our_uint32_array_len,
906  &our_int32_array, &our_int32_array_len,
908  &our_uint64_array, &our_uint64_array_len,
910  &our_int64_array, &our_int64_array_len,
912  &our_double_array, &our_double_array_len,
914  &our_byte_array, &our_byte_array_len,
916  &our_boolean_array, &our_boolean_array_len,
918  &our_string_array, &our_string_array_len,
919  0))
920  {
921  _dbus_warn ("error: %s - %s", error.name,
922  (error.message != NULL) ? error.message : "no message");
923  _dbus_assert_not_reached ("Could not get arguments");
924  }
925 
926  if (our_int16 != -0x123)
927  _dbus_assert_not_reached ("16-bit integers differ!");
928 
929  if (our_uint16 != 0x123)
930  _dbus_assert_not_reached ("16-bit uints differ!");
931 
932  if (our_int != -0x12345678)
933  _dbus_assert_not_reached ("integers differ!");
934 
935  if (our_uint != 0x12300042)
936  _dbus_assert_not_reached ("uints differ!");
937 
938  if (our_int64 != DBUS_INT64_CONSTANT (-0x123456789abcd))
939  _dbus_assert_not_reached ("64-bit integers differ!");
940  if (our_uint64 != DBUS_UINT64_CONSTANT (0x123456789abcd))
941  _dbus_assert_not_reached ("64-bit unsigned integers differ!");
942 
943  v_DOUBLE = 3.14159;
944  if (! _DBUS_DOUBLES_BITWISE_EQUAL (our_double, v_DOUBLE))
945  _dbus_assert_not_reached ("doubles differ!");
946 
947  if (strcmp (our_str, "Test string") != 0)
948  _dbus_assert_not_reached ("strings differ!");
949 
950  if (!our_bool)
951  _dbus_assert_not_reached ("booleans differ");
952 
953  if (our_byte_1 != 42)
954  _dbus_assert_not_reached ("bytes differ!");
955 
956  if (our_byte_2 != 24)
957  _dbus_assert_not_reached ("bytes differ!");
958 
959  if (our_uint32_array_len != 4 ||
960  our_uint32_array[0] != 0x12345678 ||
961  our_uint32_array[1] != 0x23456781 ||
962  our_uint32_array[2] != 0x34567812 ||
963  our_uint32_array[3] != 0x45678123)
964  _dbus_assert_not_reached ("uint array differs");
965 
966  if (our_int32_array_len != 4 ||
967  our_int32_array[0] != 0x12345678 ||
968  our_int32_array[1] != -0x23456781 ||
969  our_int32_array[2] != 0x34567812 ||
970  our_int32_array[3] != -0x45678123)
971  _dbus_assert_not_reached ("int array differs");
972 
973  if (our_uint64_array_len != 4 ||
974  our_uint64_array[0] != 0x12345678 ||
975  our_uint64_array[1] != 0x23456781 ||
976  our_uint64_array[2] != 0x34567812 ||
977  our_uint64_array[3] != 0x45678123)
978  _dbus_assert_not_reached ("uint64 array differs");
979 
980  if (our_int64_array_len != 4 ||
981  our_int64_array[0] != 0x12345678 ||
982  our_int64_array[1] != -0x23456781 ||
983  our_int64_array[2] != 0x34567812 ||
984  our_int64_array[3] != -0x45678123)
985  _dbus_assert_not_reached ("int64 array differs");
986 
987  if (our_double_array_len != 3)
988  _dbus_assert_not_reached ("double array had wrong length");
989 
990  /* On all IEEE machines (i.e. everything sane) exact equality
991  * should be preserved over the wire
992  */
993  v_DOUBLE = 0.1234;
994  if (! _DBUS_DOUBLES_BITWISE_EQUAL (our_double_array[0], v_DOUBLE))
995  _dbus_assert_not_reached ("double array had wrong values");
996  v_DOUBLE = 9876.54321;
997  if (! _DBUS_DOUBLES_BITWISE_EQUAL (our_double_array[1], v_DOUBLE))
998  _dbus_assert_not_reached ("double array had wrong values");
999  v_DOUBLE = -300.0;
1000  if (! _DBUS_DOUBLES_BITWISE_EQUAL (our_double_array[2], v_DOUBLE))
1001  _dbus_assert_not_reached ("double array had wrong values");
1002 
1003  if (our_byte_array_len != 4)
1004  _dbus_assert_not_reached ("byte array had wrong length");
1005 
1006  if (our_byte_array[0] != 'a' ||
1007  our_byte_array[1] != 'b' ||
1008  our_byte_array[2] != 'c' ||
1009  our_byte_array[3] != 234)
1010  _dbus_assert_not_reached ("byte array had wrong values");
1011 
1012  if (our_boolean_array_len != 5)
1013  _dbus_assert_not_reached ("bool array had wrong length");
1014 
1015  if (our_boolean_array[0] != TRUE ||
1016  our_boolean_array[1] != FALSE ||
1017  our_boolean_array[2] != TRUE ||
1018  our_boolean_array[3] != TRUE ||
1019  our_boolean_array[4] != FALSE)
1020  _dbus_assert_not_reached ("bool array had wrong values");
1021 
1022  if (our_string_array_len != 4)
1023  _dbus_assert_not_reached ("string array was wrong length");
1024 
1025  if (strcmp (our_string_array[0], "Foo") != 0 ||
1026  strcmp (our_string_array[1], "bar") != 0 ||
1027  strcmp (our_string_array[2], "") != 0 ||
1028  strcmp (our_string_array[3], "woo woo woo woo") != 0)
1029  _dbus_assert_not_reached ("string array had wrong values");
1030 
1031  dbus_free_string_array (our_string_array);
1032 
1033  if (dbus_message_iter_next (&iter))
1034  _dbus_assert_not_reached ("Didn't reach end of arguments");
1035 }
1036 
1037 static void
1038 verify_test_message_args_ignored (DBusMessage *message)
1039 {
1040  DBusMessageIter iter;
1041  DBusError error = DBUS_ERROR_INIT;
1042  dbus_uint32_t our_uint;
1043  DBusInitialFDs *initial_fds;
1044 
1045  initial_fds = _dbus_check_fdleaks_enter ();
1046 
1047  /* parse with empty signature: "" */
1048  dbus_message_iter_init (message, &iter);
1049  if (!dbus_message_iter_get_args (&iter, &error,
1051  {
1052  _dbus_warn ("error: %s - %s", error.name,
1053  (error.message != NULL) ? error.message : "no message");
1054  }
1055  else
1056  {
1057  _dbus_assert (!dbus_error_is_set (&error));
1058  _dbus_verbose ("arguments ignored.\n");
1059  }
1060 
1061  /* parse with shorter signature: "u" */
1062  dbus_message_iter_init (message, &iter);
1063  if (!dbus_message_iter_get_args (&iter, &error,
1064  DBUS_TYPE_UINT32, &our_uint,
1066  {
1067  _dbus_warn ("error: %s - %s", error.name,
1068  (error.message != NULL) ? error.message : "no message");
1069  }
1070  else
1071  {
1072  _dbus_assert (!dbus_error_is_set (&error));
1073  _dbus_verbose ("arguments ignored.\n");
1074  }
1075 
1076  _dbus_check_fdleaks_leave (initial_fds);
1077 }
1078 
1079 static void
1080 verify_test_message_memleak (DBusMessage *message)
1081 {
1082  DBusMessageIter iter;
1083  DBusError error = DBUS_ERROR_INIT;
1084  dbus_uint32_t our_uint1;
1085  dbus_uint32_t our_uint2;
1086  dbus_uint32_t our_uint3;
1087  char **our_string_array1;
1088  int our_string_array_len1;
1089  char **our_string_array2;
1090  int our_string_array_len2;
1091 #ifdef HAVE_UNIX_FD_PASSING
1092  int our_unix_fd1;
1093  int our_unix_fd2;
1094 #endif
1095  DBusInitialFDs *initial_fds;
1096 
1097  initial_fds = _dbus_check_fdleaks_enter ();
1098 
1099  /* parse with wrong signature: "uashuu" */
1100  dbus_error_free (&error);
1101  dbus_message_iter_init (message, &iter);
1102  if (!dbus_message_iter_get_args (&iter, &error,
1103  DBUS_TYPE_UINT32, &our_uint1,
1105  &our_string_array1, &our_string_array_len1,
1106 #ifdef HAVE_UNIX_FD_PASSING
1107  DBUS_TYPE_UNIX_FD, &our_unix_fd1,
1108 #endif
1109  DBUS_TYPE_UINT32, &our_uint2,
1110  DBUS_TYPE_UINT32, &our_uint3,
1112  {
1113  _dbus_verbose ("expected error: %s - %s\n", error.name,
1114  (error.message != NULL) ? error.message : "no message");
1115  /* ensure array of string and unix fd not leaked */
1116  _dbus_assert (our_string_array1 == NULL);
1117 #ifdef HAVE_UNIX_FD_PASSING
1118  _dbus_assert (our_unix_fd1 == -1);
1119 #endif
1120  }
1121  else
1122  {
1123  _dbus_warn ("error: parse with wrong signature: 'uashuu'.");
1124  }
1125 
1126  /* parse with wrong signature: "uashuashu" */
1127  dbus_message_iter_init (message, &iter);
1128  dbus_error_free (&error);
1129  if (!dbus_message_iter_get_args (&iter, &error,
1130  DBUS_TYPE_UINT32, &our_uint1,
1132  &our_string_array1, &our_string_array_len1,
1133 #ifdef HAVE_UNIX_FD_PASSING
1134  DBUS_TYPE_UNIX_FD, &our_unix_fd1,
1135 #endif
1136  DBUS_TYPE_UINT32, &our_uint2,
1138  &our_string_array2, &our_string_array_len2,
1139 #ifdef HAVE_UNIX_FD_PASSING
1140  DBUS_TYPE_UNIX_FD, &our_unix_fd2,
1141 #endif
1142  DBUS_TYPE_UINT32, &our_uint3,
1144  {
1145  _dbus_verbose ("expected error: %s - %s\n", error.name,
1146  (error.message != NULL) ? error.message : "no message");
1147  /* ensure array of string and unix fd not leaked */
1148  _dbus_assert (our_string_array1 == NULL);
1149  _dbus_assert (our_string_array2 == NULL);
1150 #ifdef HAVE_UNIX_FD_PASSING
1151  _dbus_assert (our_unix_fd1 == -1);
1152  _dbus_assert (our_unix_fd2 == -1);
1153 #endif
1154  }
1155  else
1156  {
1157  _dbus_warn ("error: parse with wrong signature: 'uashuashu'.");
1158  }
1159 
1160  /* parse with correct signature: "uashuash" */
1161  dbus_message_iter_init (message, &iter);
1162  dbus_error_free (&error);
1163  if (!dbus_message_iter_get_args (&iter, &error,
1164  DBUS_TYPE_UINT32, &our_uint1,
1166  &our_string_array1, &our_string_array_len1,
1167 #ifdef HAVE_UNIX_FD_PASSING
1168  DBUS_TYPE_UNIX_FD, &our_unix_fd1,
1169 #endif
1170  DBUS_TYPE_UINT32, &our_uint2,
1172  &our_string_array2, &our_string_array_len2,
1173 #ifdef HAVE_UNIX_FD_PASSING
1174  DBUS_TYPE_UNIX_FD, &our_unix_fd2,
1175 #endif
1177  {
1178  _dbus_warn ("error: %s - %s", error.name,
1179  (error.message != NULL) ? error.message : "no message");
1180  _dbus_assert_not_reached ("Could not get arguments");
1181  }
1182  else
1183  {
1184  dbus_free_string_array (our_string_array1);
1185  dbus_free_string_array (our_string_array2);
1186 #ifdef HAVE_UNIX_FD_PASSING
1187  _dbus_close (our_unix_fd1, &error);
1188  _dbus_close (our_unix_fd2, &error);
1189 #endif
1190  }
1191  _dbus_check_fdleaks_leave (initial_fds);
1192 }
1193 
1201 _dbus_message_test (const char *test_data_dir)
1202 {
1203  DBusMessage *message, *message_without_unix_fds;
1204  DBusMessageLoader *loader;
1205  int i;
1206  const char *data;
1207  DBusMessage *copy;
1208  const char *name1;
1209  const char *name2;
1210  const dbus_uint32_t our_uint32_array[] =
1211  { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
1212  const dbus_int32_t our_int32_array[] =
1213  { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
1214  const dbus_uint32_t *v_ARRAY_UINT32 = our_uint32_array;
1215  const dbus_int32_t *v_ARRAY_INT32 = our_int32_array;
1216  const dbus_uint64_t our_uint64_array[] =
1217  { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
1218  const dbus_int64_t our_int64_array[] =
1219  { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
1220  const dbus_uint64_t *v_ARRAY_UINT64 = our_uint64_array;
1221  const dbus_int64_t *v_ARRAY_INT64 = our_int64_array;
1222  const char *our_string_array[] = { "Foo", "bar", "", "woo woo woo woo" };
1223  const char *our_string_array1[] = { "foo", "Bar", "", "Woo woo Woo woo" };
1224  const char **v_ARRAY_STRING = our_string_array;
1225  const char **v1_ARRAY_STRING = our_string_array1;
1226  const double our_double_array[] = { 0.1234, 9876.54321, -300.0 };
1227  const double *v_ARRAY_DOUBLE = our_double_array;
1228  const unsigned char our_byte_array[] = { 'a', 'b', 'c', 234 };
1229  const unsigned char *v_ARRAY_BYTE = our_byte_array;
1230  const dbus_bool_t our_boolean_array[] = { TRUE, FALSE, TRUE, TRUE, FALSE };
1231  const dbus_bool_t *v_ARRAY_BOOLEAN = our_boolean_array;
1232  char sig[64];
1233  const char *s;
1234  const char *v_STRING;
1235  double v_DOUBLE;
1236  dbus_int16_t v_INT16;
1237  dbus_uint16_t v_UINT16;
1238  dbus_int32_t v_INT32;
1239  dbus_uint32_t v_UINT32;
1240  dbus_uint32_t v1_UINT32;
1241  dbus_int64_t v_INT64;
1242  dbus_uint64_t v_UINT64;
1243  unsigned char v_BYTE;
1244  unsigned char v2_BYTE;
1245  dbus_bool_t v_BOOLEAN;
1246  DBusMessageIter iter, array_iter, struct_iter;
1247 #ifdef HAVE_UNIX_FD_PASSING
1248  int v_UNIX_FD;
1249  int v1_UNIX_FD;
1250 #endif
1251  char **decomposed;
1252  DBusInitialFDs *initial_fds;
1253  dbus_bool_t ok;
1254  char basic_types[] = DBUS_TYPE_BYTE_AS_STRING \
1264 
1265  initial_fds = _dbus_check_fdleaks_enter ();
1266 
1267  message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
1268  "/org/freedesktop/TestPath",
1269  "Foo.TestInterface",
1270  "TestMethod");
1271  _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
1272  _dbus_assert (dbus_message_is_method_call (message, "Foo.TestInterface",
1273  "TestMethod"));
1274  _dbus_assert (strcmp (dbus_message_get_path (message),
1275  "/org/freedesktop/TestPath") == 0);
1276  dbus_message_set_serial (message, 1234);
1277 
1278  /* string length including nul byte not a multiple of 4 */
1279  if (!dbus_message_set_sender (message, "org.foo.bar1"))
1280  _dbus_assert_not_reached ("out of memory");
1281 
1282  _dbus_assert (dbus_message_has_sender (message, "org.foo.bar1"));
1283  dbus_message_set_reply_serial (message, 5678);
1284 
1286  _dbus_string_get_length (&message->header.data));
1287  _dbus_verbose_bytes_of_string (&message->body, 0,
1288  _dbus_string_get_length (&message->body));
1289 
1290  if (!dbus_message_set_sender (message, NULL))
1291  _dbus_assert_not_reached ("out of memory");
1292 
1293 
1295  _dbus_string_get_length (&message->header.data));
1296  _dbus_verbose_bytes_of_string (&message->body, 0,
1297  _dbus_string_get_length (&message->body));
1298 
1299 
1300  _dbus_assert (!dbus_message_has_sender (message, "org.foo.bar1"));
1301  _dbus_assert (dbus_message_get_serial (message) == 1234);
1302  _dbus_assert (dbus_message_get_reply_serial (message) == 5678);
1303  _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
1304 
1306  dbus_message_set_no_reply (message, TRUE);
1308  dbus_message_set_no_reply (message, FALSE);
1310 
1311  /* Set/get some header fields */
1312 
1313  if (!dbus_message_set_path (message, "/foo"))
1314  _dbus_assert_not_reached ("out of memory");
1315  _dbus_assert (strcmp (dbus_message_get_path (message),
1316  "/foo") == 0);
1317 
1318  if (!dbus_message_set_interface (message, "org.Foo"))
1319  _dbus_assert_not_reached ("out of memory");
1320  _dbus_assert (strcmp (dbus_message_get_interface (message),
1321  "org.Foo") == 0);
1322 
1323  if (!dbus_message_set_member (message, "Bar"))
1324  _dbus_assert_not_reached ("out of memory");
1325  _dbus_assert (strcmp (dbus_message_get_member (message),
1326  "Bar") == 0);
1327 
1328  /* Set/get them with longer values */
1329  if (!dbus_message_set_path (message, "/foo/bar"))
1330  _dbus_assert_not_reached ("out of memory");
1331  _dbus_assert (strcmp (dbus_message_get_path (message),
1332  "/foo/bar") == 0);
1333 
1334  if (!dbus_message_set_interface (message, "org.Foo.Bar"))
1335  _dbus_assert_not_reached ("out of memory");
1336  _dbus_assert (strcmp (dbus_message_get_interface (message),
1337  "org.Foo.Bar") == 0);
1338 
1339  if (!dbus_message_set_member (message, "BarFoo"))
1340  _dbus_assert_not_reached ("out of memory");
1341  _dbus_assert (strcmp (dbus_message_get_member (message),
1342  "BarFoo") == 0);
1343 
1344  /* Realloc shorter again */
1345 
1346  if (!dbus_message_set_path (message, "/foo"))
1347  _dbus_assert_not_reached ("out of memory");
1348  _dbus_assert (strcmp (dbus_message_get_path (message),
1349  "/foo") == 0);
1350 
1351  if (!dbus_message_set_interface (message, "org.Foo"))
1352  _dbus_assert_not_reached ("out of memory");
1353  _dbus_assert (strcmp (dbus_message_get_interface (message),
1354  "org.Foo") == 0);
1355 
1356  if (!dbus_message_set_member (message, "Bar"))
1357  _dbus_assert_not_reached ("out of memory");
1358  _dbus_assert (strcmp (dbus_message_get_member (message),
1359  "Bar") == 0);
1360 
1361  /* Path decomposing */
1362  dbus_message_set_path (message, NULL);
1363  dbus_message_get_path_decomposed (message, &decomposed);
1364  _dbus_assert (decomposed == NULL);
1365  dbus_free_string_array (decomposed);
1366 
1367  dbus_message_set_path (message, "/");
1368  dbus_message_get_path_decomposed (message, &decomposed);
1369  _dbus_assert (decomposed != NULL);
1370  _dbus_assert (decomposed[0] == NULL);
1371  dbus_free_string_array (decomposed);
1372 
1373  dbus_message_set_path (message, "/a/b");
1374  dbus_message_get_path_decomposed (message, &decomposed);
1375  _dbus_assert (decomposed != NULL);
1376  _dbus_assert (strcmp (decomposed[0], "a") == 0);
1377  _dbus_assert (strcmp (decomposed[1], "b") == 0);
1378  _dbus_assert (decomposed[2] == NULL);
1379  dbus_free_string_array (decomposed);
1380 
1381 1376    _dbus_assert (decomposed != Definition: dbus-con5603assert (decomposed[2] == NULL); (decomposed[2] ==