D-Bus  1.8.22
dbus-marshal-validate.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-marshal-validate.c Validation routines for marshaled data
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 #include "dbus-internals.h"
26 #include "dbus-marshal-validate.h"
27 #include "dbus-marshal-recursive.h"
28 #include "dbus-marshal-basic.h"
29 #include "dbus-signature.h"
30 #include "dbus-string.h"
31 
52  int type_pos,
53  int len)
54 {
55  const unsigned char *p;
56  const unsigned char *end;
57  int last;
58  int struct_depth;
59  int array_depth;
60  int dict_entry_depth;
61  DBusValidity result;
62 
63  int element_count;
64  DBusList *element_count_stack;
65  char opened_brackets[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH * 2 + 1] = { '\0' };
66  char last_bracket;
67 
68  result = DBUS_VALID;
69  element_count_stack = NULL;
70 
71  if (!_dbus_list_append (&element_count_stack, _DBUS_INT_TO_POINTER (0)))
72  {
74  goto out;
75  }
76 
77  _dbus_assert (type_str != NULL);
78  _dbus_assert (type_pos < _DBUS_INT32_MAX - len);
79  _dbus_assert (len >= 0);
80  _dbus_assert (type_pos >= 0);
81 
83  {
84  result = DBUS_INVALID_SIGNATURE_TOO_LONG;
85  goto out;
86  }
87 
88  p = _dbus_string_get_const_data_len (type_str, type_pos, 0);
89 
90  end = _dbus_string_get_const_data_len (type_str, type_pos + len, 0);
91  struct_depth = 0;
92  array_depth = 0;
93  dict_entry_depth = 0;
94  last = DBUS_TYPE_INVALID;
95 
96  while (p != end)
97  {
98  _dbus_assert (struct_depth + dict_entry_depth >= 0);
99  _dbus_assert (struct_depth + dict_entry_depth < _DBUS_N_ELEMENTS (opened_brackets));
100  _dbus_assert (opened_brackets[struct_depth + dict_entry_depth] == '\0');
101 
102  switch (*p)
103  {
104  case DBUS_TYPE_BYTE:
105  case DBUS_TYPE_BOOLEAN:
106  case DBUS_TYPE_INT16:
107  case DBUS_TYPE_UINT16:
108  case DBUS_TYPE_INT32:
109  case DBUS_TYPE_UINT32:
110  case DBUS_TYPE_UNIX_FD:
111  case DBUS_TYPE_INT64:
112  case DBUS_TYPE_UINT64:
113  case DBUS_TYPE_DOUBLE:
114  case DBUS_TYPE_STRING:
116  case DBUS_TYPE_SIGNATURE:
117  case DBUS_TYPE_VARIANT:
118  break;
119 
120  case DBUS_TYPE_ARRAY:
121  array_depth += 1;
122  if (array_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH)
123  {
124  result = DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION;
125  goto out;
126  }
127  break;
128 
130  struct_depth += 1;
131 
132  if (struct_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH)
133  {
134  result = DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION;
135  goto out;
136  }
137 
138  if (!_dbus_list_append (&element_count_stack,
140  {
142  goto out;
143  }
144 
145  _dbus_assert (struct_depth + dict_entry_depth >= 1);
146  _dbus_assert (struct_depth + dict_entry_depth < _DBUS_N_ELEMENTS (opened_brackets));
147  _dbus_assert (opened_brackets[struct_depth + dict_entry_depth - 1] == '\0');
148  opened_brackets[struct_depth + dict_entry_depth - 1] = DBUS_STRUCT_BEGIN_CHAR;
149  break;
150 
152  if (struct_depth == 0)
153  {
154  result = DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED;
155  goto out;
156  }
157 
158  if (last == DBUS_STRUCT_BEGIN_CHAR)
159  {
160  result = DBUS_INVALID_STRUCT_HAS_NO_FIELDS;
161  goto out;
162  }
163 
164  _dbus_assert (struct_depth + dict_entry_depth >= 1);
165  _dbus_assert (struct_depth + dict_entry_depth < _DBUS_N_ELEMENTS (opened_brackets));
166  last_bracket = opened_brackets[struct_depth + dict_entry_depth - 1];
167 
168  if (last_bracket != DBUS_STRUCT_BEGIN_CHAR)
169  {
170  result = DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED;
171  goto out;
172  }
173 
174  _dbus_list_pop_last (&element_count_stack);
175 
176  struct_depth -= 1;
177  opened_brackets[struct_depth + dict_entry_depth] = '\0';
178  break;
179 
181  if (last != DBUS_TYPE_ARRAY)
182  {
183  result = DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY;
184  goto out;
185  }
186 
187  dict_entry_depth += 1;
188 
189  if (dict_entry_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH)
190  {
191  result = DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION;
192  goto out;
193  }
194 
195  if (!_dbus_list_append (&element_count_stack,
197  {
199  goto out;
200  }
201 
202  _dbus_assert (struct_depth + dict_entry_depth >= 1);
203  _dbus_assert (struct_depth + dict_entry_depth < _DBUS_N_ELEMENTS (opened_brackets));
204  _dbus_assert (opened_brackets[struct_depth + dict_entry_depth - 1] == '\0');
205  opened_brackets[struct_depth + dict_entry_depth - 1] = DBUS_DICT_ENTRY_BEGIN_CHAR;
206  break;
207 
209  if (dict_entry_depth == 0)
210  {
211  result = DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED;
212  goto out;
213  }
214 
215  _dbus_assert (struct_depth + dict_entry_depth >= 1);
216  _dbus_assert (struct_depth + dict_entry_depth < _DBUS_N_ELEMENTS (opened_brackets));
217  last_bracket = opened_brackets[struct_depth + dict_entry_depth - 1];
218 
219  if (last_bracket != DBUS_DICT_ENTRY_BEGIN_CHAR)
220  {
221  result = DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED;
222  goto out;
223  }
224 
225  dict_entry_depth -= 1;
226  opened_brackets[struct_depth + dict_entry_depth] = '\0';
227 
228  element_count =
229  _DBUS_POINTER_TO_INT (_dbus_list_pop_last (&element_count_stack));
230 
231  if (element_count != 2)
232  {
233  if (element_count == 0)
234  result = DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS;
235  else if (element_count == 1)
236  result = DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD;
237  else
238  result = DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS;
239 
240  goto out;
241  }
242  break;
243 
244  case DBUS_TYPE_STRUCT: /* doesn't appear in signatures */
245  case DBUS_TYPE_DICT_ENTRY: /* ditto */
246  default:
247  result = DBUS_INVALID_UNKNOWN_TYPECODE;
248  goto out;
249  }
250 
251  if (*p != DBUS_TYPE_ARRAY &&
253  *p != DBUS_STRUCT_BEGIN_CHAR)
254  {
255  element_count =
256  _DBUS_POINTER_TO_INT (_dbus_list_pop_last (&element_count_stack));
257 
258  ++element_count;
259 
260  if (!_dbus_list_append (&element_count_stack,
261  _DBUS_INT_TO_POINTER (element_count)))
262  {
264  goto out;
265  }
266  }
267 
268  if (array_depth > 0)
269  {
270  if (*p == DBUS_TYPE_ARRAY && p != end)
271  {
272  const char *p1;
273  p1 = p + 1;
274  if (*p1 == DBUS_STRUCT_END_CHAR ||
276  {
277  result = DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE;
278  goto out;
279  }
280  }
281  else
282  {
283  array_depth = 0;
284  }
285  }
286 
287  if (last == DBUS_DICT_ENTRY_BEGIN_CHAR)
288  {
289  if (!(dbus_type_is_valid (*p) && dbus_type_is_basic (*p)))
290  {
291  result = DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE;
292  goto out;
293  }
294  }
295 
296  last = *p;
297  ++p;
298  }
299 
300 
301  if (array_depth > 0)
302  {
303  result = DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE;
304  goto out;
305  }
306 
307  if (struct_depth > 0)
308  {
309  result = DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED;
310  goto out;
311  }
312 
313  if (dict_entry_depth > 0)
314  {
315  result = DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED;
316  goto out;
317  }
318 
319  _dbus_assert (last != DBUS_TYPE_ARRAY);
322 
323  result = DBUS_VALID;
324 
325 out:
326  _dbus_list_clear (&element_count_stack);
327  return result;
328 }
329 
330 /* note: this function is also used to validate the header's values,
331  * since the header is a valid body with a particular signature.
332  */
333 static DBusValidity
334 validate_body_helper (DBusTypeReader *reader,
335  int byte_order,
336  dbus_bool_t walk_reader_to_end,
337  int total_depth,
338  const unsigned char *p,
339  const unsigned char *end,
340  const unsigned char **new_p)
341 {
342  int current_type;
343 
344  /* The spec allows arrays and structs to each nest 32, for total
345  * nesting of 2*32. We want to impose the same limit on "dynamic"
346  * value nesting (not visible in the signature) which is introduced
347  * by DBUS_TYPE_VARIANT.
348  */
349  if (total_depth > (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH * 2))
350  {
351  return DBUS_INVALID_NESTED_TOO_DEEPLY;
352  }
353 
354  while ((current_type = _dbus_type_reader_get_current_type (reader)) != DBUS_TYPE_INVALID)
355  {
356  const unsigned char *a;
357  int alignment;
358 
359 #if 0
360  _dbus_verbose (" validating value of type %s type reader %p type_pos %d p %p end %p %d remain\n",
361  _dbus_type_to_string (current_type), reader, reader->type_pos, p, end,
362  (int) (end - p));
363 #endif
364 
365  /* Guarantee that p has one byte to look at */
366  if (p == end)
367  return DBUS_INVALID_NOT_ENOUGH_DATA;
368 
369  switch (current_type)
370  {
371  case DBUS_TYPE_BYTE:
372  ++p;
373  break;
374 
375  case DBUS_TYPE_BOOLEAN:
376  case DBUS_TYPE_INT16:
377  case DBUS_TYPE_UINT16:
378  case DBUS_TYPE_INT32:
379  case DBUS_TYPE_UINT32:
380  case DBUS_TYPE_UNIX_FD:
381  case DBUS_TYPE_INT64:
382  case DBUS_TYPE_UINT64:
383  case DBUS_TYPE_DOUBLE:
384  alignment = _dbus_type_get_alignment (current_type);
385  a = _DBUS_ALIGN_ADDRESS (p, alignment);
386  if (a >= end)
387  return DBUS_INVALID_NOT_ENOUGH_DATA;
388  while (p != a)
389  {
390  if (*p != '\0')
391  return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
392  ++p;
393  }
394 
395  if (current_type == DBUS_TYPE_BOOLEAN)
396  {
397  dbus_uint32_t v = _dbus_unpack_uint32 (byte_order,
398  p);
399  if (!(v == 0 || v == 1))
400  return DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE;
401  }
402 
403  p += alignment;
404  break;
405 
406  case DBUS_TYPE_ARRAY:
407  case DBUS_TYPE_STRING:
409  {
410  dbus_uint32_t claimed_len;
411 
412  a = _DBUS_ALIGN_ADDRESS (p, 4);
413  if (a + 4 > end)
414  return DBUS_INVALID_NOT_ENOUGH_DATA;
415  while (p != a)
416  {
417  if (*p != '\0')
418  return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
419  ++p;
420  }
421 
422  claimed_len = _dbus_unpack_uint32 (byte_order, p);
423  p += 4;
424 
425  /* p may now be == end */
426  _dbus_assert (p <= end);
427 
428  if (current_type == DBUS_TYPE_ARRAY)
429  {
430  int array_elem_type = _dbus_type_reader_get_element_type (reader);
431 
432  if (!dbus_type_is_valid (array_elem_type))
433  {
434  return DBUS_INVALID_UNKNOWN_TYPECODE;
435  }
436 
437  alignment = _dbus_type_get_alignment (array_elem_type);
438 
439  a = _DBUS_ALIGN_ADDRESS (p, alignment);
440 
441  /* a may now be == end */
442  if (a > end)
443  return DBUS_INVALID_NOT_ENOUGH_DATA;
444 
445  while (p != a)
446  {
447  if (*p != '\0')
448  return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
449  ++p;
450  }
451  }
452 
453  if (claimed_len > (unsigned long) (end - p))
454  return DBUS_INVALID_LENGTH_OUT_OF_BOUNDS;
455 
456  if (current_type == DBUS_TYPE_OBJECT_PATH)
457  {
458  DBusString str;
459  _dbus_string_init_const_len (&str, p, claimed_len);
460  if (!_dbus_validate_path (&str, 0,
461  _dbus_string_get_length (&str)))
462  return DBUS_INVALID_BAD_PATH;
463 
464  p += claimed_len;
465  }
466  else if (current_type == DBUS_TYPE_STRING)
467  {
468  DBusString str;
469  _dbus_string_init_const_len (&str, p, claimed_len);
470  if (!_dbus_string_validate_utf8 (&str, 0,
471  _dbus_string_get_length (&str)))
472  return DBUS_INVALID_BAD_UTF8_IN_STRING;
473 
474  p += claimed_len;
475  }
476  else if (current_type == DBUS_TYPE_ARRAY && claimed_len > 0)
477  {
478  DBusTypeReader sub;
479  DBusValidity validity;
480  const unsigned char *array_end;
481  int array_elem_type;
482 
483  if (claimed_len > DBUS_MAXIMUM_ARRAY_LENGTH)
484  return DBUS_INVALID_ARRAY_LENGTH_EXCEEDS_MAXIMUM;
485 
486  /* Remember that the reader is types only, so we can't
487  * use it to iterate over elements. It stays the same
488  * for all elements.
489  */
490  _dbus_type_reader_recurse (reader, &sub);
491 
492  array_end = p + claimed_len;
493 
494  array_elem_type = _dbus_type_reader_get_element_type (reader);
495 
496  /* avoid recursive call to validate_body_helper if this is an array
497  * of fixed-size elements
498  */
499  if (dbus_type_is_fixed (array_elem_type))
500  {
501  /* Note that fixed-size types all have sizes equal to
502  * their alignments, so this is really the item size. */
503  alignment = _dbus_type_get_alignment (array_elem_type);
504  _dbus_assert (alignment == 1 || alignment == 2 ||
505  alignment == 4 || alignment == 8);
506 
507  /* Because the alignment is a power of 2, this is
508  * equivalent to: (claimed_len % alignment) != 0,
509  * but avoids slower integer division */
510  if ((claimed_len & (alignment - 1)) != 0)
511  return DBUS_INVALID_ARRAY_LENGTH_INCORRECT;
512 
513  /* bools need to be handled differently, because they can
514  * have an invalid value
515  */
516  if (array_elem_type == DBUS_TYPE_BOOLEAN)
517  {
518  dbus_uint32_t v;
519 
520  while (p < array_end)
521  {
522  v = _dbus_unpack_uint32 (byte_order, p);
523 
524  if (!(v == 0 || v == 1))
525  return DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE;
526 
527  p += alignment;
528  }
529  }
530 
531  else
532  {
533  p = array_end;
534  }
535  }
536 
537  else
538  {
539  while (p < array_end)
540  {
541  validity = validate_body_helper (&sub, byte_order, FALSE,
542  total_depth + 1,
543  p, end, &p);
544  if (validity != DBUS_VALID)
545  return validity;
546  }
547  }
548 
549  if (p != array_end)
550  return DBUS_INVALID_ARRAY_LENGTH_INCORRECT;
551  }
552 
553  /* check nul termination */
554  if (current_type != DBUS_TYPE_ARRAY)
555  {
556  if (p == end)
557  return DBUS_INVALID_NOT_ENOUGH_DATA;
558 
559  if (*p != '\0')
560  return DBUS_INVALID_STRING_MISSING_NUL;
561  ++p;
562  }
563  }
564  break;
565 
566  case DBUS_TYPE_SIGNATURE:
567  {
568  dbus_uint32_t claimed_len;
569  DBusString str;
570  DBusValidity validity;
571 
572  claimed_len = *p;
573  ++p;
574 
575  /* 1 is for nul termination */
576  if (claimed_len + 1 > (unsigned long) (end - p))
577  return DBUS_INVALID_SIGNATURE_LENGTH_OUT_OF_BOUNDS;
578 
579  _dbus_string_init_const_len (&str, p, claimed_len);
580  validity =
582  _dbus_string_get_length (&str));
583 
584  if (validity != DBUS_VALID)
585  return validity;
586 
587  p += claimed_len;
588 
589  _dbus_assert (p < end);
590  if (*p != DBUS_TYPE_INVALID)
591  return DBUS_INVALID_SIGNATURE_MISSING_NUL;
592 
593  ++p;
594 
595  _dbus_verbose ("p = %p end = %p claimed_len %u\n", p, end, claimed_len);
596  }
597  break;
598 
599  case DBUS_TYPE_VARIANT:
600  {
601  /* 1 byte sig len, sig typecodes, align to
602  * contained-type-boundary, values.
603  */
604 
605  /* In addition to normal signature validation, we need to be sure
606  * the signature contains only a single (possibly container) type.
607  */
608  dbus_uint32_t claimed_len;
609  DBusString sig;
610  DBusTypeReader sub;
611  DBusValidity validity;
612  int contained_alignment;
613  int contained_type;
614  DBusValidity reason;
615 
616  claimed_len = *p;
617  ++p;
618 
619  /* + 1 for nul */
620  if (claimed_len + 1 > (unsigned long) (end - p))
621  return DBUS_INVALID_VARIANT_SIGNATURE_LENGTH_OUT_OF_BOUNDS;
622 
623  _dbus_string_init_const_len (&sig, p, claimed_len);
624  reason = _dbus_validate_signature_with_reason (&sig, 0,
625  _dbus_string_get_length (&sig));
626  if (!(reason == DBUS_VALID))
627  {
628  if (reason == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
629  return reason;
630  else
631  return DBUS_INVALID_VARIANT_SIGNATURE_BAD;
632  }
633 
634  p += claimed_len;
635 
636  if (*p != DBUS_TYPE_INVALID)
637  return DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL;
638  ++p;
639 
640  contained_type = _dbus_first_type_in_signature (&sig, 0);
641  if (contained_type == DBUS_TYPE_INVALID)
642  return DBUS_INVALID_VARIANT_SIGNATURE_EMPTY;
643 
644  contained_alignment = _dbus_type_get_alignment (contained_type);
645 
646  a = _DBUS_ALIGN_ADDRESS (p, contained_alignment);
647  if (a > end)
648  return DBUS_INVALID_NOT_ENOUGH_DATA;
649  while (p != a)
650  {
651  if (*p != '\0')
652  return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
653  ++p;
654  }
655 
656  _dbus_type_reader_init_types_only (&sub, &sig, 0);
657 
659 
660  validity = validate_body_helper (&sub, byte_order, FALSE,
661  total_depth + 1,
662  p, end, &p);
663  if (validity != DBUS_VALID)
664  return validity;
665 
666  if (_dbus_type_reader_next (&sub))
667  return DBUS_INVALID_VARIANT_SIGNATURE_SPECIFIES_MULTIPLE_VALUES;
668 
670  }
671  break;
672 
674  case DBUS_TYPE_STRUCT:
675  {
676  DBusTypeReader sub;
677  DBusValidity validity;
678 
679  a = _DBUS_ALIGN_ADDRESS (p, 8);
680  if (a > end)
681  return DBUS_INVALID_NOT_ENOUGH_DATA;
682  while (p != a)
683  {
684  if (*p != '\0')
685  return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
686  ++p;
687  }
688 
689  _dbus_type_reader_recurse (reader, &sub);
690 
691  validity = validate_body_helper (&sub, byte_order, TRUE,
692  total_depth + 1,
693  p, end, &p);
694  if (validity != DBUS_VALID)
695  return validity;
696  }
697  break;
698 
699  default:
700  _dbus_assert_not_reached ("invalid typecode in supposedly-validated signature");
701  break;
702  }
703 
704 #if 0
705  _dbus_verbose (" validated value of type %s type reader %p type_pos %d p %p end %p %d remain\n",
706  _dbus_type_to_string (current_type), reader, reader->type_pos, p, end,
707  (int) (end - p));
708 #endif
709 
710  if (p > end)
711  {
712  _dbus_verbose ("not enough data!!! p = %p end = %p end-p = %d\n",
713  p, end, (int) (end - p));
714  return DBUS_INVALID_NOT_ENOUGH_DATA;
715  }
716 
717  if (walk_reader_to_end)
718  _dbus_type_reader_next (reader);
719  else
720  break;
721  }
722 
723  if (new_p)
724  *new_p = p;
725 
726  return DBUS_VALID;
727 }
728 
750 _dbus_validate_body_with_reason (const DBusString *expected_signature,
751  int expected_signature_start,
752  int byte_order,
753  int *bytes_remaining,
754  const DBusString *value_str,
755  int value_pos,
756  int len)
757 {
758  DBusTypeReader reader;
759  const unsigned char *p;
760  const unsigned char *end;
761  DBusValidity validity;
762 
763  _dbus_assert (len >= 0);
764  _dbus_assert (value_pos >= 0);
765  _dbus_assert (value_pos <= _dbus_string_get_length (value_str) - len);
766 
767  _dbus_verbose ("validating body from pos %d len %d sig '%s'\n",
768  value_pos, len, _dbus_string_get_const_data_len (expected_signature,
769  expected_signature_start,
770  0));
771 
773  expected_signature, expected_signature_start);
774 
775  p = _dbus_string_get_const_data_len (value_str, value_pos, len);
776  end = p + len;
777 
778  validity = validate_body_helper (&reader, byte_order, TRUE, 0, p, end, &p);
779  if (validity != DBUS_VALID)
780  return validity;
781 
782  if (bytes_remaining)
783  {
784  *bytes_remaining = end - p;
785  return DBUS_VALID;
786  }
787  else if (p < end)
789  else
790  {
791  _dbus_assert (p == end);
792  return DBUS_VALID;
793  }
794 }
795 
800 #define VALID_INITIAL_NAME_CHARACTER(c) \
801  ( ((c) >= 'A' && (c) <= 'Z') || \
802  ((c) >= 'a' && (c) <= 'z') || \
803  ((c) == '_') )
804 
809 #define VALID_NAME_CHARACTER(c) \
810  ( ((c) >= '0' && (c) <= '9') || \
811  ((c) >= 'A' && (c) <= 'Z') || \
812  ((c) >= 'a' && (c) <= 'z') || \
813  ((c) == '_') )
814 
833  int start,
834  int len)
835 {
836  const unsigned char *s;
837  const unsigned char *end;
838  const unsigned char *last_slash;
839 
840  _dbus_assert (start >= 0);
841  _dbus_assert (len >= 0);
842  _dbus_assert (start <= _dbus_string_get_length (str));
843 
844  if (len > _dbus_string_get_length (str) - start)
845  return FALSE;
846 
847  if (len == 0)
848  return FALSE;
849 
850  s = _dbus_string_get_const_data (str) + start;
851  end = s + len;
852 
853  if (*s != '/')
854  return FALSE;
855  last_slash = s;
856  ++s;
857 
858  while (s != end)
859  {
860  if (*s == '/')
861  {
862  if ((s - last_slash) < 2)
863  return FALSE; /* no empty path components allowed */
864 
865  last_slash = s;
866  }
867  else
868  {
869  if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
870  return FALSE;
871  }
872 
873  ++s;
874  }
875 
876  if ((end - last_slash) < 2 &&
877  len > 1)
878  return FALSE; /* trailing slash not allowed unless the string is "/" */
879 
880  return TRUE;
881 }
882 
883 const char *
884 _dbus_validity_to_error_message (DBusValidity validity)
885 {
886  switch (validity)
887  {
888  case DBUS_VALIDITY_UNKNOWN_OOM_ERROR: return "Out of memory";
889  case DBUS_INVALID_FOR_UNKNOWN_REASON: return "Unknown reason";
890  case DBUS_VALID_BUT_INCOMPLETE: return "Valid but incomplete";
891  case DBUS_VALIDITY_UNKNOWN: return "Validity unknown";
892  case DBUS_VALID: return "Valid";
893  case DBUS_INVALID_UNKNOWN_TYPECODE: return "Unknown typecode";
894  case DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE: return "Missing array element type";
895  case DBUS_INVALID_SIGNATURE_TOO_LONG: return "Signature is too long";
896  case DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION: return "Exceeded maximum array recursion";
897  case DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION: return "Exceeded maximum struct recursion";
898  case DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED: return "Struct ended but not started";
899  case DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED: return "Struct started but not ended";
900  case DBUS_INVALID_STRUCT_HAS_NO_FIELDS: return "Struct has no fields";
901  case DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL: return "Alignment padding not null";
902  case DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE: return "Boolean is not zero or one";
903  case DBUS_INVALID_NOT_ENOUGH_DATA: return "Not enough data";
904  case DBUS_INVALID_TOO_MUCH_DATA: return "Too much data";
905  case DBUS_INVALID_BAD_BYTE_ORDER: return "Bad byte order";
906  case DBUS_INVALID_BAD_PROTOCOL_VERSION: return "Bad protocol version";
907  case DBUS_INVALID_BAD_MESSAGE_TYPE: return "Bad message type";
908  case DBUS_INVALID_BAD_SERIAL: return "Bad serial";
909  case DBUS_INVALID_INSANE_FIELDS_ARRAY_LENGTH: return "Insane fields array length";
910  case DBUS_INVALID_INSANE_BODY_LENGTH: return "Insane body length";
911  case DBUS_INVALID_MESSAGE_TOO_LONG: return "Message too long";
912  case DBUS_INVALID_HEADER_FIELD_CODE: return "Header field code";
913  case DBUS_INVALID_HEADER_FIELD_HAS_WRONG_TYPE: return "Header field has wrong type";
914  case DBUS_INVALID_USES_LOCAL_INTERFACE: return "Uses local interface";
915  case DBUS_INVALID_USES_LOCAL_PATH: return "Uses local path";
916  case DBUS_INVALID_HEADER_FIELD_APPEARS_TWICE: return "Header field appears twice";
917  case DBUS_INVALID_BAD_DESTINATION: return "Bad destination";
918  case DBUS_INVALID_BAD_INTERFACE: return "Bad interface";
919  case DBUS_INVALID_BAD_MEMBER: return "Bad member";
920  case DBUS_INVALID_BAD_ERROR_NAME: return "Bad error name";
921  case DBUS_INVALID_BAD_SENDER: return "Bad sender";
922  case DBUS_INVALID_MISSING_PATH: return "Missing path";
923  case DBUS_INVALID_MISSING_INTERFACE: return "Missing interface";
924  case DBUS_INVALID_MISSING_MEMBER: return "Missing member";
925  case DBUS_INVALID_MISSING_ERROR_NAME: return "Missing error name";
926  case DBUS_INVALID_MISSING_REPLY_SERIAL: return "Missing reply serial";
927  case DBUS_INVALID_LENGTH_OUT_OF_BOUNDS: return "Length out of bounds";
928  case DBUS_INVALID_ARRAY_LENGTH_EXCEEDS_MAXIMUM: return "Array length exceeds maximum";
929  case DBUS_INVALID_BAD_PATH: return "Bad path";
930  case DBUS_INVALID_SIGNATURE_LENGTH_OUT_OF_BOUNDS: return "Signature length out of bounds";
931  case DBUS_INVALID_BAD_UTF8_IN_STRING: return "Bad utf8 in string";
932  case DBUS_INVALID_ARRAY_LENGTH_INCORRECT: return "Array length incorrect";
933  case DBUS_INVALID_VARIANT_SIGNATURE_LENGTH_OUT_OF_BOUNDS: return "Variant signature length out of bounds";
934  case DBUS_INVALID_VARIANT_SIGNATURE_BAD: return "Variant signature bad";
935  case DBUS_INVALID_VARIANT_SIGNATURE_EMPTY: return "Variant signature empty";
936  case DBUS_INVALID_VARIANT_SIGNATURE_SPECIFIES_MULTIPLE_VALUES: return "Variant signature specifies multiple values";
937  case DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL: return "Variant signature missing nul";
938  case DBUS_INVALID_STRING_MISSING_NUL: return "String missing nul";
939  case DBUS_INVALID_SIGNATURE_MISSING_NUL: return "Signature missing nul";
940  case DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION: return "Exceeded maximum dict entry recursion";
941  case DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED: return "Dict entry ended but not started";
942  case DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED: return "Dict entry started but not ended";
943  case DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS: return "Dict entry has no fields";
944  case DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD: return "Dict entry has only one field";
945  case DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS: return "Dict entry has too many fields";
946  case DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY: return "Dict entry not inside array";
947  case DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE: return "Dict key must be basic type";
948  case DBUS_INVALID_NESTED_TOO_DEEPLY: return "Variants cannot be used to create a hugely recursive tree of values";
949  default:
950  return "Invalid";
951  }
952 }
953 
969  int start,
970  int len)
971 {
972  const unsigned char *s;
973  const unsigned char *end;
974  const unsigned char *iface;
975  const unsigned char *last_dot;
976 
977  _dbus_assert (start >= 0);
978  _dbus_assert (len >= 0);
979  _dbus_assert (start <= _dbus_string_get_length (str));
980 
981  if (len > _dbus_string_get_length (str) - start)
982  return FALSE;
983 
984  if (len > DBUS_MAXIMUM_NAME_LENGTH)
985  return FALSE;
986 
987  if (len == 0)
988  return FALSE;
989 
990  last_dot = NULL;
991  iface = _dbus_string_get_const_data (str) + start;
992  end = iface + len;
993  s = iface;
994 
995  /* check special cases of first char so it doesn't have to be done
996  * in the loop. Note we know len > 0
997  */
998  if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */
999  return FALSE;
1000  else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s)))
1001  return FALSE;
1002  else
1003  ++s;
1004 
1005  while (s != end)
1006  {
1007  if (*s == '.')
1008  {
1009  if (_DBUS_UNLIKELY ((s + 1) == end))
1010  return FALSE;
1011  else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*(s + 1))))
1012  return FALSE;
1013  last_dot = s;
1014  ++s; /* we just validated the next char, so skip two */
1015  }
1016  else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
1017  {
1018  return FALSE;
1019  }
1020 
1021  ++s;
1022  }
1023 
1024  if (_DBUS_UNLIKELY (last_dot == NULL))
1025  return FALSE;
1026 
1027  return TRUE;
1028 }
1029 
1045  int start,
1046  int len)
1047 {
1048  const unsigned char *s;
1049  const unsigned char *end;
1050  const unsigned char *member;
1051 
1052  _dbus_assert (start >= 0);
1053  _dbus_assert (len >= 0);
1054  _dbus_assert (start <= _dbus_string_get_length (str));
1055 
1056  if (len > _dbus_string_get_length (str) - start)
1057  return FALSE;
1058 
1059  if (len > DBUS_MAXIMUM_NAME_LENGTH)
1060  return FALSE;
1061 
1062  if (len == 0)
1063  return FALSE;
1064 
1065  member = _dbus_string_get_const_data (str) + start;
1066  end = member + len;
1067  s = member;
1068 
1069  /* check special cases of first char so it doesn't have to be done
1070  * in the loop. Note we know len > 0
1071  */
1072 
1073  if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s)))
1074  return FALSE;
1075  else
1076  ++s;
1077 
1078  while (s != end)
1079  {
1080  if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
1081  {
1082  return FALSE;
1083  }
1084 
1085  ++s;
1086  }
1087 
1088  return TRUE;
1089 }
1090 
1106  int start,
1107  int len)
1108 {
1109  /* Same restrictions as interface name at the moment */
1110  return _dbus_validate_interface (str, start, len);
1111 }
1112 
1117 #define VALID_INITIAL_BUS_NAME_CHARACTER(c) \
1118  ( ((c) >= 'A' && (c) <= 'Z') || \
1119  ((c) >= 'a' && (c) <= 'z') || \
1120  ((c) == '_') || ((c) == '-'))
1121 
1126 #define VALID_BUS_NAME_CHARACTER(c) \
1127  ( ((c) >= '0' && (c) <= '9') || \
1128  ((c) >= 'A' && (c) <= 'Z') || \
1129  ((c) >= 'a' && (c) <= 'z') || \
1130  ((c) == '_') || ((c) == '-'))
1131 
1132 static dbus_bool_t
1133 _dbus_validate_bus_name_full (const DBusString *str,
1134  int start,
1135  int len,
1136  dbus_bool_t is_namespace)
1137 {
1138  const unsigned char *s;
1139  const unsigned char *end;
1140  const unsigned char *iface;
1141  const unsigned char *last_dot;
1142 
1143  _dbus_assert (start >= 0);
1144  _dbus_assert (len >= 0);
1145  _dbus_assert (start <= _dbus_string_get_length (str));
1146 
1147  if (len > _dbus_string_get_length (str) - start)
1148  return FALSE;
1149 
1150  if (len > DBUS_MAXIMUM_NAME_LENGTH)
1151  return FALSE;
1152 
1153  if (len == 0)
1154  return FALSE;
1155 
1156  last_dot = NULL;
1157  iface = _dbus_string_get_const_data (str) + start;
1158  end = iface + len;
1159  s = iface;
1160 
1161  /* check special cases of first char so it doesn't have to be done
1162  * in the loop. Note we know len > 0
1163  */
1164  if (*s == ':')
1165  {
1166  /* unique name */
1167  ++s;
1168  while (s != end)
1169  {
1170  if (*s == '.')
1171  {
1172  if (_DBUS_UNLIKELY ((s + 1) == end))
1173  return FALSE;
1174  if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*(s + 1))))
1175  return FALSE;
1176  ++s; /* we just validated the next char, so skip two */
1177  }
1178  else if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*s)))
1179  {
1180  return FALSE;
1181  }
1182 
1183  ++s;
1184  }
1185 
1186  return TRUE;
1187  }
1188  else if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */
1189  return FALSE;
1190  else if (_DBUS_UNLIKELY (!VALID_INITIAL_BUS_NAME_CHARACTER (*s)))
1191  return FALSE;
1192  else
1193  ++s;
1194 
1195  while (s != end)
1196  {
1197  if (*s == '.')
1198  {
1199  if (_DBUS_UNLIKELY ((s + 1) == end))
1200  return FALSE;
1201  else if (_DBUS_UNLIKELY (!VALID_INITIAL_BUS_NAME_CHARACTER (*(s + 1))))
1202  return FALSE;
1203  last_dot = s;
1204  ++s; /* we just validated the next char, so skip two */
1205  }
1206  else if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*s)))
1207  {
1208  return FALSE;
1209  }
1210 
1211  ++s;
1212  }
1213 
1214  if (!is_namespace && _DBUS_UNLIKELY (last_dot == NULL))
1215  return FALSE;
1216 
1217  return TRUE;
1218 }
1219 
1235  int start,
1236  int len)
1237 {
1238  return _dbus_validate_bus_name_full (str, start, len, FALSE);
1239 }
1240 
1256  int start,
1257  int len)
1258 {
1259  return _dbus_validate_bus_name_full (str, start, len, TRUE);
1260 }
1261 
1276  int start,
1277  int len)
1278 {
1279  _dbus_assert (start >= 0);
1280  _dbus_assert (start <= _dbus_string_get_length (str));
1281  _dbus_assert (len >= 0);
1282 
1283  if (len > _dbus_string_get_length (str) - start)
1284  return FALSE;
1285 
1286  return _dbus_validate_signature_with_reason (str, start, len) == DBUS_VALID;
1287 }
1288 
1292 DEFINE_DBUS_NAME_CHECK(interface)
1294 DEFINE_DBUS_NAME_CHECK(member)
1296 DEFINE_DBUS_NAME_CHECK(error_name)
1298 DEFINE_DBUS_NAME_CHECK(bus_name)
1300 DEFINE_DBUS_NAME_CHECK(signature)
1303 
1306 /* tests in dbus-marshal-validate-util.c */
dbus_bool_t dbus_type_is_fixed(int typecode)
Tells you whether values of this type can change length if you set them to some other value...
#define DBUS_TYPE_UINT16
Type code marking a 16-bit unsigned integer.
Definition: dbus-protocol.h:78
#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)...
trailing junk makes it invalid
void * _dbus_list_pop_last(DBusList **list)
Removes the last value in the list and returns it.
Definition: dbus-list.c:672
int _dbus_first_type_in_signature(const DBusString *str, int pos)
Get the first type in the signature.
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.
void _dbus_type_reader_recurse(DBusTypeReader *reader, DBusTypeReader *sub)
Initialize a new reader pointing to the first type and corresponding value that's a child of the curr...
#define DBUS_TYPE_STRUCT
STRUCT and DICT_ENTRY are sort of special since their codes can't appear in a type string...
#define DBUS_MAXIMUM_TYPE_RECURSION_DEPTH
Depth of recursion in the type tree.
#define DBUS_TYPE_DICT_ENTRY
Type code used to represent a dict entry; however, this type code does not appear in type signatures...
#define DBUS_TYPE_STRING
Type code marking a UTF-8 encoded, nul-terminated Unicode string.
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
int type_pos
current position in signature
#define _DBUS_INT_TO_POINTER(integer)
Safely stuffs an integer into a pointer, to be extracted later with _DBUS_POINTER_TO_INT.
#define DBUS_TYPE_BYTE
Type code marking an 8-bit unsigned integer.
Definition: dbus-protocol.h:66
dbus_bool_t _dbus_validate_bus_namespace(const DBusString *str, int start, int len)
Checks that the given range of the string is a prefix of 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.
void _dbus_type_reader_init_types_only(DBusTypeReader *reader, const DBusString *type_str, int type_pos)
Like _dbus_type_reader_init() but the iteration is over the signature, not over values.
#define DBUS_DICT_ENTRY_BEGIN_CHAR
Code marking the start of a dict entry type in a type signature.
DBusValidity
This is primarily used in unit testing, so we can verify that each invalid message is invalid for the...
#define DBUS_STRUCT_END_CHAR
Code marking the end of a struct type in a type signature.
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.
#define DBUS_TYPE_DOUBLE
Type code marking an 8-byte double in IEEE 754 format.
Definition: dbus-protocol.h:98
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...
#define DBUS_TYPE_ARRAY
Type code marking a D-Bus array type.
#define DBUS_TYPE_INT64
Type code marking a 64-bit signed integer.
Definition: dbus-protocol.h:90
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_uint32_t _dbus_unpack_uint32(int byte_order, const unsigned char *data)
Unpacks a 32 bit unsigned integer from a data pointer.
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_type_is_basic(int typecode)
A "basic type" is a somewhat arbitrary concept, but the intent is to include those types that are ful...
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:35
can't determine validity due to OOM
#define VALID_BUS_NAME_CHARACTER(c)
Determine wether the given character is valid as a second or later character in a bus name...
dbus_bool_t _dbus_list_append(DBusList **list, void *data)
Appends a value to the list.
Definition: dbus-list.c:270
#define DBUS_TYPE_INT32
Type code marking a 32-bit signed integer.
Definition: dbus-protocol.h:82
#define DBUS_MAXIMUM_SIGNATURE_LENGTH
This one is 255 so it fits in a byte.
dbus_bool_t _dbus_type_reader_next(DBusTypeReader *reader)
Skip to the next value on this "level".
dbus_bool_t _dbus_string_validate_utf8(const DBusString *str, int start, int len)
Checks that the given range of the string is valid UTF-8.
Definition: dbus-string.c:2537
#define _DBUS_POINTER_TO_INT(pointer)
Safely casts a void* to an integer; should only be used on void* that actually contain integers...
#define DBUS_TYPE_SIGNATURE
Type code marking a D-Bus type signature.
#define DBUS_TYPE_UINT64
Type code marking a 64-bit unsigned integer.
Definition: dbus-protocol.h:94
#define DBUS_STRUCT_BEGIN_CHAR
Code marking the start of a struct type in a type signature.
#define DBUS_TYPE_VARIANT
Type code marking a D-Bus variant type.
#define DEFINE_DBUS_NAME_CHECK(what)
Define a name check to be used in _dbus_return_if_fail() statements.
#define _DBUS_N_ELEMENTS(array)
Computes the number of elements in a fixed-size array using sizeof().
#define DBUS_TYPE_UINT32
Type code marking a 32-bit unsigned integer.
Definition: dbus-protocol.h:86
#define VALID_INITIAL_NAME_CHARACTER(c)
Determine wether the given character is valid as the first character in a name.
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
#define VALID_NAME_CHARACTER(c)
Determine wether the given character is valid as a second or later character in a name...
The type reader is an iterator for reading values from a block of values.
#define TRUE
Expands to "1".
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
#define DBUS_TYPE_OBJECT_PATH
Type code marking a D-Bus object path.
#define DBUS_TYPE_UNIX_FD
Type code marking a unix file descriptor.
#define DBUS_TYPE_INVALID
Type code that is never equal to a legitimate type code.
Definition: dbus-protocol.h:60
#define DBUS_MAXIMUM_ARRAY_LENGTH
Max length of a marshaled array in bytes (64M, 2^26) We use signed int for lengths so must be INT_MAX...
A node in a linked list.
Definition: dbus-list.h:34
#define DBUS_TYPE_INT16
Type code marking a 16-bit signed integer.
Definition: dbus-protocol.h:74
#define DBUS_TYPE_BOOLEAN
Type code marking a boolean.
Definition: dbus-protocol.h:70
int _dbus_type_reader_get_element_type(const DBusTypeReader *reader)
Gets the type of an element of the array the reader is currently pointing to.
#define _DBUS_INT32_MAX
Maximum value of type "int32".
int _dbus_type_reader_get_current_type(const DBusTypeReader *reader)
Gets the type of the value the reader is currently pointing to; or for a types-only reader gets the t...
#define FALSE
Expands to "0".
#define DBUS_DICT_ENTRY_END_CHAR
Code marking the end of a dict entry type in a type signature.
const char * _dbus_type_to_string(int typecode)
Returns a string describing the given type.
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.
int _dbus_type_get_alignment(int typecode)
Gets the alignment requirement for the given type; will be 1, 4, or 8.
void _dbus_string_init_const_len(DBusString *str, const char *value, int len)
Initializes a constant string with a length.
Definition: dbus-string.c:210
#define VALID_INITIAL_BUS_NAME_CHARACTER(c)
Determine wether the given character is valid as the first character in a bus name.
dbus_bool_t dbus_type_is_valid(int typecode)
Return TRUE if the argument is a valid typecode.
void _dbus_list_clear(DBusList **list)
Frees all links in the list and sets the list head to NULL.
Definition: dbus-list.c:542