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