1 /* -*- mode: C; c-file-style: "gnu" -*- */ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 * 22 */ 23 24 #include "dbus-internals.h" 25 #include "dbus-marshal-validate.h" 26 #include "dbus-marshal-recursive.h" 27 #include "dbus-marshal-basic.h" 28 #include "dbus-signature.h" 29 #include "dbus-string.h" 30 31 /** 32 * @addtogroup DBusMarshal 33 * 34 * @{ 35 */ 36 37 /** 38 * Verifies that the range of type_str from type_pos to type_end is a 39 * valid signature. If this function returns #TRUE, it will be safe 40 * to iterate over the signature with a types-only #DBusTypeReader. 41 * The range passed in should NOT include the terminating 42 * nul/DBUS_TYPE_INVALID. 43 * 44 * @param type_str the string 45 * @param type_pos where the typecodes start 46 * @param len length of typecodes 47 * @returns #DBUS_VALID if valid, reason why invalid otherwise 48 */ 49 DBusValidity 50 _dbus_validate_signature_with_reason (const DBusString *type_str, 51 int type_pos, 52 int len) 53 { 54 const unsigned char *p; 55 const unsigned char *end; 56 int last; 57 int struct_depth; 58 int array_depth; 59 int dict_entry_depth; 60 DBusValidity result; 61 62 int element_count; 63 DBusList *element_count_stack; 64 65 result = DBUS_VALID; 66 element_count_stack = NULL; 67 68 if (!_dbus_list_append (&element_count_stack, _DBUS_INT_TO_POINTER (0))) 69 { 70 result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR; 71 goto out; 72 } 73 74 _dbus_assert (type_str != NULL); 75 _dbus_assert (type_pos < _DBUS_INT32_MAX - len); 76 _dbus_assert (len >= 0); 77 _dbus_assert (type_pos >= 0); 78 79 if (len > DBUS_MAXIMUM_SIGNATURE_LENGTH) 80 { 81 result = DBUS_INVALID_SIGNATURE_TOO_LONG; 82 goto out; 83 } 84 85 p = _dbus_string_get_const_data_len (type_str, type_pos, 0); 86 87 end = _dbus_string_get_const_data_len (type_str, type_pos + len, 0); 88 struct_depth = 0; 89 array_depth = 0; 90 dict_entry_depth = 0; 91 last = DBUS_TYPE_INVALID; 92 93 while (p != end) 94 { 95 switch (*p) 96 { 97 case DBUS_TYPE_BYTE: 98 case DBUS_TYPE_BOOLEAN: 99 case DBUS_TYPE_INT16: 100 case DBUS_TYPE_UINT16: 101 case DBUS_TYPE_INT32: 102 case DBUS_TYPE_UINT32: 103 case DBUS_TYPE_INT64: 104 case DBUS_TYPE_UINT64: 105 case DBUS_TYPE_DOUBLE: 106 case DBUS_TYPE_STRING: 107 case DBUS_TYPE_OBJECT_PATH: 108 case DBUS_TYPE_SIGNATURE: 109 case DBUS_TYPE_VARIANT: 110 break; 111 112 case DBUS_TYPE_ARRAY: 113 array_depth += 1; 114 if (array_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH) 115 { 116 result = DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION; 117 goto out; 118 } 119 break; 120 121 case DBUS_STRUCT_BEGIN_CHAR: 122 struct_depth += 1; 123 124 if (struct_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH) 125 { 126 result = DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION; 127 goto out; 128 } 129 130 if (!_dbus_list_append (&element_count_stack, 131 _DBUS_INT_TO_POINTER (0))) 132 { 133 result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR; 134 goto out; 135 } 136 137 break; 138 139 case DBUS_STRUCT_END_CHAR: 140 if (struct_depth == 0) 141 { 142 result = DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED; 143 goto out; 144 } 145 146 if (last == DBUS_STRUCT_BEGIN_CHAR) 147 { 148 result = DBUS_INVALID_STRUCT_HAS_NO_FIELDS; 149 goto out; 150 } 151 152 _dbus_list_pop_last (&element_count_stack); 153 154 struct_depth -= 1; 155 break; 156 157 case DBUS_DICT_ENTRY_BEGIN_CHAR: 158 if (last != DBUS_TYPE_ARRAY) 159 { 160 result = DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY; 161 goto out; 162 } 163 164 dict_entry_depth += 1; 165 166 if (dict_entry_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH) 167 { 168 result = DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION; 169 goto out; 170 } 171 172 if (!_dbus_list_append (&element_count_stack, 173 _DBUS_INT_TO_POINTER (0))) 174 { 175 result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR; 176 goto out; 177 } 178 179 break; 180 181 case DBUS_DICT_ENTRY_END_CHAR: 182 if (dict_entry_depth == 0) 183 { 184 result = DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED; 185 goto out; 186 } 187 188 dict_entry_depth -= 1; 189 190 element_count = 191 _DBUS_POINTER_TO_INT (_dbus_list_pop_last (&element_count_stack)); 192 193 if (element_count != 2) 194 { 195 if (element_count == 0) 196 result = DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS; 197 else if (element_count == 1) 198 result = DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD; 199 else 200 result = DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS; 201 202 goto out; 203 } 204 break; 205 206 case DBUS_TYPE_STRUCT: /* doesn't appear in signatures */ 207 case DBUS_TYPE_DICT_ENTRY: /* ditto */ 208 default: 209 result = DBUS_INVALID_UNKNOWN_TYPECODE; 210 goto out; 211 } 212 213 if (*p != DBUS_TYPE_ARRAY && 214 *p != DBUS_DICT_ENTRY_BEGIN_CHAR && 215 *p != DBUS_STRUCT_BEGIN_CHAR) 216 { 217 element_count = 218 _DBUS_POINTER_TO_INT (_dbus_list_pop_last (&element_count_stack)); 219 220 ++element_count; 221 222 if (!_dbus_list_append (&element_count_stack, 223 _DBUS_INT_TO_POINTER (element_count))) 224 { 225 result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR; 226 goto out; 227 } 228 } 229 230 if (array_depth > 0) 231 { 232 if (*p == DBUS_TYPE_ARRAY && p != end) 233 { 234 const char *p1; 235 p1 = p + 1; 236 if (*p1 == DBUS_STRUCT_END_CHAR || 237 *p1 == DBUS_DICT_ENTRY_END_CHAR) 238 { 239 result = DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE; 240 goto out; 241 } 242 } 243 else 244 { 245 array_depth = 0; 246 } 247 } 248 249 if (last == DBUS_DICT_ENTRY_BEGIN_CHAR && 250 !dbus_type_is_basic (*p)) 251 { 252 result = DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE; 253 goto out; 254 } 255 256 last = *p; 257 ++p; 258 } 259 260 261 if (array_depth > 0) 262 { 263 result = DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE; 264 goto out; 265 } 266 267 if (struct_depth > 0) 268 { 269 result = DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED; 270 goto out; 271 } 272 273 if (dict_entry_depth > 0) 274 { 275 result = DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED; 276 goto out; 277 } 278 279 _dbus_assert (last != DBUS_TYPE_ARRAY); 280 _dbus_assert (last != DBUS_STRUCT_BEGIN_CHAR); 281 _dbus_assert (last != DBUS_DICT_ENTRY_BEGIN_CHAR); 282 283 result = DBUS_VALID; 284 285 out: 286 _dbus_list_clear (&element_count_stack); 287 return result; 288 } 289 290 static DBusValidity 291 validate_body_helper (DBusTypeReader *reader, 292 int byte_order, 293 dbus_bool_t walk_reader_to_end, 294 const unsigned char *p, 295 const unsigned char *end, 296 const unsigned char **new_p) 297 { 298 int current_type; 299 300 while ((current_type = _dbus_type_reader_get_current_type (reader)) != DBUS_TYPE_INVALID) 301 { 302 const unsigned char *a; 303 int alignment; 304 305 #if 0 306 _dbus_verbose (" validating value of type %s type reader %p type_pos %d p %p end %p %d remain\n", 307 _dbus_type_to_string (current_type), reader, reader->type_pos, p, end, 308 (int) (end - p)); 309 #endif 310 311 /* Guarantee that p has one byte to look at */ 312 if (p == end) 313 return DBUS_INVALID_NOT_ENOUGH_DATA; 314 315 switch (current_type) 316 { 317 case DBUS_TYPE_BYTE: 318 ++p; 319 break; 320 321 case DBUS_TYPE_BOOLEAN: 322 case DBUS_TYPE_INT16: 323 case DBUS_TYPE_UINT16: 324 case DBUS_TYPE_INT32: 325 case DBUS_TYPE_UINT32: 326 case DBUS_TYPE_INT64: 327 case DBUS_TYPE_UINT64: 328 case DBUS_TYPE_DOUBLE: 329 alignment = _dbus_type_get_alignment (current_type); 330 a = _DBUS_ALIGN_ADDRESS (p, alignment); 331 if (a >= end) 332 return DBUS_INVALID_NOT_ENOUGH_DATA; 333 while (p != a) 334 { 335 if (*p != '\0') 336 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 337 ++p; 338 } 339 340 if (current_type == DBUS_TYPE_BOOLEAN) 341 { 342 dbus_uint32_t v = _dbus_unpack_uint32 (byte_order, 343 p); 344 if (!(v == 0 || v == 1)) 345 return DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE; 346 } 347 348 p += alignment; 349 break; 350 351 case DBUS_TYPE_ARRAY: 352 case DBUS_TYPE_STRING: 353 case DBUS_TYPE_OBJECT_PATH: 354 { 355 dbus_uint32_t claimed_len; 356 357 a = _DBUS_ALIGN_ADDRESS (p, 4); 358 if (a + 4 > end) 359 return DBUS_INVALID_NOT_ENOUGH_DATA; 360 while (p != a) 361 { 362 if (*p != '\0') 363 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 364 ++p; 365 } 366 367 claimed_len = _dbus_unpack_uint32 (byte_order, p); 368 p += 4; 369 370 /* p may now be == end */ 371 _dbus_assert (p <= end); 372 373 if (current_type == DBUS_TYPE_ARRAY) 374 { 375 int array_elem_type = _dbus_type_reader_get_element_type (reader); 376 alignment = _dbus_type_get_alignment (array_elem_type); 377 p = _DBUS_ALIGN_ADDRESS (p, alignment); 378 } 379 380 if (claimed_len > (unsigned long) (end - p)) 381 return DBUS_INVALID_LENGTH_OUT_OF_BOUNDS; 382 383 if (current_type == DBUS_TYPE_OBJECT_PATH) 384 { 385 DBusString str; 386 _dbus_string_init_const_len (&str, p, claimed_len); 387 if (!_dbus_validate_path (&str, 0, 388 _dbus_string_get_length (&str))) 389 return DBUS_INVALID_BAD_PATH; 390 391 p += claimed_len; 392 } 393 else if (current_type == DBUS_TYPE_STRING) 394 { 395 DBusString str; 396 _dbus_string_init_const_len (&str, p, claimed_len); 397 if (!_dbus_string_validate_utf8 (&str, 0, 398 _dbus_string_get_length (&str))) 399 return DBUS_INVALID_BAD_UTF8_IN_STRING; 400 401 p += claimed_len; 402 } 403 else if (current_type == DBUS_TYPE_ARRAY && claimed_len > 0) 404 { 405 DBusTypeReader sub; 406 DBusValidity validity; 407 const unsigned char *array_end; 408 409 if (claimed_len > DBUS_MAXIMUM_ARRAY_LENGTH) 410 return DBUS_INVALID_ARRAY_LENGTH_EXCEEDS_MAXIMUM; 411 412 /* Remember that the reader is types only, so we can't 413 * use it to iterate over elements. It stays the same 414 * for all elements. 415 */ 416 _dbus_type_reader_recurse (reader, &sub); 417 418 array_end = p + claimed_len; 419 420 while (p < array_end) 421 { 422 /* FIXME we are calling a function per array element! very bad 423 * need if (dbus_type_is_fixed(elem_type)) here to just skip 424 * big blocks of ints/bytes/etc. 425 */ 426 427 validity = validate_body_helper (&sub, byte_order, FALSE, p, end, &p); 428 if (validity != DBUS_VALID) 429 return validity; 430 } 431 432 if (p != array_end) 433 return DBUS_INVALID_ARRAY_LENGTH_INCORRECT; 434 } 435 436 /* check nul termination */ 437 if (current_type != DBUS_TYPE_ARRAY) 438 { 439 if (p == end) 440 return DBUS_INVALID_NOT_ENOUGH_DATA; 441 442 if (*p != '\0') 443 return DBUS_INVALID_STRING_MISSING_NUL; 444 ++p; 445 } 446 } 447 break; 448 449 case DBUS_TYPE_SIGNATURE: 450 { 451 dbus_uint32_t claimed_len; 452 DBusString str; 453 DBusValidity validity; 454 455 claimed_len = *p; 456 ++p; 457 458 /* 1 is for nul termination */ 459 if (claimed_len + 1 > (unsigned long) (end - p)) 460 return DBUS_INVALID_SIGNATURE_LENGTH_OUT_OF_BOUNDS; 461 462 _dbus_string_init_const_len (&str, p, claimed_len); 463 validity = 464 _dbus_validate_signature_with_reason (&str, 0, 465 _dbus_string_get_length (&str)); 466 467 if (validity != DBUS_VALID) 468 return validity; 469 470 p += claimed_len; 471 472 _dbus_assert (p < end); 473 if (*p != DBUS_TYPE_INVALID) 474 return DBUS_INVALID_SIGNATURE_MISSING_NUL; 475 476 ++p; 477 478 _dbus_verbose ("p = %p end = %p claimed_len %u\n", p, end, claimed_len); 479 } 480 break; 481 482 case DBUS_TYPE_VARIANT: 483 { 484 /* 1 byte sig len, sig typecodes, align to 485 * contained-type-boundary, values. 486 */ 487 488 /* In addition to normal signature validation, we need to be sure 489 * the signature contains only a single (possibly container) type. 490 */ 491 dbus_uint32_t claimed_len; 492 DBusString sig; 493 DBusTypeReader sub; 494 DBusValidity validity; 495 int contained_alignment; 496 int contained_type; 497 DBusValidity reason; 498 499 claimed_len = *p; 500 ++p; 501 502 /* + 1 for nul */ 503 if (claimed_len + 1 > (unsigned long) (end - p)) 504 return DBUS_INVALID_VARIANT_SIGNATURE_LENGTH_OUT_OF_BOUNDS; 505 506 _dbus_string_init_const_len (&sig, p, claimed_len); 507 reason = _dbus_validate_signature_with_reason (&sig, 0, 508 _dbus_string_get_length (&sig)); 509 if (!(reason == DBUS_VALID)) 510 { 511 if (reason == DBUS_VALIDITY_UNKNOWN_OOM_ERROR) 512 return reason; 513 else 514 return DBUS_INVALID_VARIANT_SIGNATURE_BAD; 515 } 516 517 p += claimed_len; 518 519 if (*p != DBUS_TYPE_INVALID) 520 return DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL; 521 ++p; 522 523 contained_type = _dbus_first_type_in_signature (&sig, 0); 524 if (contained_type == DBUS_TYPE_INVALID) 525 return DBUS_INVALID_VARIANT_SIGNATURE_EMPTY; 526 527 contained_alignment = _dbus_type_get_alignment (contained_type); 528 529 a = _DBUS_ALIGN_ADDRESS (p, contained_alignment); 530 if (a > end) 531 return DBUS_INVALID_NOT_ENOUGH_DATA; 532 while (p != a) 533 { 534 if (*p != '\0') 535 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 536 ++p; 537 } 538 539 _dbus_type_reader_init_types_only (&sub, &sig, 0); 540 541 _dbus_assert (_dbus_type_reader_get_current_type (&sub) != DBUS_TYPE_INVALID); 542 543 validity = validate_body_helper (&sub, byte_order, FALSE, p, end, &p); 544 if (validity != DBUS_VALID) 545 return validity; 546 547 if (_dbus_type_reader_next (&sub)) 548 return DBUS_INVALID_VARIANT_SIGNATURE_SPECIFIES_MULTIPLE_VALUES; 549 550 _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_INVALID); 551 } 552 break; 553 554 case DBUS_TYPE_DICT_ENTRY: 555 case DBUS_TYPE_STRUCT: 556 { 557 DBusTypeReader sub; 558 DBusValidity validity; 559 560 a = _DBUS_ALIGN_ADDRESS (p, 8); 561 if (a > end) 562 return DBUS_INVALID_NOT_ENOUGH_DATA; 563 while (p != a) 564 { 565 if (*p != '\0') 566 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 567 ++p; 568 } 569 570 _dbus_type_reader_recurse (reader, &sub); 571 572 validity = validate_body_helper (&sub, byte_order, TRUE, p, end, &p); 573 if (validity != DBUS_VALID) 574 return validity; 575 } 576 break; 577 578 default: 579 _dbus_assert_not_reached ("invalid typecode in supposedly-validated signature"); 580 break; 581 } 582 583 #if 0 584 _dbus_verbose (" validated value of type %s type reader %p type_pos %d p %p end %p %d remain\n", 585 _dbus_type_to_string (current_type), reader, reader->type_pos, p, end, 586 (int) (end - p)); 587 #endif 588 589 if (p > end) 590 { 591 _dbus_verbose ("not enough data!!! p = %p end = %p end-p = %d\n", 592 p, end, (int) (end - p)); 593 return DBUS_INVALID_NOT_ENOUGH_DATA; 594 } 595 596 if (walk_reader_to_end) 597 _dbus_type_reader_next (reader); 598 else 599 break; 600 } 601 602 if (new_p) 603 *new_p = p; 604 605 return DBUS_VALID; 606 } 607 608 /** 609 * Verifies that the range of value_str from value_pos to value_end is 610 * a legitimate value of type expected_signature. If this function 611 * returns #TRUE, it will be safe to iterate over the values with 612 * #DBusTypeReader. The signature is assumed to be already valid. 613 * 614 * If bytes_remaining is not #NULL, then leftover bytes will be stored 615 * there and #DBUS_VALID returned. If it is #NULL, then 616 * #DBUS_INVALID_TOO_MUCH_DATA will be returned if bytes are left 617 * over. 618 * 619 * @param expected_signature the expected types in the value_str 620 * @param expected_signature_start where in expected_signature is the signature 621 * @param byte_order the byte order 622 * @param bytes_remaining place to store leftover bytes 623 * @param value_str the string containing the body 624 * @param value_pos where the values start 625 * @param len length of values after value_pos 626 * @returns #DBUS_VALID if valid, reason why invalid otherwise 627 */ 628 DBusValidity 629 _dbus_validate_body_with_reason (const DBusString *expected_signature, 630 int expected_signature_start, 631 int byte_order, 632 int *bytes_remaining, 633 const DBusString *value_str, 634 int value_pos, 635 int len) 636 { 637 DBusTypeReader reader; 638 const unsigned char *p; 639 const unsigned char *end; 640 DBusValidity validity; 641 642 _dbus_assert (len >= 0); 643 _dbus_assert (value_pos >= 0); 644 _dbus_assert (value_pos <= _dbus_string_get_length (value_str) - len); 645 646 _dbus_verbose ("validating body from pos %d len %d sig '%s'\n", 647 value_pos, len, _dbus_string_get_const_data_len (expected_signature, 648 expected_signature_start, 649 0)); 650 651 _dbus_type_reader_init_types_only (&reader, 652 expected_signature, expected_signature_start); 653 654 p = _dbus_string_get_const_data_len (value_str, value_pos, len); 655 end = p + len; 656 657 validity = validate_body_helper (&reader, byte_order, TRUE, p, end, &p); 658 if (validity != DBUS_VALID) 659 return validity; 660 661 if (bytes_remaining) 662 { 663 *bytes_remaining = end - p; 664 return DBUS_VALID; 665 } 666 else if (p < end) 667 return DBUS_INVALID_TOO_MUCH_DATA; 668 else 669 { 670 _dbus_assert (p == end); 671 return DBUS_VALID; 672 } 673 } 674 675 /** 676 * Determine wether the given character is valid as the first character 677 * in a name. 678 */ 679 #define VALID_INITIAL_NAME_CHARACTER(c) \ 680 ( ((c) >= 'A' && (c) <= 'Z') || \ 681 ((c) >= 'a' && (c) <= 'z') || \ 682 ((c) == '_') ) 683 684 /** 685 * Determine wether the given character is valid as a second or later 686 * character in a name 687 */ 688 #define VALID_NAME_CHARACTER(c) \ 689 ( ((c) >= '0' && (c) <= '9') || \ 690 ((c) >= 'A' && (c) <= 'Z') || \ 691 ((c) >= 'a' && (c) <= 'z') || \ 692 ((c) == '_') ) 693 694 /** 695 * Checks that the given range of the string is a valid object path 696 * name in the D-Bus protocol. Part of the validation ensures that 697 * the object path contains only ASCII. 698 * 699 * @todo this is inconsistent with most of DBusString in that 700 * it allows a start,len range that extends past the string end. 701 * 702 * @todo change spec to disallow more things, such as spaces in the 703 * path name 704 * 705 * @param str the string 706 * @param start first byte index to check 707 * @param len number of bytes to check 708 * @returns #TRUE if the byte range exists and is a valid name 709 */ 710 dbus_bool_t 711 _dbus_validate_path (const DBusString *str, 712 int start, 713 int len) 714 { 715 const unsigned char *s; 716 const unsigned char *end; 717 const unsigned char *last_slash; 718 719 _dbus_assert (start >= 0); 720 _dbus_assert (len >= 0); 721 _dbus_assert (start <= _dbus_string_get_length (str)); 722 723 if (len > _dbus_string_get_length (str) - start) 724 return FALSE; 725 726 if (len == 0) 727 return FALSE; 728 729 s = _dbus_string_get_const_data (str) + start; 730 end = s + len; 731 732 if (*s != '/') 733 return FALSE; 734 last_slash = s; 735 ++s; 736 737 while (s != end) 738 { 739 if (*s == '/') 740 { 741 if ((s - last_slash) < 2) 742 return FALSE; /* no empty path components allowed */ 743 744 last_slash = s; 745 } 746 else 747 { 748 if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s))) 749 return FALSE; 750 } 751 752 ++s; 753 } 754 755 if ((end - last_slash) < 2 && 756 len > 1) 757 return FALSE; /* trailing slash not allowed unless the string is "/" */ 758 759 return TRUE; 760 } 761 762 /** 763 * Checks that the given range of the string is a valid interface name 764 * in the D-Bus protocol. This includes a length restriction and an 765 * ASCII subset, see the specification. 766 * 767 * @todo this is inconsistent with most of DBusString in that 768 * it allows a start,len range that extends past the string end. 769 * 770 * @param str the string 771 * @param start first byte index to check 772 * @param len number of bytes to check 773 * @returns #TRUE if the byte range exists and is a valid name 774 */ 775 dbus_bool_t 776 _dbus_validate_interface (const DBusString *str, 777 int start, 778 int len) 779 { 780 const unsigned char *s; 781 const unsigned char *end; 782 const unsigned char *iface; 783 const unsigned char *last_dot; 784 785 _dbus_assert (start >= 0); 786 _dbus_assert (len >= 0); 787 _dbus_assert (start <= _dbus_string_get_length (str)); 788 789 if (len > _dbus_string_get_length (str) - start) 790 return FALSE; 791 792 if (len > DBUS_MAXIMUM_NAME_LENGTH) 793 return FALSE; 794 795 if (len == 0) 796 return FALSE; 797 798 last_dot = NULL; 799 iface = _dbus_string_get_const_data (str) + start; 800 end = iface + len; 801 s = iface; 802 803 /* check special cases of first char so it doesn't have to be done 804 * in the loop. Note we know len > 0 805 */ 806 if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */ 807 return FALSE; 808 else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s))) 809 return FALSE; 810 else 811 ++s; 812 813 while (s != end) 814 { 815 if (*s == '.') 816 { 817 if (_DBUS_UNLIKELY ((s + 1) == end)) 818 return FALSE; 819 else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*(s + 1)))) 820 return FALSE; 821 last_dot = s; 822 ++s; /* we just validated the next char, so skip two */ 823 } 824 else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s))) 825 { 826 return FALSE; 827 } 828 829 ++s; 830 } 831 832 if (_DBUS_UNLIKELY (last_dot == NULL)) 833 return FALSE; 834 835 return TRUE; 836 } 837 838 /** 839 * Checks that the given range of the string is a valid member name 840 * in the D-Bus protocol. This includes a length restriction, etc., 841 * see the specification. 842 * 843 * @todo this is inconsistent with most of DBusString in that 844 * it allows a start,len range that extends past the string end. 845 * 846 * @param str the string 847 * @param start first byte index to check 848 * @param len number of bytes to check 849 * @returns #TRUE if the byte range exists and is a valid name 850 */ 851 dbus_bool_t 852 _dbus_validate_member (const DBusString *str, 853 int start, 854 int len) 855 { 856 const unsigned char *s; 857 const unsigned char *end; 858 const unsigned char *member; 859 860 _dbus_assert (start >= 0); 861 _dbus_assert (len >= 0); 862 _dbus_assert (start <= _dbus_string_get_length (str)); 863 864 if (len > _dbus_string_get_length (str) - start) 865 return FALSE; 866 867 if (len > DBUS_MAXIMUM_NAME_LENGTH) 868 return FALSE; 869 870 if (len == 0) 871 return FALSE; 872 873 member = _dbus_string_get_const_data (str) + start; 874 end = member + len; 875 s = member; 876 877 /* check special cases of first char so it doesn't have to be done 878 * in the loop. Note we know len > 0 879 */ 880 881 if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s))) 882 return FALSE; 883 else 884 ++s; 885 886 while (s != end) 887 { 888 if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s))) 889 { 890 return FALSE; 891 } 892 893 ++s; 894 } 895 896 return TRUE; 897 } 898 899 /** 900 * Checks that the given range of the string is a valid error name 901 * in the D-Bus protocol. This includes a length restriction, etc., 902 * see the specification. 903 * 904 * @todo this is inconsistent with most of DBusString in that 905 * it allows a start,len range that extends past the string end. 906 * 907 * @param str the string 908 * @param start first byte index to check 909 * @param len number of bytes to check 910 * @returns #TRUE if the byte range exists and is a valid name 911 */ 912 dbus_bool_t 913 _dbus_validate_error_name (const DBusString *str, 914 int start, 915 int len) 916 { 917 /* Same restrictions as interface name at the moment */ 918 return _dbus_validate_interface (str, start, len); 919 } 920 921 /** 922 * Determine wether the given character is valid as the first character 923 * in a bus name. 924 */ 925 #define VALID_INITIAL_BUS_NAME_CHARACTER(c) \ 926 ( ((c) >= 'A' && (c) <= 'Z') || \ 927 ((c) >= 'a' && (c) <= 'z') || \ 928 ((c) == '_') || ((c) == '-')) 929 930 /** 931 * Determine wether the given character is valid as a second or later 932 * character in a bus name 933 */ 934 #define VALID_BUS_NAME_CHARACTER(c) \ 935 ( ((c) >= '0' && (c) <= '9') || \ 936 ((c) >= 'A' && (c) <= 'Z') || \ 937 ((c) >= 'a' && (c) <= 'z') || \ 938 ((c) == '_') || ((c) == '-')) 939 940 /** 941 * Checks that the given range of the string is a valid bus name in 942 * the D-Bus protocol. This includes a length restriction, etc., see 943 * the specification. 944 * 945 * @todo this is inconsistent with most of DBusString in that 946 * it allows a start,len range that extends past the string end. 947 * 948 * @param str the string 949 * @param start first byte index to check 950 * @param len number of bytes to check 951 * @returns #TRUE if the byte range exists and is a valid name 952 */ 953 dbus_bool_t 954 _dbus_validate_bus_name (const DBusString *str, 955 int start, 956 int len) 957 { 958 const unsigned char *s; 959 const unsigned char *end; 960 const unsigned char *iface; 961 const unsigned char *last_dot; 962 963 _dbus_assert (start >= 0); 964 _dbus_assert (len >= 0); 965 _dbus_assert (start <= _dbus_string_get_length (str)); 966 967 if (len > _dbus_string_get_length (str) - start) 968 return FALSE; 969 970 if (len > DBUS_MAXIMUM_NAME_LENGTH) 971 return FALSE; 972 973 if (len == 0) 974 return FALSE; 975 976 last_dot = NULL; 977 iface = _dbus_string_get_const_data (str) + start; 978 end = iface + len; 979 s = iface; 980 981 /* check special cases of first char so it doesn't have to be done 982 * in the loop. Note we know len > 0 983 */ 984 if (*s == ':') 985 { 986 /* unique name */ 987 ++s; 988 while (s != end) 989 { 990 if (*s == '.') 991 { 992 if (_DBUS_UNLIKELY ((s + 1) == end)) 993 return FALSE; 994 if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*(s + 1)))) 995 return FALSE; 996 ++s; /* we just validated the next char, so skip two */ 997 } 998 else if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*s))) 999 { 1000 return FALSE; 1001 } 1002 1003 ++s; 1004 } 1005 1006 return TRUE; 1007 } 1008 else if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */ 1009 return FALSE; 1010 else if (_DBUS_UNLIKELY (!VALID_INITIAL_BUS_NAME_CHARACTER (*s))) 1011 return FALSE; 1012 else 1013 ++s; 1014 1015 while (s != end) 1016 { 1017 if (*s == '.') 1018 { 1019 if (_DBUS_UNLIKELY ((s + 1) == end)) 1020 return FALSE; 1021 else if (_DBUS_UNLIKELY (!VALID_INITIAL_BUS_NAME_CHARACTER (*(s + 1)))) 1022 return FALSE; 1023 last_dot = s; 1024 ++s; /* we just validated the next char, so skip two */ 1025 } 1026 else if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*s))) 1027 { 1028 return FALSE; 1029 } 1030 1031 ++s; 1032 } 1033 1034 if (_DBUS_UNLIKELY (last_dot == NULL)) 1035 return FALSE; 1036 1037 return TRUE; 1038 } 1039 1040 /** 1041 * Checks that the given range of the string is a valid message type 1042 * signature in the D-Bus protocol. 1043 * 1044 * @todo this is inconsistent with most of DBusString in that 1045 * it allows a start,len range that extends past the string end. 1046 * 1047 * @param str the string 1048 * @param start first byte index to check 1049 * @param len number of bytes to check 1050 * @returns #TRUE if the byte range exists and is a valid signature 1051 */ 1052 dbus_bool_t 1053 _dbus_validate_signature (const DBusString *str, 1054 int start, 1055 int len) 1056 { 1057 _dbus_assert (start >= 0); 1058 _dbus_assert (start <= _dbus_string_get_length (str)); 1059 _dbus_assert (len >= 0); 1060 1061 if (len > _dbus_string_get_length (str) - start) 1062 return FALSE; 1063 1064 return _dbus_validate_signature_with_reason (str, start, len) == DBUS_VALID; 1065 } 1066 1067 /** define _dbus_check_is_valid_path() */ 1068 DEFINE_DBUS_NAME_CHECK(path); 1069 /** define _dbus_check_is_valid_interface() */ 1070 DEFINE_DBUS_NAME_CHECK(interface); 1071 /** define _dbus_check_is_valid_member() */ 1072 DEFINE_DBUS_NAME_CHECK(member); 1073 /** define _dbus_check_is_valid_error_name() */ 1074 DEFINE_DBUS_NAME_CHECK(error_name); 1075 /** define _dbus_check_is_valid_bus_name() */ 1076 DEFINE_DBUS_NAME_CHECK(bus_name); 1077 /** define _dbus_check_is_valid_signature() */ 1078 DEFINE_DBUS_NAME_CHECK(signature); 1079 1080 /** @} */ 1081 1082 /* tests in dbus-marshal-validate-util.c */ 1083