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