dbus-marshal-validate.c revision e61f13cf328d131ddbd8b49842fcd0f49847dbff
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., 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 */ 49DBusValidity 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_valid (*p) && 251 !dbus_type_is_basic (*p)) 252 { 253 result = DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE; 254 goto out; 255 } 256 257 last = *p; 258 ++p; 259 } 260 261 262 if (array_depth > 0) 263 { 264 result = DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE; 265 goto out; 266 } 267 268 if (struct_depth > 0) 269 { 270 result = DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED; 271 goto out; 272 } 273 274 if (dict_entry_depth > 0) 275 { 276 result = DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED; 277 goto out; 278 } 279 280 _dbus_assert (last != DBUS_TYPE_ARRAY); 281 _dbus_assert (last != DBUS_STRUCT_BEGIN_CHAR); 282 _dbus_assert (last != DBUS_DICT_ENTRY_BEGIN_CHAR); 283 284 result = DBUS_VALID; 285 286out: 287 _dbus_list_clear (&element_count_stack); 288 return result; 289} 290 291static DBusValidity 292validate_body_helper (DBusTypeReader *reader, 293 int byte_order, 294 dbus_bool_t walk_reader_to_end, 295 const unsigned char *p, 296 const unsigned char *end, 297 const unsigned char **new_p) 298{ 299 int current_type; 300 301 while ((current_type = _dbus_type_reader_get_current_type (reader)) != DBUS_TYPE_INVALID) 302 { 303 const unsigned char *a; 304 int alignment; 305 306#if 0 307 _dbus_verbose (" validating value of type %s type reader %p type_pos %d p %p end %p %d remain\n", 308 _dbus_type_to_string (current_type), reader, reader->type_pos, p, end, 309 (int) (end - p)); 310#endif 311 312 /* Guarantee that p has one byte to look at */ 313 if (p == end) 314 return DBUS_INVALID_NOT_ENOUGH_DATA; 315 316 switch (current_type) 317 { 318 case DBUS_TYPE_BYTE: 319 ++p; 320 break; 321 322 case DBUS_TYPE_BOOLEAN: 323 case DBUS_TYPE_INT16: 324 case DBUS_TYPE_UINT16: 325 case DBUS_TYPE_INT32: 326 case DBUS_TYPE_UINT32: 327 case DBUS_TYPE_INT64: 328 case DBUS_TYPE_UINT64: 329 case DBUS_TYPE_DOUBLE: 330 alignment = _dbus_type_get_alignment (current_type); 331 a = _DBUS_ALIGN_ADDRESS (p, alignment); 332 if (a >= end) 333 return DBUS_INVALID_NOT_ENOUGH_DATA; 334 while (p != a) 335 { 336 if (*p != '\0') 337 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 338 ++p; 339 } 340 341 if (current_type == DBUS_TYPE_BOOLEAN) 342 { 343 dbus_uint32_t v = _dbus_unpack_uint32 (byte_order, 344 p); 345 if (!(v == 0 || v == 1)) 346 return DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE; 347 } 348 349 p += alignment; 350 break; 351 352 case DBUS_TYPE_ARRAY: 353 case DBUS_TYPE_STRING: 354 case DBUS_TYPE_OBJECT_PATH: 355 { 356 dbus_uint32_t claimed_len; 357 358 a = _DBUS_ALIGN_ADDRESS (p, 4); 359 if (a + 4 > end) 360 return DBUS_INVALID_NOT_ENOUGH_DATA; 361 while (p != a) 362 { 363 if (*p != '\0') 364 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 365 ++p; 366 } 367 368 claimed_len = _dbus_unpack_uint32 (byte_order, p); 369 p += 4; 370 371 /* p may now be == end */ 372 _dbus_assert (p <= end); 373 374 if (current_type == DBUS_TYPE_ARRAY) 375 { 376 int array_elem_type = _dbus_type_reader_get_element_type (reader); 377 378 if (!_dbus_type_is_valid (array_elem_type)) 379 { 380 return DBUS_INVALID_UNKNOWN_TYPECODE; 381 } 382 383 alignment = _dbus_type_get_alignment (array_elem_type); 384 385 a = _DBUS_ALIGN_ADDRESS (p, alignment); 386 387 /* a may now be == end */ 388 if (a > end) 389 return DBUS_INVALID_NOT_ENOUGH_DATA; 390 391 while (p != a) 392 { 393 if (*p != '\0') 394 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 395 ++p; 396 } 397 } 398 399 if (claimed_len > (unsigned long) (end - p)) 400 return DBUS_INVALID_LENGTH_OUT_OF_BOUNDS; 401 402 if (current_type == DBUS_TYPE_OBJECT_PATH) 403 { 404 DBusString str; 405 _dbus_string_init_const_len (&str, p, claimed_len); 406 if (!_dbus_validate_path (&str, 0, 407 _dbus_string_get_length (&str))) 408 return DBUS_INVALID_BAD_PATH; 409 410 p += claimed_len; 411 } 412 else if (current_type == DBUS_TYPE_STRING) 413 { 414 DBusString str; 415 _dbus_string_init_const_len (&str, p, claimed_len); 416 if (!_dbus_string_validate_utf8 (&str, 0, 417 _dbus_string_get_length (&str))) 418 return DBUS_INVALID_BAD_UTF8_IN_STRING; 419 420 p += claimed_len; 421 } 422 else if (current_type == DBUS_TYPE_ARRAY && claimed_len > 0) 423 { 424 DBusTypeReader sub; 425 DBusValidity validity; 426 const unsigned char *array_end; 427 int array_elem_type; 428 429 if (claimed_len > DBUS_MAXIMUM_ARRAY_LENGTH) 430 return DBUS_INVALID_ARRAY_LENGTH_EXCEEDS_MAXIMUM; 431 432 /* Remember that the reader is types only, so we can't 433 * use it to iterate over elements. It stays the same 434 * for all elements. 435 */ 436 _dbus_type_reader_recurse (reader, &sub); 437 438 array_end = p + claimed_len; 439 440 array_elem_type = _dbus_type_reader_get_element_type (reader); 441 442 /* avoid recursive call to validate_body_helper if this is an array 443 * of fixed-size elements 444 */ 445 if (dbus_type_is_fixed (array_elem_type)) 446 { 447 /* bools need to be handled differently, because they can 448 * have an invalid value 449 */ 450 if (array_elem_type == DBUS_TYPE_BOOLEAN) 451 { 452 dbus_uint32_t v; 453 alignment = _dbus_type_get_alignment (array_elem_type); 454 455 while (p < array_end) 456 { 457 v = _dbus_unpack_uint32 (byte_order, p); 458 459 if (!(v == 0 || v == 1)) 460 return DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE; 461 462 p += alignment; 463 } 464 } 465 466 else 467 { 468 p = array_end; 469 } 470 } 471 472 else 473 { 474 while (p < array_end) 475 { 476 validity = validate_body_helper (&sub, byte_order, FALSE, p, end, &p); 477 if (validity != DBUS_VALID) 478 return validity; 479 } 480 } 481 482 if (p != array_end) 483 return DBUS_INVALID_ARRAY_LENGTH_INCORRECT; 484 } 485 486 /* check nul termination */ 487 if (current_type != DBUS_TYPE_ARRAY) 488 { 489 if (p == end) 490 return DBUS_INVALID_NOT_ENOUGH_DATA; 491 492 if (*p != '\0') 493 return DBUS_INVALID_STRING_MISSING_NUL; 494 ++p; 495 } 496 } 497 break; 498 499 case DBUS_TYPE_SIGNATURE: 500 { 501 dbus_uint32_t claimed_len; 502 DBusString str; 503 DBusValidity validity; 504 505 claimed_len = *p; 506 ++p; 507 508 /* 1 is for nul termination */ 509 if (claimed_len + 1 > (unsigned long) (end - p)) 510 return DBUS_INVALID_SIGNATURE_LENGTH_OUT_OF_BOUNDS; 511 512 _dbus_string_init_const_len (&str, p, claimed_len); 513 validity = 514 _dbus_validate_signature_with_reason (&str, 0, 515 _dbus_string_get_length (&str)); 516 517 if (validity != DBUS_VALID) 518 return validity; 519 520 p += claimed_len; 521 522 _dbus_assert (p < end); 523 if (*p != DBUS_TYPE_INVALID) 524 return DBUS_INVALID_SIGNATURE_MISSING_NUL; 525 526 ++p; 527 528 _dbus_verbose ("p = %p end = %p claimed_len %u\n", p, end, claimed_len); 529 } 530 break; 531 532 case DBUS_TYPE_VARIANT: 533 { 534 /* 1 byte sig len, sig typecodes, align to 535 * contained-type-boundary, values. 536 */ 537 538 /* In addition to normal signature validation, we need to be sure 539 * the signature contains only a single (possibly container) type. 540 */ 541 dbus_uint32_t claimed_len; 542 DBusString sig; 543 DBusTypeReader sub; 544 DBusValidity validity; 545 int contained_alignment; 546 int contained_type; 547 DBusValidity reason; 548 549 claimed_len = *p; 550 ++p; 551 552 /* + 1 for nul */ 553 if (claimed_len + 1 > (unsigned long) (end - p)) 554 return DBUS_INVALID_VARIANT_SIGNATURE_LENGTH_OUT_OF_BOUNDS; 555 556 _dbus_string_init_const_len (&sig, p, claimed_len); 557 reason = _dbus_validate_signature_with_reason (&sig, 0, 558 _dbus_string_get_length (&sig)); 559 if (!(reason == DBUS_VALID)) 560 { 561 if (reason == DBUS_VALIDITY_UNKNOWN_OOM_ERROR) 562 return reason; 563 else 564 return DBUS_INVALID_VARIANT_SIGNATURE_BAD; 565 } 566 567 p += claimed_len; 568 569 if (*p != DBUS_TYPE_INVALID) 570 return DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL; 571 ++p; 572 573 contained_type = _dbus_first_type_in_signature (&sig, 0); 574 if (contained_type == DBUS_TYPE_INVALID) 575 return DBUS_INVALID_VARIANT_SIGNATURE_EMPTY; 576 577 contained_alignment = _dbus_type_get_alignment (contained_type); 578 579 a = _DBUS_ALIGN_ADDRESS (p, contained_alignment); 580 if (a > end) 581 return DBUS_INVALID_NOT_ENOUGH_DATA; 582 while (p != a) 583 { 584 if (*p != '\0') 585 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 586 ++p; 587 } 588 589 _dbus_type_reader_init_types_only (&sub, &sig, 0); 590 591 _dbus_assert (_dbus_type_reader_get_current_type (&sub) != DBUS_TYPE_INVALID); 592 593 validity = validate_body_helper (&sub, byte_order, FALSE, p, end, &p); 594 if (validity != DBUS_VALID) 595 return validity; 596 597 if (_dbus_type_reader_next (&sub)) 598 return DBUS_INVALID_VARIANT_SIGNATURE_SPECIFIES_MULTIPLE_VALUES; 599 600 _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_INVALID); 601 } 602 break; 603 604 case DBUS_TYPE_DICT_ENTRY: 605 case DBUS_TYPE_STRUCT: 606 { 607 DBusTypeReader sub; 608 DBusValidity validity; 609 610 a = _DBUS_ALIGN_ADDRESS (p, 8); 611 if (a > end) 612 return DBUS_INVALID_NOT_ENOUGH_DATA; 613 while (p != a) 614 { 615 if (*p != '\0') 616 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 617 ++p; 618 } 619 620 _dbus_type_reader_recurse (reader, &sub); 621 622 validity = validate_body_helper (&sub, byte_order, TRUE, p, end, &p); 623 if (validity != DBUS_VALID) 624 return validity; 625 } 626 break; 627 628 default: 629 _dbus_assert_not_reached ("invalid typecode in supposedly-validated signature"); 630 break; 631 } 632 633#if 0 634 _dbus_verbose (" validated value of type %s type reader %p type_pos %d p %p end %p %d remain\n", 635 _dbus_type_to_string (current_type), reader, reader->type_pos, p, end, 636 (int) (end - p)); 637#endif 638 639 if (p > end) 640 { 641 _dbus_verbose ("not enough data!!! p = %p end = %p end-p = %d\n", 642 p, end, (int) (end - p)); 643 return DBUS_INVALID_NOT_ENOUGH_DATA; 644 } 645 646 if (walk_reader_to_end) 647 _dbus_type_reader_next (reader); 648 else 649 break; 650 } 651 652 if (new_p) 653 *new_p = p; 654 655 return DBUS_VALID; 656} 657 658/** 659 * Verifies that the range of value_str from value_pos to value_end is 660 * a legitimate value of type expected_signature. If this function 661 * returns #TRUE, it will be safe to iterate over the values with 662 * #DBusTypeReader. The signature is assumed to be already valid. 663 * 664 * If bytes_remaining is not #NULL, then leftover bytes will be stored 665 * there and #DBUS_VALID returned. If it is #NULL, then 666 * #DBUS_INVALID_TOO_MUCH_DATA will be returned if bytes are left 667 * over. 668 * 669 * @param expected_signature the expected types in the value_str 670 * @param expected_signature_start where in expected_signature is the signature 671 * @param byte_order the byte order 672 * @param bytes_remaining place to store leftover bytes 673 * @param value_str the string containing the body 674 * @param value_pos where the values start 675 * @param len length of values after value_pos 676 * @returns #DBUS_VALID if valid, reason why invalid otherwise 677 */ 678DBusValidity 679_dbus_validate_body_with_reason (const DBusString *expected_signature, 680 int expected_signature_start, 681 int byte_order, 682 int *bytes_remaining, 683 const DBusString *value_str, 684 int value_pos, 685 int len) 686{ 687 DBusTypeReader reader; 688 const unsigned char *p; 689 const unsigned char *end; 690 DBusValidity validity; 691 692 _dbus_assert (len >= 0); 693 _dbus_assert (value_pos >= 0); 694 _dbus_assert (value_pos <= _dbus_string_get_length (value_str) - len); 695 696 _dbus_verbose ("validating body from pos %d len %d sig '%s'\n", 697 value_pos, len, _dbus_string_get_const_data_len (expected_signature, 698 expected_signature_start, 699 0)); 700 701 _dbus_type_reader_init_types_only (&reader, 702 expected_signature, expected_signature_start); 703 704 p = _dbus_string_get_const_data_len (value_str, value_pos, len); 705 end = p + len; 706 707 validity = validate_body_helper (&reader, byte_order, TRUE, p, end, &p); 708 if (validity != DBUS_VALID) 709 return validity; 710 711 if (bytes_remaining) 712 { 713 *bytes_remaining = end - p; 714 return DBUS_VALID; 715 } 716 else if (p < end) 717 return DBUS_INVALID_TOO_MUCH_DATA; 718 else 719 { 720 _dbus_assert (p == end); 721 return DBUS_VALID; 722 } 723} 724 725/** 726 * Determine wether the given character is valid as the first character 727 * in a name. 728 */ 729#define VALID_INITIAL_NAME_CHARACTER(c) \ 730 ( ((c) >= 'A' && (c) <= 'Z') || \ 731 ((c) >= 'a' && (c) <= 'z') || \ 732 ((c) == '_') ) 733 734/** 735 * Determine wether the given character is valid as a second or later 736 * character in a name 737 */ 738#define VALID_NAME_CHARACTER(c) \ 739 ( ((c) >= '0' && (c) <= '9') || \ 740 ((c) >= 'A' && (c) <= 'Z') || \ 741 ((c) >= 'a' && (c) <= 'z') || \ 742 ((c) == '_') ) 743 744/** 745 * Checks that the given range of the string is a valid object path 746 * name in the D-Bus protocol. Part of the validation ensures that 747 * the object path contains only ASCII. 748 * 749 * @todo this is inconsistent with most of DBusString in that 750 * it allows a start,len range that extends past the string end. 751 * 752 * @todo change spec to disallow more things, such as spaces in the 753 * path name 754 * 755 * @param str the string 756 * @param start first byte index to check 757 * @param len number of bytes to check 758 * @returns #TRUE if the byte range exists and is a valid name 759 */ 760dbus_bool_t 761_dbus_validate_path (const DBusString *str, 762 int start, 763 int len) 764{ 765 const unsigned char *s; 766 const unsigned char *end; 767 const unsigned char *last_slash; 768 769 _dbus_assert (start >= 0); 770 _dbus_assert (len >= 0); 771 _dbus_assert (start <= _dbus_string_get_length (str)); 772 773 if (len > _dbus_string_get_length (str) - start) 774 return FALSE; 775 776 if (len == 0) 777 return FALSE; 778 779 s = _dbus_string_get_const_data (str) + start; 780 end = s + len; 781 782 if (*s != '/') 783 return FALSE; 784 last_slash = s; 785 ++s; 786 787 while (s != end) 788 { 789 if (*s == '/') 790 { 791 if ((s - last_slash) < 2) 792 return FALSE; /* no empty path components allowed */ 793 794 last_slash = s; 795 } 796 else 797 { 798 if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s))) 799 return FALSE; 800 } 801 802 ++s; 803 } 804 805 if ((end - last_slash) < 2 && 806 len > 1) 807 return FALSE; /* trailing slash not allowed unless the string is "/" */ 808 809 return TRUE; 810} 811 812/** 813 * Checks that the given range of the string is a valid interface name 814 * in the D-Bus protocol. This includes a length restriction and an 815 * ASCII subset, see the specification. 816 * 817 * @todo this is inconsistent with most of DBusString in that 818 * it allows a start,len range that extends past the string end. 819 * 820 * @param str the string 821 * @param start first byte index to check 822 * @param len number of bytes to check 823 * @returns #TRUE if the byte range exists and is a valid name 824 */ 825dbus_bool_t 826_dbus_validate_interface (const DBusString *str, 827 int start, 828 int len) 829{ 830 const unsigned char *s; 831 const unsigned char *end; 832 const unsigned char *iface; 833 const unsigned char *last_dot; 834 835 _dbus_assert (start >= 0); 836 _dbus_assert (len >= 0); 837 _dbus_assert (start <= _dbus_string_get_length (str)); 838 839 if (len > _dbus_string_get_length (str) - start) 840 return FALSE; 841 842 if (len > DBUS_MAXIMUM_NAME_LENGTH) 843 return FALSE; 844 845 if (len == 0) 846 return FALSE; 847 848 last_dot = NULL; 849 iface = _dbus_string_get_const_data (str) + start; 850 end = iface + len; 851 s = iface; 852 853 /* check special cases of first char so it doesn't have to be done 854 * in the loop. Note we know len > 0 855 */ 856 if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */ 857 return FALSE; 858 else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s))) 859 return FALSE; 860 else 861 ++s; 862 863 while (s != end) 864 { 865 if (*s == '.') 866 { 867 if (_DBUS_UNLIKELY ((s + 1) == end)) 868 return FALSE; 869 else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*(s + 1)))) 870 return FALSE; 871 last_dot = s; 872 ++s; /* we just validated the next char, so skip two */ 873 } 874 else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s))) 875 { 876 return FALSE; 877 } 878 879 ++s; 880 } 881 882 if (_DBUS_UNLIKELY (last_dot == NULL)) 883 return FALSE; 884 885 return TRUE; 886} 887 888/** 889 * Checks that the given range of the string is a valid member name 890 * in the D-Bus protocol. This includes a length restriction, etc., 891 * see the specification. 892 * 893 * @todo this is inconsistent with most of DBusString in that 894 * it allows a start,len range that extends past the string end. 895 * 896 * @param str the string 897 * @param start first byte index to check 898 * @param len number of bytes to check 899 * @returns #TRUE if the byte range exists and is a valid name 900 */ 901dbus_bool_t 902_dbus_validate_member (const DBusString *str, 903 int start, 904 int len) 905{ 906 const unsigned char *s; 907 const unsigned char *end; 908 const unsigned char *member; 909 910 _dbus_assert (start >= 0); 911 _dbus_assert (len >= 0); 912 _dbus_assert (start <= _dbus_string_get_length (str)); 913 914 if (len > _dbus_string_get_length (str) - start) 915 return FALSE; 916 917 if (len > DBUS_MAXIMUM_NAME_LENGTH) 918 return FALSE; 919 920 if (len == 0) 921 return FALSE; 922 923 member = _dbus_string_get_const_data (str) + start; 924 end = member + len; 925 s = member; 926 927 /* check special cases of first char so it doesn't have to be done 928 * in the loop. Note we know len > 0 929 */ 930 931 if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s))) 932 return FALSE; 933 else 934 ++s; 935 936 while (s != end) 937 { 938 if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s))) 939 { 940 return FALSE; 941 } 942 943 ++s; 944 } 945 946 return TRUE; 947} 948 949/** 950 * Checks that the given range of the string is a valid error name 951 * in the D-Bus protocol. This includes a length restriction, etc., 952 * see the specification. 953 * 954 * @todo this is inconsistent with most of DBusString in that 955 * it allows a start,len range that extends past the string end. 956 * 957 * @param str the string 958 * @param start first byte index to check 959 * @param len number of bytes to check 960 * @returns #TRUE if the byte range exists and is a valid name 961 */ 962dbus_bool_t 963_dbus_validate_error_name (const DBusString *str, 964 int start, 965 int len) 966{ 967 /* Same restrictions as interface name at the moment */ 968 return _dbus_validate_interface (str, start, len); 969} 970 971/** 972 * Determine wether the given character is valid as the first character 973 * in a bus name. 974 */ 975#define VALID_INITIAL_BUS_NAME_CHARACTER(c) \ 976 ( ((c) >= 'A' && (c) <= 'Z') || \ 977 ((c) >= 'a' && (c) <= 'z') || \ 978 ((c) == '_') || ((c) == '-')) 979 980/** 981 * Determine wether the given character is valid as a second or later 982 * character in a bus name 983 */ 984#define VALID_BUS_NAME_CHARACTER(c) \ 985 ( ((c) >= '0' && (c) <= '9') || \ 986 ((c) >= 'A' && (c) <= 'Z') || \ 987 ((c) >= 'a' && (c) <= 'z') || \ 988 ((c) == '_') || ((c) == '-')) 989 990/** 991 * Checks that the given range of the string is a valid bus name in 992 * the D-Bus protocol. This includes a length restriction, etc., see 993 * the specification. 994 * 995 * @todo this is inconsistent with most of DBusString in that 996 * it allows a start,len range that extends past the string end. 997 * 998 * @param str the string 999 * @param start first byte index to check 1000 * @param len number of bytes to check 1001 * @returns #TRUE if the byte range exists and is a valid name 1002 */ 1003dbus_bool_t 1004_dbus_validate_bus_name (const DBusString *str, 1005 int start, 1006 int len) 1007{ 1008 const unsigned char *s; 1009 const unsigned char *end; 1010 const unsigned char *iface; 1011 const unsigned char *last_dot; 1012 1013 _dbus_assert (start >= 0); 1014 _dbus_assert (len >= 0); 1015 _dbus_assert (start <= _dbus_string_get_length (str)); 1016 1017 if (len > _dbus_string_get_length (str) - start) 1018 return FALSE; 1019 1020 if (len > DBUS_MAXIMUM_NAME_LENGTH) 1021 return FALSE; 1022 1023 if (len == 0) 1024 return FALSE; 1025 1026 last_dot = NULL; 1027 iface = _dbus_string_get_const_data (str) + start; 1028 end = iface + len; 1029 s = iface; 1030 1031 /* check special cases of first char so it doesn't have to be done 1032 * in the loop. Note we know len > 0 1033 */ 1034 if (*s == ':') 1035 { 1036 /* unique name */ 1037 ++s; 1038 while (s != end) 1039 { 1040 if (*s == '.') 1041 { 1042 if (_DBUS_UNLIKELY ((s + 1) == end)) 1043 return FALSE; 1044 if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*(s + 1)))) 1045 return FALSE; 1046 ++s; /* we just validated the next char, so skip two */ 1047 } 1048 else if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*s))) 1049 { 1050 return FALSE; 1051 } 1052 1053 ++s; 1054 } 1055 1056 return TRUE; 1057 } 1058 else if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */ 1059 return FALSE; 1060 else if (_DBUS_UNLIKELY (!VALID_INITIAL_BUS_NAME_CHARACTER (*s))) 1061 return FALSE; 1062 else 1063 ++s; 1064 1065 while (s != end) 1066 { 1067 if (*s == '.') 1068 { 1069 if (_DBUS_UNLIKELY ((s + 1) == end)) 1070 return FALSE; 1071 else if (_DBUS_UNLIKELY (!VALID_INITIAL_BUS_NAME_CHARACTER (*(s + 1)))) 1072 return FALSE; 1073 last_dot = s; 1074 ++s; /* we just validated the next char, so skip two */ 1075 } 1076 else if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*s))) 1077 { 1078 return FALSE; 1079 } 1080 1081 ++s; 1082 } 1083 1084 if (_DBUS_UNLIKELY (last_dot == NULL)) 1085 return FALSE; 1086 1087 return TRUE; 1088} 1089 1090/** 1091 * Checks that the given range of the string is a valid message type 1092 * signature in the D-Bus protocol. 1093 * 1094 * @todo this is inconsistent with most of DBusString in that 1095 * it allows a start,len range that extends past the string end. 1096 * 1097 * @param str the string 1098 * @param start first byte index to check 1099 * @param len number of bytes to check 1100 * @returns #TRUE if the byte range exists and is a valid signature 1101 */ 1102dbus_bool_t 1103_dbus_validate_signature (const DBusString *str, 1104 int start, 1105 int len) 1106{ 1107 _dbus_assert (start >= 0); 1108 _dbus_assert (start <= _dbus_string_get_length (str)); 1109 _dbus_assert (len >= 0); 1110 1111 if (len > _dbus_string_get_length (str) - start) 1112 return FALSE; 1113 1114 return _dbus_validate_signature_with_reason (str, start, len) == DBUS_VALID; 1115} 1116 1117/** define _dbus_check_is_valid_path() */ 1118DEFINE_DBUS_NAME_CHECK(path) 1119/** define _dbus_check_is_valid_interface() */ 1120DEFINE_DBUS_NAME_CHECK(interface) 1121/** define _dbus_check_is_valid_member() */ 1122DEFINE_DBUS_NAME_CHECK(member) 1123/** define _dbus_check_is_valid_error_name() */ 1124DEFINE_DBUS_NAME_CHECK(error_name) 1125/** define _dbus_check_is_valid_bus_name() */ 1126DEFINE_DBUS_NAME_CHECK(bus_name) 1127/** define _dbus_check_is_valid_signature() */ 1128DEFINE_DBUS_NAME_CHECK(signature) 1129 1130/** @} */ 1131 1132/* tests in dbus-marshal-validate-util.c */ 1133