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