dbus-marshal-validate.c revision 8873c90f99303f9cc308f15f8d03e637911f5b9e
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 28/** 29 * @addtogroup DBusMarshal 30 * 31 * @{ 32 */ 33 34/** 35 * Verifies that the range of type_str from type_pos to type_end is a 36 * valid signature. If this function returns #TRUE, it will be safe 37 * to iterate over the signature with a types-only #DBusTypeReader. 38 * The range passed in should NOT include the terminating 39 * nul/DBUS_TYPE_INVALID. 40 * 41 * @param type_str the string 42 * @param type_pos where the typecodes start 43 * @param len length of typecodes 44 * @returns #DBUS_VALID if valid, reason why invalid otherwise 45 */ 46DBusValidity 47_dbus_validate_signature_with_reason (const DBusString *type_str, 48 int type_pos, 49 int len) 50{ 51 const unsigned char *p; 52 const unsigned char *end; 53 int last; 54 int struct_depth; 55 int array_depth; 56 57 _dbus_assert (type_str != NULL); 58 _dbus_assert (type_pos < _DBUS_INT_MAX - len); 59 _dbus_assert (len >= 0); 60 _dbus_assert (type_pos >= 0); 61 62 if (len > DBUS_MAXIMUM_SIGNATURE_LENGTH) 63 return DBUS_INVALID_SIGNATURE_TOO_LONG; 64 65 p = _dbus_string_get_const_data_len (type_str, type_pos, 0); 66 end = _dbus_string_get_const_data_len (type_str, type_pos + len, 0); 67 struct_depth = 0; 68 array_depth = 0; 69 last = DBUS_TYPE_INVALID; 70 71 while (p != end) 72 { 73 switch (*p) 74 { 75 case DBUS_TYPE_BYTE: 76 case DBUS_TYPE_BOOLEAN: 77 case DBUS_TYPE_INT32: 78 case DBUS_TYPE_UINT32: 79 case DBUS_TYPE_INT64: 80 case DBUS_TYPE_UINT64: 81 case DBUS_TYPE_DOUBLE: 82 case DBUS_TYPE_STRING: 83 case DBUS_TYPE_OBJECT_PATH: 84 case DBUS_TYPE_SIGNATURE: 85 case DBUS_TYPE_VARIANT: 86 break; 87 88 case DBUS_TYPE_ARRAY: 89 array_depth += 1; 90 if (array_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH) 91 return DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION; 92 break; 93 94 case DBUS_STRUCT_BEGIN_CHAR: 95 struct_depth += 1; 96 97 if (struct_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH) 98 return DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION; 99 break; 100 101 case DBUS_STRUCT_END_CHAR: 102 if (struct_depth == 0) 103 return DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED; 104 105 if (last == DBUS_STRUCT_BEGIN_CHAR) 106 return DBUS_INVALID_STRUCT_HAS_NO_FIELDS; 107 108 struct_depth -= 1; 109 break; 110 111 case DBUS_TYPE_STRUCT: /* doesn't appear in signatures */ 112 default: 113 return DBUS_INVALID_UNKNOWN_TYPECODE; 114 } 115 116 if (*p != DBUS_TYPE_ARRAY) 117 array_depth = 0; 118 119 last = *p; 120 ++p; 121 } 122 123 if (array_depth > 0) 124 return DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE; 125 126 if (struct_depth > 0) 127 return DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED; 128 129 return DBUS_VALID; 130} 131 132static DBusValidity 133validate_body_helper (DBusTypeReader *reader, 134 int byte_order, 135 dbus_bool_t walk_reader_to_end, 136 const unsigned char *p, 137 const unsigned char *end, 138 const unsigned char **new_p) 139{ 140 int current_type; 141 142 while ((current_type = _dbus_type_reader_get_current_type (reader)) != DBUS_TYPE_INVALID) 143 { 144 const unsigned char *a; 145 int alignment; 146 147 _dbus_verbose (" validating value of type %s type reader %p type_pos %d p %p end %p %d remain\n", 148 _dbus_type_to_string (current_type), reader, reader->type_pos, p, end, 149 (int) (end - p)); 150 151 /* Guarantee that p has one byte to look at */ 152 if (p == end) 153 return DBUS_INVALID_NOT_ENOUGH_DATA; 154 155 switch (current_type) 156 { 157 case DBUS_TYPE_BYTE: 158 ++p; 159 break; 160 161 case DBUS_TYPE_BOOLEAN: 162 case DBUS_TYPE_INT32: 163 case DBUS_TYPE_UINT32: 164 case DBUS_TYPE_INT64: 165 case DBUS_TYPE_UINT64: 166 case DBUS_TYPE_DOUBLE: 167 alignment = _dbus_type_get_alignment (current_type); 168 a = _DBUS_ALIGN_ADDRESS (p, alignment); 169 if (a >= end) 170 return DBUS_INVALID_NOT_ENOUGH_DATA; 171 while (p != a) 172 { 173 if (*p != '\0') 174 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 175 ++p; 176 } 177 178 if (current_type == DBUS_TYPE_BOOLEAN) 179 { 180 dbus_uint32_t v = _dbus_unpack_uint32 (byte_order, 181 p); 182 if (!(v == 0 || v == 1)) 183 return DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE; 184 } 185 186 p += alignment; 187 break; 188 189 case DBUS_TYPE_ARRAY: 190 case DBUS_TYPE_STRING: 191 case DBUS_TYPE_OBJECT_PATH: 192 { 193 dbus_uint32_t claimed_len; 194 195 a = _DBUS_ALIGN_ADDRESS (p, 4); 196 if (a + 4 >= end) 197 return DBUS_INVALID_NOT_ENOUGH_DATA; 198 while (p != a) 199 { 200 if (*p != '\0') 201 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 202 ++p; 203 } 204 205 claimed_len = _dbus_unpack_uint32 (byte_order, p); 206 p += 4; 207 208 if (current_type == DBUS_TYPE_ARRAY) 209 { 210 int array_elem_type = _dbus_type_reader_get_element_type (reader); 211 alignment = _dbus_type_get_alignment (array_elem_type); 212 p = _DBUS_ALIGN_ADDRESS (p, alignment); 213 } 214 215 if (claimed_len > (unsigned long) (end - p)) 216 return DBUS_INVALID_STRING_LENGTH_OUT_OF_BOUNDS; 217 218 if (current_type == DBUS_TYPE_OBJECT_PATH) 219 { 220 DBusString str; 221 _dbus_string_init_const_len (&str, p, claimed_len); 222 if (!_dbus_validate_path (&str, 0, 223 _dbus_string_get_length (&str))) 224 return DBUS_INVALID_BAD_PATH; 225 226 p += claimed_len; 227 } 228 else if (current_type == DBUS_TYPE_STRING) 229 { 230 DBusString str; 231 _dbus_string_init_const_len (&str, p, claimed_len); 232 if (!_dbus_string_validate_utf8 (&str, 0, 233 _dbus_string_get_length (&str))) 234 return DBUS_INVALID_BAD_UTF8_IN_STRING; 235 236 p += claimed_len; 237 } 238 else if (current_type == DBUS_TYPE_ARRAY && claimed_len > 0) 239 { 240 DBusTypeReader sub; 241 DBusValidity validity; 242 const unsigned char *array_end; 243 244 /* Remember that the reader is types only, so we can't 245 * use it to iterate over elements. It stays the same 246 * for all elements. 247 */ 248 _dbus_type_reader_recurse (reader, &sub); 249 250 array_end = p + claimed_len; 251 252 while (p < array_end) 253 { 254 validity = validate_body_helper (&sub, byte_order, FALSE, p, end, &p); 255 if (validity != DBUS_VALID) 256 return validity; 257 } 258 259 if (p != array_end) 260 return DBUS_INVALID_ARRAY_LENGTH_INCORRECT; 261 } 262 263 /* check nul termination */ 264 if (current_type != DBUS_TYPE_ARRAY) 265 { 266 if (p == end) 267 return DBUS_INVALID_NOT_ENOUGH_DATA; 268 269 if (*p != '\0') 270 return DBUS_INVALID_STRING_MISSING_NUL; 271 ++p; 272 } 273 } 274 break; 275 276 case DBUS_TYPE_SIGNATURE: 277 { 278 dbus_uint32_t claimed_len; 279 DBusString str; 280 281 claimed_len = *p; 282 ++p; 283 284 /* 1 is for nul termination */ 285 if (claimed_len + 1 > (unsigned long) (end - p)) 286 return DBUS_INVALID_SIGNATURE_LENGTH_OUT_OF_BOUNDS; 287 288 _dbus_string_init_const_len (&str, p, claimed_len); 289 if (!_dbus_validate_signature (&str, 0, 290 _dbus_string_get_length (&str))) 291 return DBUS_INVALID_BAD_SIGNATURE; 292 293 p += claimed_len; 294 295 _dbus_assert (p < end); 296 if (*p != DBUS_TYPE_INVALID) 297 return DBUS_INVALID_SIGNATURE_MISSING_NUL; 298 299 ++p; 300 301 _dbus_verbose ("p = %p end = %p claimed_len %u\n", p, end, claimed_len); 302 } 303 break; 304 305 case DBUS_TYPE_VARIANT: 306 { 307 /* 1 byte sig len, sig typecodes, align to 308 * contained-type-boundary, values. 309 */ 310 311 /* In addition to normal signature validation, we need to be sure 312 * the signature contains only a single (possibly container) type. 313 */ 314 dbus_uint32_t claimed_len; 315 DBusString sig; 316 DBusTypeReader sub; 317 DBusValidity validity; 318 int contained_alignment; 319 320 claimed_len = *p; 321 ++p; 322 323 /* + 1 for nul */ 324 if (claimed_len + 1 > (unsigned long) (end - p)) 325 return DBUS_INVALID_VARIANT_SIGNATURE_LENGTH_OUT_OF_BOUNDS; 326 327 _dbus_string_init_const_len (&sig, p, claimed_len); 328 if (!_dbus_validate_signature (&sig, 0, 329 _dbus_string_get_length (&sig))) 330 return DBUS_INVALID_VARIANT_SIGNATURE_BAD; 331 332 p += claimed_len; 333 334 if (*p != DBUS_TYPE_INVALID) 335 return DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL; 336 ++p; 337 338 contained_alignment = _dbus_type_get_alignment (_dbus_first_type_in_signature (&sig, 0)); 339 340 a = _DBUS_ALIGN_ADDRESS (p, contained_alignment); 341 if (a > end) 342 return DBUS_INVALID_NOT_ENOUGH_DATA; 343 while (p != a) 344 { 345 if (*p != '\0') 346 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 347 ++p; 348 } 349 350 _dbus_type_reader_init_types_only (&sub, &sig, 0); 351 352 if (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_INVALID) 353 return DBUS_INVALID_VARIANT_SIGNATURE_EMPTY; 354 355 validity = validate_body_helper (&sub, byte_order, FALSE, p, end, &p); 356 if (validity != DBUS_VALID) 357 return validity; 358 359 if (_dbus_type_reader_next (&sub)) 360 return DBUS_INVALID_VARIANT_SIGNATURE_SPECIFIES_MULTIPLE_VALUES; 361 362 _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_INVALID); 363 } 364 break; 365 366 case DBUS_TYPE_STRUCT: 367 { 368 DBusTypeReader sub; 369 DBusValidity validity; 370 371 a = _DBUS_ALIGN_ADDRESS (p, 8); 372 if (a > end) 373 return DBUS_INVALID_NOT_ENOUGH_DATA; 374 while (p != a) 375 { 376 if (*p != '\0') 377 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 378 ++p; 379 } 380 381 _dbus_type_reader_recurse (reader, &sub); 382 383 validity = validate_body_helper (&sub, byte_order, TRUE, p, end, &p); 384 if (validity != DBUS_VALID) 385 return validity; 386 } 387 break; 388 389 default: 390 _dbus_assert_not_reached ("invalid typecode in supposedly-validated signature"); 391 break; 392 } 393 394 _dbus_verbose (" validated value of type %s type reader %p type_pos %d p %p end %p %d remain\n", 395 _dbus_type_to_string (current_type), reader, reader->type_pos, p, end, 396 (int) (end - p)); 397 398 if (p > end) 399 { 400 _dbus_verbose ("not enough data!!! p = %p end = %p end-p = %d\n", 401 p, end, (int) (end - p)); 402 return DBUS_INVALID_NOT_ENOUGH_DATA; 403 } 404 405 if (walk_reader_to_end) 406 _dbus_type_reader_next (reader); 407 else 408 break; 409 } 410 411 if (new_p) 412 *new_p = p; 413 414 return DBUS_VALID; 415} 416 417/** 418 * Verifies that the range of value_str from value_pos to value_end is 419 * a legitimate value of type expected_signature. If this function 420 * returns #TRUE, it will be safe to iterate over the values with 421 * #DBusTypeReader. The signature is assumed to be already valid. 422 * 423 * If bytes_remaining is not #NULL, then leftover bytes will be stored 424 * there and #DBUS_VALID returned. If it is #NULL, then 425 * #DBUS_INVALID_TOO_MUCH_DATA will be returned if bytes are left 426 * over. 427 * 428 * @param expected_signature the expected types in the value_str 429 * @param expected_signature_start where in expected_signature is the signature 430 * @param byte_order the byte order 431 * @param bytes_remaining place to store leftover bytes 432 * @param value_str the string containing the body 433 * @param value_pos where the values start 434 * @param len length of values after value_pos 435 * @returns #DBUS_VALID if valid, reason why invalid otherwise 436 */ 437DBusValidity 438_dbus_validate_body_with_reason (const DBusString *expected_signature, 439 int expected_signature_start, 440 int byte_order, 441 int *bytes_remaining, 442 const DBusString *value_str, 443 int value_pos, 444 int len) 445{ 446 DBusTypeReader reader; 447 const unsigned char *p; 448 const unsigned char *end; 449 DBusValidity validity; 450 451 _dbus_assert (len >= 0); 452 _dbus_assert (value_pos >= 0); 453 _dbus_assert (value_pos <= _dbus_string_get_length (value_str) - len); 454 455 _dbus_verbose ("validating body from pos %d len %d sig '%s'\n", 456 value_pos, len, _dbus_string_get_const_data_len (expected_signature, 457 expected_signature_start, 458 0)); 459 460 _dbus_type_reader_init_types_only (&reader, 461 expected_signature, expected_signature_start); 462 463 p = _dbus_string_get_const_data_len (value_str, value_pos, len); 464 end = p + len; 465 466 validity = validate_body_helper (&reader, byte_order, TRUE, p, end, &p); 467 if (validity != DBUS_VALID) 468 return validity; 469 470 if (bytes_remaining) 471 { 472 *bytes_remaining = end - p; 473 return DBUS_VALID; 474 } 475 else if (p < end) 476 return DBUS_INVALID_TOO_MUCH_DATA; 477 else 478 { 479 _dbus_assert (p == end); 480 return DBUS_VALID; 481 } 482} 483 484/** 485 * Determine wether the given charater is valid as the first charater 486 * in a name. 487 */ 488#define VALID_INITIAL_NAME_CHARACTER(c) \ 489 ( ((c) >= 'A' && (c) <= 'Z') || \ 490 ((c) >= 'a' && (c) <= 'z') || \ 491 ((c) == '_') ) 492 493/** 494 * Determine wether the given charater is valid as a second or later 495 * character in a name 496 */ 497#define VALID_NAME_CHARACTER(c) \ 498 ( ((c) >= '0' && (c) <= '9') || \ 499 ((c) >= 'A' && (c) <= 'Z') || \ 500 ((c) >= 'a' && (c) <= 'z') || \ 501 ((c) == '_') ) 502 503/** 504 * Checks that the given range of the string is a valid object path 505 * name in the D-BUS protocol. Part of the validation ensures that 506 * the object path contains only ASCII. 507 * 508 * @todo this is inconsistent with most of DBusString in that 509 * it allows a start,len range that extends past the string end. 510 * 511 * @todo change spec to disallow more things, such as spaces in the 512 * path name 513 * 514 * @param str the string 515 * @param start first byte index to check 516 * @param len number of bytes to check 517 * @returns #TRUE if the byte range exists and is a valid name 518 */ 519dbus_bool_t 520_dbus_validate_path (const DBusString *str, 521 int start, 522 int len) 523{ 524 const unsigned char *s; 525 const unsigned char *end; 526 const unsigned char *last_slash; 527 528 _dbus_assert (start >= 0); 529 _dbus_assert (len >= 0); 530 _dbus_assert (start <= _dbus_string_get_length (str)); 531 532 if (len > _dbus_string_get_length (str) - start) 533 return FALSE; 534 535 if (len == 0) 536 return FALSE; 537 538 s = _dbus_string_get_const_data (str) + start; 539 end = s + len; 540 541 if (*s != '/') 542 return FALSE; 543 last_slash = s; 544 ++s; 545 546 while (s != end) 547 { 548 if (*s == '/') 549 { 550 if ((s - last_slash) < 2) 551 return FALSE; /* no empty path components allowed */ 552 553 last_slash = s; 554 } 555 else 556 { 557 if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s))) 558 return FALSE; 559 } 560 561 ++s; 562 } 563 564 if ((end - last_slash) < 2 && 565 len > 1) 566 return FALSE; /* trailing slash not allowed unless the string is "/" */ 567 568 return TRUE; 569} 570 571/** 572 * Checks that the given range of the string is a valid interface name 573 * in the D-BUS protocol. This includes a length restriction and an 574 * ASCII subset, see the specification. 575 * 576 * @todo this is inconsistent with most of DBusString in that 577 * it allows a start,len range that extends past the string end. 578 * 579 * @param str the string 580 * @param start first byte index to check 581 * @param len number of bytes to check 582 * @returns #TRUE if the byte range exists and is a valid name 583 */ 584dbus_bool_t 585_dbus_validate_interface (const DBusString *str, 586 int start, 587 int len) 588{ 589 const unsigned char *s; 590 const unsigned char *end; 591 const unsigned char *iface; 592 const unsigned char *last_dot; 593 594 _dbus_assert (start >= 0); 595 _dbus_assert (len >= 0); 596 _dbus_assert (start <= _dbus_string_get_length (str)); 597 598 if (len > _dbus_string_get_length (str) - start) 599 return FALSE; 600 601 if (len > DBUS_MAXIMUM_NAME_LENGTH) 602 return FALSE; 603 604 if (len == 0) 605 return FALSE; 606 607 last_dot = NULL; 608 iface = _dbus_string_get_const_data (str) + start; 609 end = iface + len; 610 s = iface; 611 612 /* check special cases of first char so it doesn't have to be done 613 * in the loop. Note we know len > 0 614 */ 615 if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */ 616 return FALSE; 617 else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s))) 618 return FALSE; 619 else 620 ++s; 621 622 while (s != end) 623 { 624 if (*s == '.') 625 { 626 if (_DBUS_UNLIKELY ((s + 1) == end)) 627 return FALSE; 628 else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*(s + 1)))) 629 return FALSE; 630 last_dot = s; 631 ++s; /* we just validated the next char, so skip two */ 632 } 633 else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s))) 634 { 635 return FALSE; 636 } 637 638 ++s; 639 } 640 641 if (_DBUS_UNLIKELY (last_dot == NULL)) 642 return FALSE; 643 644 return TRUE; 645} 646 647/** 648 * Checks that the given range of the string is a valid member name 649 * in the D-BUS protocol. This includes a length restriction, etc., 650 * see the specification. 651 * 652 * @todo this is inconsistent with most of DBusString in that 653 * it allows a start,len range that extends past the string end. 654 * 655 * @param str the string 656 * @param start first byte index to check 657 * @param len number of bytes to check 658 * @returns #TRUE if the byte range exists and is a valid name 659 */ 660dbus_bool_t 661_dbus_validate_member (const DBusString *str, 662 int start, 663 int len) 664{ 665 const unsigned char *s; 666 const unsigned char *end; 667 const unsigned char *member; 668 669 _dbus_assert (start >= 0); 670 _dbus_assert (len >= 0); 671 _dbus_assert (start <= _dbus_string_get_length (str)); 672 673 if (len > _dbus_string_get_length (str) - start) 674 return FALSE; 675 676 if (len > DBUS_MAXIMUM_NAME_LENGTH) 677 return FALSE; 678 679 if (len == 0) 680 return FALSE; 681 682 member = _dbus_string_get_const_data (str) + start; 683 end = member + len; 684 s = member; 685 686 /* check special cases of first char so it doesn't have to be done 687 * in the loop. Note we know len > 0 688 */ 689 690 if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s))) 691 return FALSE; 692 else 693 ++s; 694 695 while (s != end) 696 { 697 if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s))) 698 { 699 return FALSE; 700 } 701 702 ++s; 703 } 704 705 return TRUE; 706} 707 708/** 709 * Checks that the given range of the string is a valid error name 710 * in the D-BUS protocol. This includes a length restriction, etc., 711 * see the specification. 712 * 713 * @todo this is inconsistent with most of DBusString in that 714 * it allows a start,len range that extends past the string end. 715 * 716 * @param str the string 717 * @param start first byte index to check 718 * @param len number of bytes to check 719 * @returns #TRUE if the byte range exists and is a valid name 720 */ 721dbus_bool_t 722_dbus_validate_error_name (const DBusString *str, 723 int start, 724 int len) 725{ 726 /* Same restrictions as interface name at the moment */ 727 return _dbus_validate_interface (str, start, len); 728} 729 730/* This assumes the first char exists and is ':' */ 731static dbus_bool_t 732_dbus_validate_unique_name (const DBusString *str, 733 int start, 734 int len) 735{ 736 const unsigned char *s; 737 const unsigned char *end; 738 const unsigned char *name; 739 740 _dbus_assert (start >= 0); 741 _dbus_assert (len >= 0); 742 _dbus_assert (start <= _dbus_string_get_length (str)); 743 744 if (len > _dbus_string_get_length (str) - start) 745 return FALSE; 746 747 if (len > DBUS_MAXIMUM_NAME_LENGTH) 748 return FALSE; 749 750 _dbus_assert (len > 0); 751 752 name = _dbus_string_get_const_data (str) + start; 753 end = name + len; 754 _dbus_assert (*name == ':'); 755 s = name + 1; 756 757 while (s != end) 758 { 759 if (*s == '.') 760 { 761 if (_DBUS_UNLIKELY ((s + 1) == end)) 762 return FALSE; 763 if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*(s + 1)))) 764 return FALSE; 765 ++s; /* we just validated the next char, so skip two */ 766 } 767 else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s))) 768 { 769 return FALSE; 770 } 771 772 ++s; 773 } 774 775 return TRUE; 776} 777 778/** 779 * Checks that the given range of the string is a valid bus name in 780 * the D-BUS protocol. This includes a length restriction, etc., see 781 * the specification. 782 * 783 * @todo this is inconsistent with most of DBusString in that 784 * it allows a start,len range that extends past the string end. 785 * 786 * @param str the string 787 * @param start first byte index to check 788 * @param len number of bytes to check 789 * @returns #TRUE if the byte range exists and is a valid name 790 */ 791dbus_bool_t 792_dbus_validate_bus_name (const DBusString *str, 793 int start, 794 int len) 795{ 796 if (_DBUS_UNLIKELY (len == 0)) 797 return FALSE; 798 if (_dbus_string_get_byte (str, start) == ':') 799 return _dbus_validate_unique_name (str, start, len); 800 else 801 return _dbus_validate_interface (str, start, len); 802} 803 804/** 805 * Checks that the given range of the string is a valid message type 806 * signature in the D-BUS protocol. 807 * 808 * @todo this is inconsistent with most of DBusString in that 809 * it allows a start,len range that extends past the string end. 810 * 811 * @param str the string 812 * @param start first byte index to check 813 * @param len number of bytes to check 814 * @returns #TRUE if the byte range exists and is a valid signature 815 */ 816dbus_bool_t 817_dbus_validate_signature (const DBusString *str, 818 int start, 819 int len) 820{ 821 _dbus_assert (start >= 0); 822 _dbus_assert (start <= _dbus_string_get_length (str)); 823 _dbus_assert (len >= 0); 824 825 if (len > _dbus_string_get_length (str) - start) 826 return FALSE; 827 828 return _dbus_validate_signature_with_reason (str, start, len) == DBUS_VALID; 829} 830 831/** define _dbus_check_is_valid_path() */ 832DEFINE_DBUS_NAME_CHECK(path); 833/** define _dbus_check_is_valid_interface() */ 834DEFINE_DBUS_NAME_CHECK(interface); 835/** define _dbus_check_is_valid_member() */ 836DEFINE_DBUS_NAME_CHECK(member); 837/** define _dbus_check_is_valid_error_name() */ 838DEFINE_DBUS_NAME_CHECK(error_name); 839/** define _dbus_check_is_valid_bus_name() */ 840DEFINE_DBUS_NAME_CHECK(bus_name); 841/** define _dbus_check_is_valid_signature() */ 842DEFINE_DBUS_NAME_CHECK(signature); 843 844/** @} */ 845 846#ifdef DBUS_BUILD_TESTS 847#include "dbus-test.h" 848#include <stdio.h> 849 850typedef struct 851{ 852 const char *data; 853 DBusValidity expected; 854} ValidityTest; 855 856static void 857run_validity_tests (const ValidityTest *tests, 858 int n_tests, 859 DBusValidity (* func) (const DBusString*,int,int)) 860{ 861 int i; 862 863 for (i = 0; i < n_tests; i++) 864 { 865 DBusString str; 866 DBusValidity v; 867 868 _dbus_string_init_const (&str, tests[i].data); 869 870 v = (*func) (&str, 0, _dbus_string_get_length (&str)); 871 872 if (v != tests[i].expected) 873 { 874 _dbus_warn ("Improper validation result %d for '%s'\n", 875 v, tests[i].data); 876 _dbus_assert_not_reached ("test failed"); 877 } 878 879 ++i; 880 } 881} 882 883static const ValidityTest signature_tests[] = { 884 { "", DBUS_VALID }, 885 { "i", DBUS_VALID }, 886 { "ai", DBUS_VALID }, 887 { "(i)", DBUS_VALID }, 888 { "q", DBUS_INVALID_UNKNOWN_TYPECODE }, 889 { "a", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE }, 890 { "aaaaaa", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE }, 891 { "ii(ii)a", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE }, 892 { "ia", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE }, 893 /* DBUS_INVALID_SIGNATURE_TOO_LONG, */ /* too hard to test this way */ 894 { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 895 DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION }, 896 { "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((ii))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))", 897 DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION }, 898 { ")", DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED }, 899 { "i)", DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED }, 900 { "a)", DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED }, 901 { "(", DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED }, 902 { "(i", DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED }, 903 { "(iiiii", DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED }, 904 { "(ai", DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED }, 905 { "()", DBUS_INVALID_STRUCT_HAS_NO_FIELDS }, 906 { "(())", DBUS_INVALID_STRUCT_HAS_NO_FIELDS }, 907 { "a()", DBUS_INVALID_STRUCT_HAS_NO_FIELDS }, 908 { "i()", DBUS_INVALID_STRUCT_HAS_NO_FIELDS }, 909 { "()i", DBUS_INVALID_STRUCT_HAS_NO_FIELDS } 910}; 911 912dbus_bool_t 913_dbus_marshal_validate_test (void) 914{ 915 DBusString str; 916 int i; 917 918 const char *valid_paths[] = { 919 "/", 920 "/foo/bar", 921 "/foo", 922 "/foo/bar/baz" 923 }; 924 const char *invalid_paths[] = { 925 "bar", 926 "bar/baz", 927 "/foo/bar/", 928 "/foo/" 929 "foo/", 930 "boo//blah", 931 "//", 932 "///", 933 "foo///blah/", 934 "Hello World", 935 "", 936 " ", 937 "foo bar" 938 }; 939 940 const char *valid_interfaces[] = { 941 "org.freedesktop.Foo", 942 "Bar.Baz", 943 "Blah.Blah.Blah.Blah.Blah", 944 "a.b", 945 "a.b.c.d.e.f.g", 946 "a0.b1.c2.d3.e4.f5.g6", 947 "abc123.foo27" 948 }; 949 const char *invalid_interfaces[] = { 950 ".", 951 "", 952 "..", 953 ".Foo.Bar", 954 "..Foo.Bar", 955 "Foo.Bar.", 956 "Foo.Bar..", 957 "Foo", 958 "9foo.bar.baz", 959 "foo.bar..baz", 960 "foo.bar...baz", 961 "foo.bar.b..blah", 962 ":", 963 ":0-1", 964 "10", 965 ":11.34324", 966 "0.0.0", 967 "0..0", 968 "foo.Bar.%", 969 "foo.Bar!!", 970 "!Foo.bar.bz", 971 "foo.$.blah", 972 "", 973 " ", 974 "foo bar" 975 }; 976 977 const char *valid_unique_names[] = { 978 ":0", 979 ":a", 980 ":", 981 ":.a", 982 ":.1", 983 ":0.1", 984 ":000.2222", 985 ":.blah", 986 ":abce.freedesktop.blah" 987 }; 988 const char *invalid_unique_names[] = { 989 ":-", 990 ":!", 991 ":0-10", 992 ":blah.", 993 ":blah.", 994 ":blah..org", 995 ":blah.org..", 996 ":..blah.org", 997 "", 998 " ", 999 "foo bar" 1000 }; 1001 1002 const char *valid_members[] = { 1003 "Hello", 1004 "Bar", 1005 "foobar", 1006 "_foobar", 1007 "foo89" 1008 }; 1009 1010 const char *invalid_members[] = { 1011 "9Hello", 1012 "10", 1013 "1", 1014 "foo-bar", 1015 "blah.org", 1016 ".blah", 1017 "blah.", 1018 "Hello.", 1019 "!foo", 1020 "", 1021 " ", 1022 "foo bar" 1023 }; 1024 1025 const char *valid_signatures[] = { 1026 "", 1027 "sss", 1028 "i", 1029 "b" 1030 }; 1031 1032 const char *invalid_signatures[] = { 1033 " ", 1034 "not a valid signature", 1035 "123", 1036 ".", 1037 "(" 1038 }; 1039 1040 /* Signature with reason */ 1041 1042 run_validity_tests (signature_tests, _DBUS_N_ELEMENTS (signature_tests), 1043 _dbus_validate_signature_with_reason); 1044 1045 /* Path validation */ 1046 i = 0; 1047 while (i < (int) _DBUS_N_ELEMENTS (valid_paths)) 1048 { 1049 _dbus_string_init_const (&str, valid_paths[i]); 1050 1051 if (!_dbus_validate_path (&str, 0, 1052 _dbus_string_get_length (&str))) 1053 { 1054 _dbus_warn ("Path \"%s\" should have been valid\n", valid_paths[i]); 1055 _dbus_assert_not_reached ("invalid path"); 1056 } 1057 1058 ++i; 1059 } 1060 1061 i = 0; 1062 while (i < (int) _DBUS_N_ELEMENTS (invalid_paths)) 1063 { 1064 _dbus_string_init_const (&str, invalid_paths[i]); 1065 1066 if (_dbus_validate_path (&str, 0, 1067 _dbus_string_get_length (&str))) 1068 { 1069 _dbus_warn ("Path \"%s\" should have been invalid\n", invalid_paths[i]); 1070 _dbus_assert_not_reached ("valid path"); 1071 } 1072 1073 ++i; 1074 } 1075 1076 /* Interface validation */ 1077 i = 0; 1078 while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces)) 1079 { 1080 _dbus_string_init_const (&str, valid_interfaces[i]); 1081 1082 if (!_dbus_validate_interface (&str, 0, 1083 _dbus_string_get_length (&str))) 1084 { 1085 _dbus_warn ("Interface \"%s\" should have been valid\n", valid_interfaces[i]); 1086 _dbus_assert_not_reached ("invalid interface"); 1087 } 1088 1089 ++i; 1090 } 1091 1092 i = 0; 1093 while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces)) 1094 { 1095 _dbus_string_init_const (&str, invalid_interfaces[i]); 1096 1097 if (_dbus_validate_interface (&str, 0, 1098 _dbus_string_get_length (&str))) 1099 { 1100 _dbus_warn ("Interface \"%s\" should have been invalid\n", invalid_interfaces[i]); 1101 _dbus_assert_not_reached ("valid interface"); 1102 } 1103 1104 ++i; 1105 } 1106 1107 /* Bus name validation (check that valid interfaces are valid bus names, 1108 * and invalid interfaces are invalid services except if they start with ':') 1109 */ 1110 i = 0; 1111 while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces)) 1112 { 1113 _dbus_string_init_const (&str, valid_interfaces[i]); 1114 1115 if (!_dbus_validate_bus_name (&str, 0, 1116 _dbus_string_get_length (&str))) 1117 { 1118 _dbus_warn ("Bus name \"%s\" should have been valid\n", valid_interfaces[i]); 1119 _dbus_assert_not_reached ("invalid bus name"); 1120 } 1121 1122 ++i; 1123 } 1124 1125 i = 0; 1126 while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces)) 1127 { 1128 if (invalid_interfaces[i][0] != ':') 1129 { 1130 _dbus_string_init_const (&str, invalid_interfaces[i]); 1131 1132 if (_dbus_validate_bus_name (&str, 0, 1133 _dbus_string_get_length (&str))) 1134 { 1135 _dbus_warn ("Bus name \"%s\" should have been invalid\n", invalid_interfaces[i]); 1136 _dbus_assert_not_reached ("valid bus name"); 1137 } 1138 } 1139 1140 ++i; 1141 } 1142 1143 /* unique name validation */ 1144 i = 0; 1145 while (i < (int) _DBUS_N_ELEMENTS (valid_unique_names)) 1146 { 1147 _dbus_string_init_const (&str, valid_unique_names[i]); 1148 1149 if (!_dbus_validate_bus_name (&str, 0, 1150 _dbus_string_get_length (&str))) 1151 { 1152 _dbus_warn ("Bus name \"%s\" should have been valid\n", valid_unique_names[i]); 1153 _dbus_assert_not_reached ("invalid unique name"); 1154 } 1155 1156 ++i; 1157 } 1158 1159 i = 0; 1160 while (i < (int) _DBUS_N_ELEMENTS (invalid_unique_names)) 1161 { 1162 _dbus_string_init_const (&str, invalid_unique_names[i]); 1163 1164 if (_dbus_validate_bus_name (&str, 0, 1165 _dbus_string_get_length (&str))) 1166 { 1167 _dbus_warn ("Bus name \"%s\" should have been invalid\n", invalid_unique_names[i]); 1168 _dbus_assert_not_reached ("valid unique name"); 1169 } 1170 1171 ++i; 1172 } 1173 1174 1175 /* Error name validation (currently identical to interfaces) 1176 */ 1177 i = 0; 1178 while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces)) 1179 { 1180 _dbus_string_init_const (&str, valid_interfaces[i]); 1181 1182 if (!_dbus_validate_error_name (&str, 0, 1183 _dbus_string_get_length (&str))) 1184 { 1185 _dbus_warn ("Error name \"%s\" should have been valid\n", valid_interfaces[i]); 1186 _dbus_assert_not_reached ("invalid error name"); 1187 } 1188 1189 ++i; 1190 } 1191 1192 i = 0; 1193 while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces)) 1194 { 1195 if (invalid_interfaces[i][0] != ':') 1196 { 1197 _dbus_string_init_const (&str, invalid_interfaces[i]); 1198 1199 if (_dbus_validate_error_name (&str, 0, 1200 _dbus_string_get_length (&str))) 1201 { 1202 _dbus_warn ("Error name \"%s\" should have been invalid\n", invalid_interfaces[i]); 1203 _dbus_assert_not_reached ("valid error name"); 1204 } 1205 } 1206 1207 ++i; 1208 } 1209 1210 /* Member validation */ 1211 i = 0; 1212 while (i < (int) _DBUS_N_ELEMENTS (valid_members)) 1213 { 1214 _dbus_string_init_const (&str, valid_members[i]); 1215 1216 if (!_dbus_validate_member (&str, 0, 1217 _dbus_string_get_length (&str))) 1218 { 1219 _dbus_warn ("Member \"%s\" should have been valid\n", valid_members[i]); 1220 _dbus_assert_not_reached ("invalid member"); 1221 } 1222 1223 ++i; 1224 } 1225 1226 i = 0; 1227 while (i < (int) _DBUS_N_ELEMENTS (invalid_members)) 1228 { 1229 _dbus_string_init_const (&str, invalid_members[i]); 1230 1231 if (_dbus_validate_member (&str, 0, 1232 _dbus_string_get_length (&str))) 1233 { 1234 _dbus_warn ("Member \"%s\" should have been invalid\n", invalid_members[i]); 1235 _dbus_assert_not_reached ("valid member"); 1236 } 1237 1238 ++i; 1239 } 1240 1241 /* Signature validation */ 1242 i = 0; 1243 while (i < (int) _DBUS_N_ELEMENTS (valid_signatures)) 1244 { 1245 _dbus_string_init_const (&str, valid_signatures[i]); 1246 1247 if (!_dbus_validate_signature (&str, 0, 1248 _dbus_string_get_length (&str))) 1249 { 1250 _dbus_warn ("Signature \"%s\" should have been valid\n", valid_signatures[i]); 1251 _dbus_assert_not_reached ("invalid signature"); 1252 } 1253 1254 ++i; 1255 } 1256 1257 i = 0; 1258 while (i < (int) _DBUS_N_ELEMENTS (invalid_signatures)) 1259 { 1260 _dbus_string_init_const (&str, invalid_signatures[i]); 1261 1262 if (_dbus_validate_signature (&str, 0, 1263 _dbus_string_get_length (&str))) 1264 { 1265 _dbus_warn ("Signature \"%s\" should have been invalid\n", invalid_signatures[i]); 1266 _dbus_assert_not_reached ("valid signature"); 1267 } 1268 1269 ++i; 1270 } 1271 1272 /* Validate claimed length longer than real length */ 1273 _dbus_string_init_const (&str, "abc.efg"); 1274 if (_dbus_validate_bus_name (&str, 0, 8)) 1275 _dbus_assert_not_reached ("validated too-long string"); 1276 if (_dbus_validate_interface (&str, 0, 8)) 1277 _dbus_assert_not_reached ("validated too-long string"); 1278 if (_dbus_validate_error_name (&str, 0, 8)) 1279 _dbus_assert_not_reached ("validated too-long string"); 1280 1281 _dbus_string_init_const (&str, "abc"); 1282 if (_dbus_validate_member (&str, 0, 4)) 1283 _dbus_assert_not_reached ("validated too-long string"); 1284 1285 _dbus_string_init_const (&str, "sss"); 1286 if (_dbus_validate_signature (&str, 0, 4)) 1287 _dbus_assert_not_reached ("validated too-long signature"); 1288 1289 /* Validate string exceeding max name length */ 1290 if (!_dbus_string_init (&str)) 1291 _dbus_assert_not_reached ("no memory"); 1292 1293 while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH) 1294 if (!_dbus_string_append (&str, "abc.def")) 1295 _dbus_assert_not_reached ("no memory"); 1296 1297 if (_dbus_validate_bus_name (&str, 0, _dbus_string_get_length (&str))) 1298 _dbus_assert_not_reached ("validated overmax string"); 1299 if (_dbus_validate_interface (&str, 0, _dbus_string_get_length (&str))) 1300 _dbus_assert_not_reached ("validated overmax string"); 1301 if (_dbus_validate_error_name (&str, 0, _dbus_string_get_length (&str))) 1302 _dbus_assert_not_reached ("validated overmax string"); 1303 1304 /* overlong member */ 1305 _dbus_string_set_length (&str, 0); 1306 while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH) 1307 if (!_dbus_string_append (&str, "abc")) 1308 _dbus_assert_not_reached ("no memory"); 1309 1310 if (_dbus_validate_member (&str, 0, _dbus_string_get_length (&str))) 1311 _dbus_assert_not_reached ("validated overmax string"); 1312 1313 /* overlong unique name */ 1314 _dbus_string_set_length (&str, 0); 1315 _dbus_string_append (&str, ":"); 1316 while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH) 1317 if (!_dbus_string_append (&str, "abc")) 1318 _dbus_assert_not_reached ("no memory"); 1319 1320 if (_dbus_validate_bus_name (&str, 0, _dbus_string_get_length (&str))) 1321 _dbus_assert_not_reached ("validated overmax string"); 1322 1323 _dbus_string_free (&str); 1324 1325 return TRUE; 1326} 1327 1328#endif /* DBUS_BUILD_TESTS */ 1329