D-Bus  1.8.16
dbus-marshal-validate-util.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-marshal-validate-util.c Would be in dbus-marshal-validate.c, but only used by tests/bus
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 
24 #include <config.h>
25 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
26 
27 #ifndef DOXYGEN_SHOULD_SKIP_THIS
28 
29 #include "dbus-internals.h"
30 #include "dbus-marshal-validate.h"
31 #include "dbus-marshal-recursive.h"
32 
33 #include "dbus-test.h"
34 #include <stdio.h>
35 
36 typedef struct
37 {
38  const char *data;
39  DBusValidity expected;
40 } ValidityTest;
41 
42 static void
43 run_validity_tests (const ValidityTest *tests,
44  int n_tests,
45  DBusValidity (* func) (const DBusString*,int,int))
46 {
47  int i;
48 
49  for (i = 0; i < n_tests; i++)
50  {
51  DBusString str;
52  DBusValidity v;
53 
54  _dbus_string_init_const (&str, tests[i].data);
55 
56  v = (*func) (&str, 0, _dbus_string_get_length (&str));
57 
58  if (v != tests[i].expected)
59  {
60  _dbus_warn ("Improper validation result %d for '%s'\n",
61  v, tests[i].data);
62  _dbus_assert_not_reached ("test failed");
63  }
64 
65  ++i;
66  }
67 }
68 
69 static const ValidityTest signature_tests[] = {
70  { "", DBUS_VALID },
71  { "i", DBUS_VALID },
72  { "ai", DBUS_VALID },
73  { "(i)", DBUS_VALID },
74  { "w", DBUS_INVALID_UNKNOWN_TYPECODE },
75  { "a", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
76  { "aaaaaa", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
77  { "ii(ii)a", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
78  { "ia", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
79  /* DBUS_INVALID_SIGNATURE_TOO_LONG, */ /* too hard to test this way */
80  { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
81  DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION },
82  { "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((ii))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))",
83  DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION },
84  { ")", DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED },
85  { "i)", DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED },
86  { "a)", DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED },
87  { "(", DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED },
88  { "(i", DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED },
89  { "(iiiii", DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED },
90  { "(ai", DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED },
91  { "()", DBUS_INVALID_STRUCT_HAS_NO_FIELDS },
92  { "(())", DBUS_INVALID_STRUCT_HAS_NO_FIELDS },
93  { "a()", DBUS_INVALID_STRUCT_HAS_NO_FIELDS },
94  { "i()", DBUS_INVALID_STRUCT_HAS_NO_FIELDS },
95  { "()i", DBUS_INVALID_STRUCT_HAS_NO_FIELDS },
96  { "(a)", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
97  { "a{ia}", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
98  { "a{}", DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS },
99  { "a{aii}", DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE },
100  /* { "a{i}", DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD }, */
101  /* { "{is}", DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY }, */
102  /* { "a{isi}", DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS }, */
103 };
104 
106 _dbus_marshal_validate_test (void)
107 {
108  DBusString str;
109  int i;
110 
111  const char *valid_paths[] = {
112  "/",
113  "/foo/bar",
114  "/foo",
115  "/foo/bar/baz"
116  };
117  const char *invalid_paths[] = {
118  "bar",
119  "bar/baz",
120  "/foo/bar/",
121  "/foo/"
122  "foo/",
123  "boo//blah",
124  "//",
125  "///",
126  "foo///blah/",
127  "Hello World",
128  "",
129  " ",
130  "foo bar"
131  };
132 
133  const char *valid_interfaces[] = {
134  "org.freedesktop.Foo",
135  "Bar.Baz",
136  "Blah.Blah.Blah.Blah.Blah",
137  "a.b",
138  "a.b.c.d.e.f.g",
139  "a0.b1.c2.d3.e4.f5.g6",
140  "abc123.foo27"
141  };
142  const char *invalid_interfaces[] = {
143  ".",
144  "",
145  "..",
146  ".Foo.Bar",
147  "..Foo.Bar",
148  "Foo.Bar.",
149  "Foo.Bar..",
150  "Foo",
151  "9foo.bar.baz",
152  "foo.bar..baz",
153  "foo.bar...baz",
154  "foo.bar.b..blah",
155  ":",
156  ":0-1",
157  "10",
158  ":11.34324",
159  "0.0.0",
160  "0..0",
161  "foo.Bar.%",
162  "foo.Bar!!",
163  "!Foo.bar.bz",
164  "foo.$.blah",
165  "",
166  " ",
167  "foo bar"
168  };
169 
170  const char *valid_unique_names[] = {
171  ":0",
172  ":a",
173  ":",
174  ":.a",
175  ":.1",
176  ":0.1",
177  ":000.2222",
178  ":.blah",
179  ":abce.freedesktop.blah"
180  };
181  const char *invalid_unique_names[] = {
182  //":-",
183  ":!",
184  //":0-10",
185  ":blah.",
186  ":blah.",
187  ":blah..org",
188  ":blah.org..",
189  ":..blah.org",
190  "",
191  " ",
192  "foo bar"
193  };
194 
195  const char *valid_members[] = {
196  "Hello",
197  "Bar",
198  "foobar",
199  "_foobar",
200  "foo89"
201  };
202 
203  const char *invalid_members[] = {
204  "9Hello",
205  "10",
206  "1",
207  "foo-bar",
208  "blah.org",
209  ".blah",
210  "blah.",
211  "Hello.",
212  "!foo",
213  "",
214  " ",
215  "foo bar"
216  };
217 
218  const char *valid_signatures[] = {
219  "",
220  "sss",
221  "i",
222  "b"
223  };
224 
225  const char *invalid_signatures[] = {
226  " ",
227  "not a valid signature",
228  "123",
229  ".",
230  "(",
231  "a{(ii)i}" /* https://bugs.freedesktop.org/show_bug.cgi?id=17803 */
232  };
233 
234  /* Signature with reason */
235 
236  run_validity_tests (signature_tests, _DBUS_N_ELEMENTS (signature_tests),
238 
239  /* Path validation */
240  i = 0;
241  while (i < (int) _DBUS_N_ELEMENTS (valid_paths))
242  {
243  _dbus_string_init_const (&str, valid_paths[i]);
244 
245  if (!_dbus_validate_path (&str, 0,
246  _dbus_string_get_length (&str)))
247  {
248  _dbus_warn ("Path \"%s\" should have been valid\n", valid_paths[i]);
249  _dbus_assert_not_reached ("invalid path");
250  }
251 
252  ++i;
253  }
254 
255  i = 0;
256  while (i < (int) _DBUS_N_ELEMENTS (invalid_paths))
257  {
258  _dbus_string_init_const (&str, invalid_paths[i]);
259 
260  if (_dbus_validate_path (&str, 0,
261  _dbus_string_get_length (&str)))
262  {
263  _dbus_warn ("Path \"%s\" should have been invalid\n", invalid_paths[i]);
264  _dbus_assert_not_reached ("valid path");
265  }
266 
267  ++i;
268  }
269 
270  /* Interface validation */
271  i = 0;
272  while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
273  {
274  _dbus_string_init_const (&str, valid_interfaces[i]);
275 
276  if (!_dbus_validate_interface (&str, 0,
277  _dbus_string_get_length (&str)))
278  {
279  _dbus_warn ("Interface \"%s\" should have been valid\n", valid_interfaces[i]);
280  _dbus_assert_not_reached ("invalid interface");
281  }
282 
283  ++i;
284  }
285 
286  i = 0;
287  while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
288  {
289  _dbus_string_init_const (&str, invalid_interfaces[i]);
290 
291  if (_dbus_validate_interface (&str, 0,
292  _dbus_string_get_length (&str)))
293  {
294  _dbus_warn ("Interface \"%s\" should have been invalid\n", invalid_interfaces[i]);
295  _dbus_assert_not_reached ("valid interface");
296  }
297 
298  ++i;
299  }
300 
301  /* Bus name validation (check that valid interfaces are valid bus names,
302  * and invalid interfaces are invalid services except if they start with ':')
303  */
304  i = 0;
305  while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
306  {
307  _dbus_string_init_const (&str, valid_interfaces[i]);
308 
309  if (!_dbus_validate_bus_name (&str, 0,
310  _dbus_string_get_length (&str)))
311  {
312  _dbus_warn ("Bus name \"%s\" should have been valid\n", valid_interfaces[i]);
313  _dbus_assert_not_reached ("invalid bus name");
314  }
315 
316  ++i;
317  }
318 
319  i = 0;
320  while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
321  {
322  if (invalid_interfaces[i][0] != ':')
323  {
324  _dbus_string_init_const (&str, invalid_interfaces[i]);
325 
326  if (_dbus_validate_bus_name (&str, 0,
327  _dbus_string_get_length (&str)))
328  {
329  _dbus_warn ("Bus name \"%s\" should have been invalid\n", invalid_interfaces[i]);
330  _dbus_assert_not_reached ("valid bus name");
331  }
332  }
333 
334  ++i;
335  }
336 
337  /* unique name validation */
338  i = 0;
339  while (i < (int) _DBUS_N_ELEMENTS (valid_unique_names))
340  {
341  _dbus_string_init_const (&str, valid_unique_names[i]);
342 
343  if (!_dbus_validate_bus_name (&str, 0,
344  _dbus_string_get_length (&str)))
345  {
346  _dbus_warn ("Bus name \"%s\" should have been valid\n", valid_unique_names[i]);
347  _dbus_assert_not_reached ("invalid unique name");
348  }
349 
350  ++i;
351  }
352 
353  i = 0;
354  while (i < (int) _DBUS_N_ELEMENTS (invalid_unique_names))
355  {
356  _dbus_string_init_const (&str, invalid_unique_names[i]);
357 
358  if (_dbus_validate_bus_name (&str, 0,
359  _dbus_string_get_length (&str)))
360  {
361  _dbus_warn ("Bus name \"%s\" should have been invalid\n", invalid_unique_names[i]);
362  _dbus_assert_not_reached ("valid unique name");
363  }
364 
365  ++i;
366  }
367 
368 
369  /* Error name validation (currently identical to interfaces)
370  */
371  i = 0;
372  while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
373  {
374  _dbus_string_init_const (&str, valid_interfaces[i]);
375 
376  if (!_dbus_validate_error_name (&str, 0,
377  _dbus_string_get_length (&str)))
378  {
379  _dbus_warn ("Error name \"%s\" should have been valid\n", valid_interfaces[i]);
380  _dbus_assert_not_reached ("invalid error name");
381  }
382 
383  ++i;
384  }
385 
386  i = 0;
387  while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
388  {
389  if (invalid_interfaces[i][0] != ':')
390  {
391  _dbus_string_init_const (&str, invalid_interfaces[i]);
392 
393  if (_dbus_validate_error_name (&str, 0,
394  _dbus_string_get_length (&str)))
395  {
396  _dbus_warn ("Error name \"%s\" should have been invalid\n", invalid_interfaces[i]);
397  _dbus_assert_not_reached ("valid error name");
398  }
399  }
400 
401  ++i;
402  }
403 
404  /* Member validation */
405  i = 0;
406  while (i < (int) _DBUS_N_ELEMENTS (valid_members))
407  {
408  _dbus_string_init_const (&str, valid_members[i]);
409 
410  if (!_dbus_validate_member (&str, 0,
411  _dbus_string_get_length (&str)))
412  {
413  _dbus_warn ("Member \"%s\" should have been valid\n", valid_members[i]);
414  _dbus_assert_not_reached ("invalid member");
415  }
416 
417  ++i;
418  }
419 
420  i = 0;
421  while (i < (int) _DBUS_N_ELEMENTS (invalid_members))
422  {
423  _dbus_string_init_const (&str, invalid_members[i]);
424 
425  if (_dbus_validate_member (&str, 0,
426  _dbus_string_get_length (&str)))
427  {
428  _dbus_warn ("Member \"%s\" should have been invalid\n", invalid_members[i]);
429  _dbus_assert_not_reached ("valid member");
430  }
431 
432  ++i;
433  }
434 
435  /* Signature validation */
436  i = 0;
437  while (i < (int) _DBUS_N_ELEMENTS (valid_signatures))
438  {
439  _dbus_string_init_const (&str, valid_signatures[i]);
440 
441  if (!_dbus_validate_signature (&str, 0,
442  _dbus_string_get_length (&str)))
443  {
444  _dbus_warn ("Signature \"%s\" should have been valid\n", valid_signatures[i]);
445  _dbus_assert_not_reached ("invalid signature");
446  }
447 
448  ++i;
449  }
450 
451  i = 0;
452  while (i < (int) _DBUS_N_ELEMENTS (invalid_signatures))
453  {
454  _dbus_string_init_const (&str, invalid_signatures[i]);
455 
456  if (_dbus_validate_signature (&str, 0,
457  _dbus_string_get_length (&str)))
458  {
459  _dbus_warn ("Signature \"%s\" should have been invalid\n", invalid_signatures[i]);
460  _dbus_assert_not_reached ("valid signature");
461  }
462 
463  ++i;
464  }
465 
466  /* Validate claimed length longer than real length */
467  _dbus_string_init_const (&str, "abc.efg");
468  if (_dbus_validate_bus_name (&str, 0, 8))
469  _dbus_assert_not_reached ("validated too-long string");
470  if (_dbus_validate_interface (&str, 0, 8))
471  _dbus_assert_not_reached ("validated too-long string");
472  if (_dbus_validate_error_name (&str, 0, 8))
473  _dbus_assert_not_reached ("validated too-long string");
474 
475  _dbus_string_init_const (&str, "abc");
476  if (_dbus_validate_member (&str, 0, 4))
477  _dbus_assert_not_reached ("validated too-long string");
478 
479  _dbus_string_init_const (&str, "sss");
480  if (_dbus_validate_signature (&str, 0, 4))
481  _dbus_assert_not_reached ("validated too-long signature");
482 
483  /* Validate string exceeding max name length */
484  if (!_dbus_string_init (&str))
485  _dbus_assert_not_reached ("no memory");
486 
487  while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
488  if (!_dbus_string_append (&str, "abc.def"))
489  _dbus_assert_not_reached ("no memory");
490 
491  if (_dbus_validate_bus_name (&str, 0, _dbus_string_get_length (&str)))
492  _dbus_assert_not_reached ("validated overmax string");
493  if (_dbus_validate_interface (&str, 0, _dbus_string_get_length (&str)))
494  _dbus_assert_not_reached ("validated overmax string");
495  if (_dbus_validate_error_name (&str, 0, _dbus_string_get_length (&str)))
496  _dbus_assert_not_reached ("validated overmax string");
497 
498  /* overlong member */
499  _dbus_string_set_length (&str, 0);
500  while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
501  if (!_dbus_string_append (&str, "abc"))
502  _dbus_assert_not_reached ("no memory");
503 
504  if (_dbus_validate_member (&str, 0, _dbus_string_get_length (&str)))
505  _dbus_assert_not_reached ("validated overmax string");
506 
507  /* overlong unique name */
508  _dbus_string_set_length (&str, 0);
509  _dbus_string_append (&str, ":");
510  while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
511  if (!_dbus_string_append (&str, "abc"))
512  _dbus_assert_not_reached ("no memory");
513 
514  if (_dbus_validate_bus_name (&str, 0, _dbus_string_get_length (&str)))
515  _dbus_assert_not_reached ("validated overmax string");
516 
517  _dbus_string_free (&str);
518 
519  /* Body validation; test basic validation of valid bodies for both endian */
520 
521  {
522  int sequence;
523  DBusString signature;
524  DBusString body;
525 
526  if (!_dbus_string_init (&signature) || !_dbus_string_init (&body))
527  _dbus_assert_not_reached ("oom");
528 
529  sequence = 0;
530  while (dbus_internal_do_not_use_generate_bodies (sequence,
532  &signature, &body))
533  {
534  DBusValidity validity;
535 
536  validity = _dbus_validate_body_with_reason (&signature, 0,
538  NULL, &body, 0,
539  _dbus_string_get_length (&body));
540  if (validity != DBUS_VALID)
541  {
542  _dbus_warn ("invalid code %d expected valid on sequence %d little endian\n",
543  validity, sequence);
544  _dbus_verbose_bytes_of_string (&signature, 0, _dbus_string_get_length (&signature));
545  _dbus_verbose_bytes_of_string (&body, 0, _dbus_string_get_length (&body));
546  _dbus_assert_not_reached ("test failed");
547  }
548 
549  _dbus_string_set_length (&signature, 0);
550  _dbus_string_set_length (&body, 0);
551  ++sequence;
552  }
553 
554  sequence = 0;
555  while (dbus_internal_do_not_use_generate_bodies (sequence,
557  &signature, &body))
558  {
559  DBusValidity validity;
560 
561  validity = _dbus_validate_body_with_reason (&signature, 0,
563  NULL, &body, 0,
564  _dbus_string_get_length (&body));
565  if (validity != DBUS_VALID)
566  {
567  _dbus_warn ("invalid code %d expected valid on sequence %d big endian\n",
568  validity, sequence);
569  _dbus_verbose_bytes_of_string (&signature, 0, _dbus_string_get_length (&signature));
570  _dbus_verbose_bytes_of_string (&body, 0, _dbus_string_get_length (&body));
571  _dbus_assert_not_reached ("test failed");
572  }
573 
574  _dbus_string_set_length (&signature, 0);
575  _dbus_string_set_length (&body, 0);
576  ++sequence;
577  }
578 
579  _dbus_string_free (&signature);
580  _dbus_string_free (&body);
581  }
582 
583  return TRUE;
584 }
585 
586 #endif /* !DOXYGEN_SHOULD_SKIP_THIS */
587 
588 #endif /* DBUS_ENABLE_EMBEDDED_TESTS */
dbus_bool_t _dbus_string_append(DBusString *str, const char *buffer)
Appends a nul-terminated C-style string to a DBusString.
Definition: dbus-string.c:918
#define NULL
A null pointer, defined appropriately for C or C++.
#define DBUS_MAXIMUM_NAME_LENGTH
Max length in bytes of a bus name, interface, or member (not object path, paths are unlimited)...
dbus_bool_t _dbus_validate_bus_name(const DBusString *str, int start, int len)
Checks that the given range of the string is a valid bus name in the D-Bus protocol.
dbus_bool_t _dbus_validate_interface(const DBusString *str, int start, int len)
Checks that the given range of the string is a valid interface name in the D-Bus protocol.
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:175
DBusValidity
This is primarily used in unit testing, so we can verify that each invalid message is invalid for the...
dbus_bool_t _dbus_validate_error_name(const DBusString *str, int start, int len)
Checks that the given range of the string is a valid error name in the D-Bus protocol.
dbus_bool_t _dbus_validate_signature(const DBusString *str, int start, int len)
Checks that the given range of the string is a valid message type signature in the D-Bus protocol...
dbus_bool_t _dbus_validate_member(const DBusString *str, int start, int len)
Checks that the given range of the string is a valid member name in the D-Bus protocol.
dbus_bool_t _dbus_validate_path(const DBusString *str, int start, int len)
Checks that the given range of the string is a valid object path name in the D-Bus protocol...
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:35
void _dbus_string_init_const(DBusString *str, const char *value)
Initializes a constant string.
Definition: dbus-string.c:190
void _dbus_warn(const char *format,...)
Prints a warning message to stderr.
#define DBUS_BIG_ENDIAN
Code marking MSB-first byte order in the wire protocol.
Definition: dbus-protocol.h:54
#define _DBUS_N_ELEMENTS(array)
Computes the number of elements in a fixed-size array using sizeof().
DBusValidity _dbus_validate_body_with_reason(const DBusString *expected_signature, int expected_signature_start, int byte_order, int *bytes_remaining, const DBusString *value_str, int value_pos, int len)
Verifies that the range of value_str from value_pos to value_end is a legitimate value of type expect...
the data is valid
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init().
Definition: dbus-string.c:242
#define TRUE
Expands to "1".
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
dbus_bool_t _dbus_string_set_length(DBusString *str, int length)
Sets the length of a string.
Definition: dbus-string.c:785
void _dbus_verbose_bytes_of_string(const DBusString *str, int start, int len)
Dump the given part of the string to verbose log.
DBusValidity _dbus_validate_signature_with_reason(const DBusString *type_str, int type_pos, int len)
Verifies that the range of type_str from type_pos to type_end is a valid signature.
#define DBUS_LITTLE_ENDIAN
Code marking LSB-first byte order in the wire protocol.
Definition: dbus-protocol.h:53