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