1/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 2/* dbus-message-factory.c Generator of valid and invalid message data for test suite 3 * 4 * Copyright (C) 2005 Red Hat Inc. 5 * 6 * Licensed under the Academic Free License version 2.1 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 * 22 */ 23#include <config.h> 24 25#ifndef DOXYGEN_SHOULD_SKIP_THIS 26 27#ifdef DBUS_BUILD_TESTS 28#include "dbus-message-factory.h" 29#include "dbus-message-private.h" 30#include "dbus-signature.h" 31#include "dbus-test.h" 32#include <stdio.h> 33 34typedef enum 35 { 36 CHANGE_TYPE_ADJUST, 37 CHANGE_TYPE_ABSOLUTE 38 } ChangeType; 39 40#define BYTE_ORDER_OFFSET 0 41#define TYPE_OFFSET 1 42#define BODY_LENGTH_OFFSET 4 43#define FIELDS_ARRAY_LENGTH_OFFSET 12 44 45static void 46iter_recurse (DBusMessageDataIter *iter) 47{ 48 iter->depth += 1; 49 _dbus_assert (iter->depth < _DBUS_MESSAGE_DATA_MAX_NESTING); 50 _dbus_assert (iter->sequence_nos[iter->depth] >= 0); 51} 52 53static int 54iter_get_sequence (DBusMessageDataIter *iter) 55{ 56 _dbus_assert (iter->sequence_nos[iter->depth] >= 0); 57 return iter->sequence_nos[iter->depth]; 58} 59 60static void 61iter_set_sequence (DBusMessageDataIter *iter, 62 int sequence) 63{ 64 _dbus_assert (sequence >= 0); 65 iter->sequence_nos[iter->depth] = sequence; 66} 67 68static void 69iter_unrecurse (DBusMessageDataIter *iter) 70{ 71 iter->depth -= 1; 72 _dbus_assert (iter->depth >= 0); 73} 74 75static void 76iter_next (DBusMessageDataIter *iter) 77{ 78 iter->sequence_nos[iter->depth] += 1; 79} 80 81static dbus_bool_t 82iter_first_in_series (DBusMessageDataIter *iter) 83{ 84 int i; 85 86 i = iter->depth; 87 while (i < _DBUS_MESSAGE_DATA_MAX_NESTING) 88 { 89 if (iter->sequence_nos[i] != 0) 90 return FALSE; 91 ++i; 92 } 93 return TRUE; 94} 95 96typedef dbus_bool_t (* DBusInnerGeneratorFunc) (DBusMessageDataIter *iter, 97 DBusMessage **message_p); 98typedef dbus_bool_t (* DBusMessageGeneratorFunc) (DBusMessageDataIter *iter, 99 DBusString *data, 100 DBusValidity *expected_validity); 101 102static void 103set_reply_serial (DBusMessage *message) 104{ 105 if (message == NULL) 106 _dbus_assert_not_reached ("oom"); 107 if (!dbus_message_set_reply_serial (message, 100)) 108 _dbus_assert_not_reached ("oom"); 109} 110 111static dbus_bool_t 112generate_trivial_inner (DBusMessageDataIter *iter, 113 DBusMessage **message_p) 114{ 115 DBusMessage *message; 116 117 switch (iter_get_sequence (iter)) 118 { 119 case 0: 120 message = dbus_message_new_method_call ("org.freedesktop.TextEditor", 121 "/foo/bar", 122 "org.freedesktop.DocumentFactory", 123 "Create"); 124 break; 125 case 1: 126 message = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_RETURN); 127 set_reply_serial (message); 128 break; 129 case 2: 130 message = dbus_message_new_signal ("/foo/bar", 131 "org.freedesktop.DocumentFactory", 132 "Created"); 133 break; 134 case 3: 135 message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR); 136 137 if (!dbus_message_set_error_name (message, 138 "org.freedesktop.TestErrorName")) 139 _dbus_assert_not_reached ("oom"); 140 141 { 142 DBusMessageIter iter; 143 const char *v_STRING = "This is an error"; 144 145 dbus_message_iter_init_append (message, &iter); 146 if (!dbus_message_iter_append_basic (&iter, 147 DBUS_TYPE_STRING, 148 &v_STRING)) 149 _dbus_assert_not_reached ("oom"); 150 } 151 152 set_reply_serial (message); 153 break; 154 default: 155 return FALSE; 156 } 157 158 if (message == NULL) 159 _dbus_assert_not_reached ("oom"); 160 161 *message_p = message; 162 163 return TRUE; 164} 165 166static dbus_bool_t 167generate_many_bodies_inner (DBusMessageDataIter *iter, 168 DBusMessage **message_p) 169{ 170 DBusMessage *message; 171 DBusString signature; 172 DBusString body; 173 char byte_order; 174 175 /* Keeping this small makes things go faster */ 176 message = dbus_message_new_method_call ("o.z.F", 177 "/", 178 "o.z.B", 179 "Nah"); 180 if (message == NULL) 181 _dbus_assert_not_reached ("oom"); 182 183 byte_order = _dbus_header_get_byte_order (&message->header); 184 185 set_reply_serial (message); 186 187 if (!_dbus_string_init (&signature) || !_dbus_string_init (&body)) 188 _dbus_assert_not_reached ("oom"); 189 190 if (dbus_internal_do_not_use_generate_bodies (iter_get_sequence (iter), 191 byte_order, 192 &signature, &body)) 193 { 194 const char *v_SIGNATURE; 195 196 v_SIGNATURE = _dbus_string_get_const_data (&signature); 197 if (!_dbus_header_set_field_basic (&message->header, 198 DBUS_HEADER_FIELD_SIGNATURE, 199 DBUS_TYPE_SIGNATURE, 200 &v_SIGNATURE)) 201 _dbus_assert_not_reached ("oom"); 202 203 if (!_dbus_string_move (&body, 0, &message->body, 0)) 204 _dbus_assert_not_reached ("oom"); 205 206 _dbus_marshal_set_uint32 (&message->header.data, BODY_LENGTH_OFFSET, 207 _dbus_string_get_length (&message->body), 208 byte_order); 209 210 *message_p = message; 211 } 212 else 213 { 214 dbus_message_unref (message); 215 *message_p = NULL; 216 } 217 218 _dbus_string_free (&signature); 219 _dbus_string_free (&body); 220 221 return *message_p != NULL; 222} 223 224static void 225generate_from_message (DBusString *data, 226 DBusValidity *expected_validity, 227 DBusMessage *message) 228{ 229 dbus_message_set_serial (message, 1); 230 dbus_message_lock (message); 231 232 *expected_validity = DBUS_VALID; 233 234 /* move for efficiency, since we'll nuke the message anyway */ 235 if (!_dbus_string_move (&message->header.data, 0, 236 data, 0)) 237 _dbus_assert_not_reached ("oom"); 238 239 if (!_dbus_string_copy (&message->body, 0, 240 data, _dbus_string_get_length (data))) 241 _dbus_assert_not_reached ("oom"); 242} 243 244static dbus_bool_t 245generate_outer (DBusMessageDataIter *iter, 246 DBusString *data, 247 DBusValidity *expected_validity, 248 DBusInnerGeneratorFunc func) 249{ 250 DBusMessage *message; 251 252 message = NULL; 253 if (!(*func)(iter, &message)) 254 return FALSE; 255 256 iter_next (iter); 257 258 _dbus_assert (message != NULL); 259 260 generate_from_message (data, expected_validity, message); 261 262 dbus_message_unref (message); 263 264 return TRUE; 265} 266 267static dbus_bool_t 268generate_trivial (DBusMessageDataIter *iter, 269 DBusString *data, 270 DBusValidity *expected_validity) 271{ 272 return generate_outer (iter, data, expected_validity, 273 generate_trivial_inner); 274} 275 276static dbus_bool_t 277generate_many_bodies (DBusMessageDataIter *iter, 278 DBusString *data, 279 DBusValidity *expected_validity) 280{ 281 return generate_outer (iter, data, expected_validity, 282 generate_many_bodies_inner); 283} 284 285static DBusMessage* 286simple_method_call (void) 287{ 288 DBusMessage *message; 289 /* Keeping this small makes stuff go faster */ 290 message = dbus_message_new_method_call ("o.b.Q", 291 "/f/b", 292 "o.b.Z", 293 "Fro"); 294 if (message == NULL) 295 _dbus_assert_not_reached ("oom"); 296 return message; 297} 298 299static DBusMessage* 300simple_signal (void) 301{ 302 DBusMessage *message; 303 message = dbus_message_new_signal ("/f/b", 304 "o.b.Z", 305 "Fro"); 306 if (message == NULL) 307 _dbus_assert_not_reached ("oom"); 308 return message; 309} 310 311static DBusMessage* 312simple_method_return (void) 313{ 314 DBusMessage *message; 315 message = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_RETURN); 316 if (message == NULL) 317 _dbus_assert_not_reached ("oom"); 318 319 set_reply_serial (message); 320 321 return message; 322} 323 324static DBusMessage* 325simple_error (void) 326{ 327 DBusMessage *message; 328 message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR); 329 if (message == NULL) 330 _dbus_assert_not_reached ("oom"); 331 332 if (!dbus_message_set_error_name (message, "foo.bar")) 333 _dbus_assert_not_reached ("oom"); 334 335 set_reply_serial (message); 336 337 return message; 338} 339 340static DBusMessage* 341message_with_nesting_levels (int levels) 342{ 343 DBusMessage *message; 344 dbus_int32_t v_INT32; 345 DBusMessageIter *parents; 346 DBusMessageIter *children; 347 int i; 348 349 /* If levels is higher it breaks sig_refcount in DBusMessageRealIter 350 * in dbus-message.c, this assert is just to help you know you need 351 * to fix that if you hit it 352 */ 353 _dbus_assert (levels < 256); 354 355 parents = dbus_new(DBusMessageIter, levels + 1); 356 children = dbus_new(DBusMessageIter, levels + 1); 357 358 v_INT32 = 42; 359 message = simple_method_call (); 360 361 i = 0; 362 dbus_message_iter_init_append (message, &parents[i]); 363 while (i < levels) 364 { 365 dbus_message_iter_open_container (&parents[i], DBUS_TYPE_VARIANT, 366 i == (levels - 1) ? 367 DBUS_TYPE_INT32_AS_STRING : 368 DBUS_TYPE_VARIANT_AS_STRING, 369 &children[i]); 370 ++i; 371 parents[i] = children[i-1]; 372 } 373 --i; 374 dbus_message_iter_append_basic (&children[i], DBUS_TYPE_INT32, &v_INT32); 375 while (i >= 0) 376 { 377 dbus_message_iter_close_container (&parents[i], &children[i]); 378 --i; 379 } 380 381 dbus_free(parents); 382 dbus_free(children); 383 384 return message; 385} 386 387static dbus_bool_t 388generate_special (DBusMessageDataIter *iter, 389 DBusString *data, 390 DBusValidity *expected_validity) 391{ 392 int item_seq; 393 DBusMessage *message; 394 int pos; 395 dbus_int32_t v_INT32; 396 397 _dbus_assert (_dbus_string_get_length (data) == 0); 398 399 message = NULL; 400 pos = -1; 401 v_INT32 = 42; 402 item_seq = iter_get_sequence (iter); 403 404 if (item_seq == 0) 405 { 406 message = simple_method_call (); 407 if (!dbus_message_append_args (message, 408 DBUS_TYPE_INT32, &v_INT32, 409 DBUS_TYPE_INT32, &v_INT32, 410 DBUS_TYPE_INT32, &v_INT32, 411 DBUS_TYPE_INVALID)) 412 _dbus_assert_not_reached ("oom"); 413 414 _dbus_header_get_field_raw (&message->header, 415 DBUS_HEADER_FIELD_SIGNATURE, 416 NULL, &pos); 417 generate_from_message (data, expected_validity, message); 418 419 /* set an invalid typecode */ 420 _dbus_string_set_byte (data, pos + 1, '$'); 421 422 *expected_validity = DBUS_INVALID_UNKNOWN_TYPECODE; 423 } 424 else if (item_seq == 1) 425 { 426 char long_sig[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH+2]; 427 const char *v_STRING; 428 int i; 429 430 message = simple_method_call (); 431 if (!dbus_message_append_args (message, 432 DBUS_TYPE_INT32, &v_INT32, 433 DBUS_TYPE_INT32, &v_INT32, 434 DBUS_TYPE_INT32, &v_INT32, 435 DBUS_TYPE_INVALID)) 436 _dbus_assert_not_reached ("oom"); 437 438 i = 0; 439 while (i < (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH + 1)) 440 { 441 long_sig[i] = DBUS_TYPE_ARRAY; 442 ++i; 443 } 444 long_sig[i] = DBUS_TYPE_INVALID; 445 446 v_STRING = long_sig; 447 if (!_dbus_header_set_field_basic (&message->header, 448 DBUS_HEADER_FIELD_SIGNATURE, 449 DBUS_TYPE_SIGNATURE, 450 &v_STRING)) 451 _dbus_assert_not_reached ("oom"); 452 453 _dbus_header_get_field_raw (&message->header, 454 DBUS_HEADER_FIELD_SIGNATURE, 455 NULL, &pos); 456 generate_from_message (data, expected_validity, message); 457 458 *expected_validity = DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION; 459 } 460 else if (item_seq == 2) 461 { 462 char long_sig[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*2+4]; 463 const char *v_STRING; 464 int i; 465 466 message = simple_method_call (); 467 if (!dbus_message_append_args (message, 468 DBUS_TYPE_INT32, &v_INT32, 469 DBUS_TYPE_INT32, &v_INT32, 470 DBUS_TYPE_INT32, &v_INT32, 471 DBUS_TYPE_INVALID)) 472 _dbus_assert_not_reached ("oom"); 473 474 i = 0; 475 while (i <= (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH + 1)) 476 { 477 long_sig[i] = DBUS_STRUCT_BEGIN_CHAR; 478 ++i; 479 } 480 481 long_sig[i] = DBUS_TYPE_INT32; 482 ++i; 483 484 while (i < (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*2 + 3)) 485 { 486 long_sig[i] = DBUS_STRUCT_END_CHAR; 487 ++i; 488 } 489 long_sig[i] = DBUS_TYPE_INVALID; 490 491 v_STRING = long_sig; 492 if (!_dbus_header_set_field_basic (&message->header, 493 DBUS_HEADER_FIELD_SIGNATURE, 494 DBUS_TYPE_SIGNATURE, 495 &v_STRING)) 496 _dbus_assert_not_reached ("oom"); 497 498 _dbus_header_get_field_raw (&message->header, 499 DBUS_HEADER_FIELD_SIGNATURE, 500 NULL, &pos); 501 generate_from_message (data, expected_validity, message); 502 503 *expected_validity = DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION; 504 } 505 else if (item_seq == 3) 506 { 507 message = simple_method_call (); 508 if (!dbus_message_append_args (message, 509 DBUS_TYPE_INT32, &v_INT32, 510 DBUS_TYPE_INT32, &v_INT32, 511 DBUS_TYPE_INT32, &v_INT32, 512 DBUS_TYPE_INVALID)) 513 _dbus_assert_not_reached ("oom"); 514 515 _dbus_header_get_field_raw (&message->header, 516 DBUS_HEADER_FIELD_SIGNATURE, 517 NULL, &pos); 518 generate_from_message (data, expected_validity, message); 519 520 _dbus_string_set_byte (data, pos + 1, DBUS_STRUCT_BEGIN_CHAR); 521 522 *expected_validity = DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED; 523 } 524 else if (item_seq == 4) 525 { 526 message = simple_method_call (); 527 if (!dbus_message_append_args (message, 528 DBUS_TYPE_INT32, &v_INT32, 529 DBUS_TYPE_INT32, &v_INT32, 530 DBUS_TYPE_INT32, &v_INT32, 531 DBUS_TYPE_INVALID)) 532 _dbus_assert_not_reached ("oom"); 533 534 _dbus_header_get_field_raw (&message->header, 535 DBUS_HEADER_FIELD_SIGNATURE, 536 NULL, &pos); 537 generate_from_message (data, expected_validity, message); 538 539 _dbus_string_set_byte (data, pos + 1, DBUS_STRUCT_END_CHAR); 540 541 *expected_validity = DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED; 542 } 543 else if (item_seq == 5) 544 { 545 message = simple_method_call (); 546 if (!dbus_message_append_args (message, 547 DBUS_TYPE_INT32, &v_INT32, 548 DBUS_TYPE_INT32, &v_INT32, 549 DBUS_TYPE_INT32, &v_INT32, 550 DBUS_TYPE_INVALID)) 551 _dbus_assert_not_reached ("oom"); 552 553 _dbus_header_get_field_raw (&message->header, 554 DBUS_HEADER_FIELD_SIGNATURE, 555 NULL, &pos); 556 generate_from_message (data, expected_validity, message); 557 558 _dbus_string_set_byte (data, pos + 1, DBUS_STRUCT_BEGIN_CHAR); 559 _dbus_string_set_byte (data, pos + 2, DBUS_STRUCT_END_CHAR); 560 561 *expected_validity = DBUS_INVALID_STRUCT_HAS_NO_FIELDS; 562 } 563 else if (item_seq == 6) 564 { 565 message = simple_method_call (); 566 generate_from_message (data, expected_validity, message); 567 568 _dbus_string_set_byte (data, TYPE_OFFSET, DBUS_MESSAGE_TYPE_INVALID); 569 570 *expected_validity = DBUS_INVALID_BAD_MESSAGE_TYPE; 571 } 572 else if (item_seq == 7) 573 { 574 /* Messages of unknown type are considered valid */ 575 message = simple_method_call (); 576 generate_from_message (data, expected_validity, message); 577 578 _dbus_string_set_byte (data, TYPE_OFFSET, 100); 579 580 *expected_validity = DBUS_VALID; 581 } 582 else if (item_seq == 8) 583 { 584 char byte_order; 585 586 message = simple_method_call (); 587 byte_order = _dbus_header_get_byte_order (&message->header); 588 generate_from_message (data, expected_validity, message); 589 590 _dbus_marshal_set_uint32 (data, BODY_LENGTH_OFFSET, 591 DBUS_MAXIMUM_MESSAGE_LENGTH / 2 + 4, 592 byte_order); 593 _dbus_marshal_set_uint32 (data, FIELDS_ARRAY_LENGTH_OFFSET, 594 DBUS_MAXIMUM_MESSAGE_LENGTH / 2 + 4, 595 byte_order); 596 *expected_validity = DBUS_INVALID_MESSAGE_TOO_LONG; 597 } 598 else if (item_seq == 9) 599 { 600 const char *v_STRING = "not a valid bus name"; 601 message = simple_method_call (); 602 603 if (!_dbus_header_set_field_basic (&message->header, 604 DBUS_HEADER_FIELD_SENDER, 605 DBUS_TYPE_STRING, &v_STRING)) 606 _dbus_assert_not_reached ("oom"); 607 608 generate_from_message (data, expected_validity, message); 609 610 *expected_validity = DBUS_INVALID_BAD_SENDER; 611 } 612 else if (item_seq == 10) 613 { 614 message = simple_method_call (); 615 616 if (!dbus_message_set_interface (message, DBUS_INTERFACE_LOCAL)) 617 _dbus_assert_not_reached ("oom"); 618 619 generate_from_message (data, expected_validity, message); 620 621 *expected_validity = DBUS_INVALID_USES_LOCAL_INTERFACE; 622 } 623 else if (item_seq == 11) 624 { 625 message = simple_method_call (); 626 627 if (!dbus_message_set_path (message, DBUS_PATH_LOCAL)) 628 _dbus_assert_not_reached ("oom"); 629 630 generate_from_message (data, expected_validity, message); 631 632 *expected_validity = DBUS_INVALID_USES_LOCAL_PATH; 633 } 634 else if (item_seq == 12) 635 { 636 /* Method calls don't have to have interface */ 637 message = simple_method_call (); 638 639 if (!dbus_message_set_interface (message, NULL)) 640 _dbus_assert_not_reached ("oom"); 641 642 generate_from_message (data, expected_validity, message); 643 644 *expected_validity = DBUS_VALID; 645 } 646 else if (item_seq == 13) 647 { 648 /* Signals require an interface */ 649 message = simple_signal (); 650 651 if (!dbus_message_set_interface (message, NULL)) 652 _dbus_assert_not_reached ("oom"); 653 654 generate_from_message (data, expected_validity, message); 655 656 *expected_validity = DBUS_INVALID_MISSING_INTERFACE; 657 } 658 else if (item_seq == 14) 659 { 660 message = simple_method_return (); 661 662 if (!_dbus_header_delete_field (&message->header, DBUS_HEADER_FIELD_REPLY_SERIAL)) 663 _dbus_assert_not_reached ("oom"); 664 665 generate_from_message (data, expected_validity, message); 666 667 *expected_validity = DBUS_INVALID_MISSING_REPLY_SERIAL; 668 } 669 else if (item_seq == 15) 670 { 671 message = simple_error (); 672 673 if (!dbus_message_set_error_name (message, NULL)) 674 _dbus_assert_not_reached ("oom"); 675 676 generate_from_message (data, expected_validity, message); 677 678 *expected_validity = DBUS_INVALID_MISSING_ERROR_NAME; 679 } 680 else if (item_seq == 16) 681 { 682 char long_sig[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*4+10]; 683 const char *v_STRING; 684 int i; 685 int n_begins; 686 687 message = simple_method_call (); 688 if (!dbus_message_append_args (message, 689 DBUS_TYPE_INT32, &v_INT32, 690 DBUS_TYPE_INT32, &v_INT32, 691 DBUS_TYPE_INT32, &v_INT32, 692 DBUS_TYPE_INVALID)) 693 _dbus_assert_not_reached ("oom"); 694 695 i = 0; 696 while (i <= (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*3 + 3)) 697 { 698 long_sig[i] = DBUS_TYPE_ARRAY; 699 ++i; 700 long_sig[i] = DBUS_DICT_ENTRY_BEGIN_CHAR; 701 ++i; 702 long_sig[i] = DBUS_TYPE_INT32; 703 ++i; 704 } 705 n_begins = i / 3; 706 707 long_sig[i] = DBUS_TYPE_INT32; 708 ++i; 709 710 while (n_begins > 0) 711 { 712 long_sig[i] = DBUS_DICT_ENTRY_END_CHAR; 713 ++i; 714 n_begins -= 1; 715 } 716 long_sig[i] = DBUS_TYPE_INVALID; 717 718 v_STRING = long_sig; 719 if (!_dbus_header_set_field_basic (&message->header, 720 DBUS_HEADER_FIELD_SIGNATURE, 721 DBUS_TYPE_SIGNATURE, 722 &v_STRING)) 723 _dbus_assert_not_reached ("oom"); 724 725 _dbus_header_get_field_raw (&message->header, 726 DBUS_HEADER_FIELD_SIGNATURE, 727 NULL, &pos); 728 generate_from_message (data, expected_validity, message); 729 730 *expected_validity = DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION; 731 } 732 else if (item_seq == 17) 733 { 734 message = simple_method_call (); 735 if (!dbus_message_append_args (message, 736 DBUS_TYPE_INT32, &v_INT32, 737 DBUS_TYPE_INT32, &v_INT32, 738 DBUS_TYPE_INT32, &v_INT32, 739 DBUS_TYPE_INVALID)) 740 _dbus_assert_not_reached ("oom"); 741 742 _dbus_header_get_field_raw (&message->header, 743 DBUS_HEADER_FIELD_SIGNATURE, 744 NULL, &pos); 745 generate_from_message (data, expected_validity, message); 746 747 _dbus_string_set_byte (data, pos + 1, DBUS_TYPE_ARRAY); 748 _dbus_string_set_byte (data, pos + 2, DBUS_DICT_ENTRY_BEGIN_CHAR); 749 750 *expected_validity = DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED; 751 } 752 else if (item_seq == 18) 753 { 754 message = simple_method_call (); 755 if (!dbus_message_append_args (message, 756 DBUS_TYPE_INT32, &v_INT32, 757 DBUS_TYPE_INT32, &v_INT32, 758 DBUS_TYPE_INT32, &v_INT32, 759 DBUS_TYPE_INVALID)) 760 _dbus_assert_not_reached ("oom"); 761 762 _dbus_header_get_field_raw (&message->header, 763 DBUS_HEADER_FIELD_SIGNATURE, 764 NULL, &pos); 765 generate_from_message (data, expected_validity, message); 766 767 _dbus_string_set_byte (data, pos + 1, DBUS_DICT_ENTRY_END_CHAR); 768 769 *expected_validity = DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED; 770 } 771 else if (item_seq == 19) 772 { 773 message = simple_method_call (); 774 if (!dbus_message_append_args (message, 775 DBUS_TYPE_INT32, &v_INT32, 776 DBUS_TYPE_INT32, &v_INT32, 777 DBUS_TYPE_INT32, &v_INT32, 778 DBUS_TYPE_INVALID)) 779 _dbus_assert_not_reached ("oom"); 780 781 _dbus_header_get_field_raw (&message->header, 782 DBUS_HEADER_FIELD_SIGNATURE, 783 NULL, &pos); 784 generate_from_message (data, expected_validity, message); 785 786 _dbus_string_set_byte (data, pos + 1, DBUS_TYPE_ARRAY); 787 _dbus_string_set_byte (data, pos + 2, DBUS_DICT_ENTRY_BEGIN_CHAR); 788 _dbus_string_set_byte (data, pos + 3, DBUS_DICT_ENTRY_END_CHAR); 789 790 *expected_validity = DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS; 791 } 792 else if (item_seq == 20) 793 { 794 /* 64 levels of nesting is OK */ 795 message = message_with_nesting_levels(64); 796 797 generate_from_message (data, expected_validity, message); 798 799 *expected_validity = DBUS_VALID; 800 } 801 else if (item_seq == 21) 802 { 803 /* 65 levels of nesting is not OK */ 804 message = message_with_nesting_levels(65); 805 806 generate_from_message (data, expected_validity, message); 807 808 *expected_validity = DBUS_INVALID_NESTED_TOO_DEEPLY; 809 } 810 else 811 { 812 return FALSE; 813 } 814 815 if (message) 816 dbus_message_unref (message); 817 818 iter_next (iter); 819 return TRUE; 820} 821 822static dbus_bool_t 823generate_wrong_length (DBusMessageDataIter *iter, 824 DBusString *data, 825 DBusValidity *expected_validity) 826{ 827 int lengths[] = { -42, -17, -16, -15, -9, -8, -7, -6, -5, -4, -3, -2, -1, 828 1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 16, 30 }; 829 int adjust; 830 int len_seq; 831 832 restart: 833 len_seq = iter_get_sequence (iter); 834 if (len_seq == _DBUS_N_ELEMENTS (lengths)) 835 return FALSE; 836 837 _dbus_assert (len_seq < _DBUS_N_ELEMENTS (lengths)); 838 839 iter_recurse (iter); 840 if (!generate_many_bodies (iter, data, expected_validity)) 841 { 842 iter_set_sequence (iter, 0); /* reset to first body */ 843 iter_unrecurse (iter); 844 iter_next (iter); /* next length adjustment */ 845 goto restart; 846 } 847 iter_unrecurse (iter); 848 849 adjust = lengths[len_seq]; 850 851 if (adjust < 0) 852 { 853 if ((_dbus_string_get_length (data) + adjust) < DBUS_MINIMUM_HEADER_SIZE) 854 _dbus_string_set_length (data, DBUS_MINIMUM_HEADER_SIZE); 855 else 856 _dbus_string_shorten (data, - adjust); 857 *expected_validity = DBUS_INVALID_FOR_UNKNOWN_REASON; 858 } 859 else 860 { 861 if (!_dbus_string_lengthen (data, adjust)) 862 _dbus_assert_not_reached ("oom"); 863 *expected_validity = DBUS_INVALID_TOO_MUCH_DATA; 864 } 865 866 /* Fixup lengths */ 867 { 868 int old_body_len; 869 int new_body_len; 870 int byte_order; 871 872 _dbus_assert (_dbus_string_get_length (data) >= DBUS_MINIMUM_HEADER_SIZE); 873 874 byte_order = _dbus_string_get_byte (data, BYTE_ORDER_OFFSET); 875 old_body_len = _dbus_marshal_read_uint32 (data, 876 BODY_LENGTH_OFFSET, 877 byte_order, 878 NULL); 879 _dbus_assert (old_body_len < _dbus_string_get_length (data)); 880 new_body_len = old_body_len + adjust; 881 if (new_body_len < 0) 882 { 883 new_body_len = 0; 884 /* we just munged the header, and aren't sure how */ 885 *expected_validity = DBUS_VALIDITY_UNKNOWN; 886 } 887 888 _dbus_verbose ("changing body len from %u to %u by adjust %d\n", 889 old_body_len, new_body_len, adjust); 890 891 _dbus_marshal_set_uint32 (data, BODY_LENGTH_OFFSET, 892 new_body_len, 893 byte_order); 894 } 895 896 return TRUE; 897} 898 899static dbus_bool_t 900generate_byte_changed (DBusMessageDataIter *iter, 901 DBusString *data, 902 DBusValidity *expected_validity) 903{ 904 int byte_seq; 905 int v_BYTE; 906 907 /* This is a little convoluted to make the bodies the 908 * outer loop and each byte of each body the inner 909 * loop 910 */ 911 912 restart: 913 if (!generate_many_bodies (iter, data, expected_validity)) 914 return FALSE; 915 916 iter_recurse (iter); 917 byte_seq = iter_get_sequence (iter); 918 iter_next (iter); 919 iter_unrecurse (iter); 920 921 if (byte_seq == _dbus_string_get_length (data)) 922 { 923 _dbus_string_set_length (data, 0); 924 /* reset byte count */ 925 iter_recurse (iter); 926 iter_set_sequence (iter, 0); 927 iter_unrecurse (iter); 928 goto restart; 929 } 930 else 931 { 932 /* Undo the "next" in generate_many_bodies */ 933 iter_set_sequence (iter, iter_get_sequence (iter) - 1); 934 } 935 936 _dbus_assert (byte_seq < _dbus_string_get_length (data)); 937 v_BYTE = _dbus_string_get_byte (data, byte_seq); 938 v_BYTE += byte_seq; /* arbitrary but deterministic change to the byte */ 939 _dbus_string_set_byte (data, byte_seq, v_BYTE); 940 *expected_validity = DBUS_VALIDITY_UNKNOWN; 941 942 return TRUE; 943} 944 945#if 0 946/* This is really expensive and doesn't add too much coverage */ 947 948static dbus_bool_t 949find_next_typecode (DBusMessageDataIter *iter, 950 DBusString *data, 951 DBusValidity *expected_validity) 952{ 953 int body_seq; 954 int byte_seq; 955 int base_depth; 956 957 base_depth = iter->depth; 958 959 restart: 960 _dbus_assert (iter->depth == (base_depth + 0)); 961 _dbus_string_set_length (data, 0); 962 963 body_seq = iter_get_sequence (iter); 964 965 if (!generate_many_bodies (iter, data, expected_validity)) 966 return FALSE; 967 /* Undo the "next" in generate_many_bodies */ 968 iter_set_sequence (iter, body_seq); 969 970 iter_recurse (iter); 971 while (TRUE) 972 { 973 _dbus_assert (iter->depth == (base_depth + 1)); 974 975 byte_seq = iter_get_sequence (iter); 976 977 _dbus_assert (byte_seq <= _dbus_string_get_length (data)); 978 979 if (byte_seq == _dbus_string_get_length (data)) 980 { 981 /* reset byte count */ 982 iter_set_sequence (iter, 0); 983 iter_unrecurse (iter); 984 _dbus_assert (iter->depth == (base_depth + 0)); 985 iter_next (iter); /* go to the next body */ 986 goto restart; 987 } 988 989 _dbus_assert (byte_seq < _dbus_string_get_length (data)); 990 991 if (dbus_type_is_valid (_dbus_string_get_byte (data, byte_seq))) 992 break; 993 else 994 iter_next (iter); 995 } 996 997 _dbus_assert (byte_seq == iter_get_sequence (iter)); 998 _dbus_assert (byte_seq < _dbus_string_get_length (data)); 999 1000 iter_unrecurse (iter); 1001 1002 _dbus_assert (iter->depth == (base_depth + 0)); 1003 1004 return TRUE; 1005} 1006 1007static const int typecodes[] = { 1008 DBUS_TYPE_INVALID, 1009 DBUS_TYPE_BYTE, 1010 DBUS_TYPE_BOOLEAN, 1011 DBUS_TYPE_INT16, 1012 DBUS_TYPE_UINT16, 1013 DBUS_TYPE_INT32, 1014 DBUS_TYPE_UINT32, 1015 DBUS_TYPE_INT64, 1016 DBUS_TYPE_UINT64, 1017 DBUS_TYPE_DOUBLE, 1018 DBUS_TYPE_STRING, 1019 DBUS_TYPE_OBJECT_PATH, 1020 DBUS_TYPE_SIGNATURE, 1021 DBUS_TYPE_ARRAY, 1022 DBUS_TYPE_VARIANT, 1023 DBUS_STRUCT_BEGIN_CHAR, 1024 DBUS_STRUCT_END_CHAR, 1025 DBUS_DICT_ENTRY_BEGIN_CHAR, 1026 DBUS_DICT_ENTRY_END_CHAR, 1027 DBUS_TYPE_UNIX_FD, 1028 255 /* random invalid typecode */ 1029}; 1030 1031static dbus_bool_t 1032generate_typecode_changed (DBusMessageDataIter *iter, 1033 DBusString *data, 1034 DBusValidity *expected_validity) 1035{ 1036 int byte_seq; 1037 int typecode_seq; 1038 int base_depth; 1039 1040 base_depth = iter->depth; 1041 1042 restart: 1043 _dbus_assert (iter->depth == (base_depth + 0)); 1044 _dbus_string_set_length (data, 0); 1045 1046 if (!find_next_typecode (iter, data, expected_validity)) 1047 return FALSE; 1048 1049 iter_recurse (iter); 1050 byte_seq = iter_get_sequence (iter); 1051 1052 _dbus_assert (byte_seq < _dbus_string_get_length (data)); 1053 1054 iter_recurse (iter); 1055 typecode_seq = iter_get_sequence (iter); 1056 iter_next (iter); 1057 1058 _dbus_assert (typecode_seq <= _DBUS_N_ELEMENTS (typecodes)); 1059 1060 if (typecode_seq == _DBUS_N_ELEMENTS (typecodes)) 1061 { 1062 _dbus_assert (iter->depth == (base_depth + 2)); 1063 iter_set_sequence (iter, 0); /* reset typecode sequence */ 1064 iter_unrecurse (iter); 1065 _dbus_assert (iter->depth == (base_depth + 1)); 1066 iter_next (iter); /* go to the next byte_seq */ 1067 iter_unrecurse (iter); 1068 _dbus_assert (iter->depth == (base_depth + 0)); 1069 goto restart; 1070 } 1071 1072 _dbus_assert (iter->depth == (base_depth + 2)); 1073 iter_unrecurse (iter); 1074 _dbus_assert (iter->depth == (base_depth + 1)); 1075 iter_unrecurse (iter); 1076 _dbus_assert (iter->depth == (base_depth + 0)); 1077 1078#if 0 1079 printf ("Changing byte %d in message %d to %c\n", 1080 byte_seq, iter_get_sequence (iter), typecodes[typecode_seq]); 1081#endif 1082 1083 _dbus_string_set_byte (data, byte_seq, typecodes[typecode_seq]); 1084 *expected_validity = DBUS_VALIDITY_UNKNOWN; 1085 return TRUE; 1086} 1087#endif 1088 1089typedef struct 1090{ 1091 ChangeType type; 1092 dbus_uint32_t value; /* cast to signed for adjusts */ 1093} UIntChange; 1094 1095static const UIntChange uint32_changes[] = { 1096 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) -1 }, 1097 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) -2 }, 1098 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) -3 }, 1099 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) 1 }, 1100 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) 2 }, 1101 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) 3 }, 1102 { CHANGE_TYPE_ABSOLUTE, _DBUS_UINT32_MAX }, 1103 { CHANGE_TYPE_ABSOLUTE, 0 }, 1104 { CHANGE_TYPE_ABSOLUTE, 1 }, 1105 { CHANGE_TYPE_ABSOLUTE, _DBUS_UINT32_MAX - 1 }, 1106 { CHANGE_TYPE_ABSOLUTE, _DBUS_UINT32_MAX - 5 } 1107}; 1108 1109static dbus_bool_t 1110generate_uint32_changed (DBusMessageDataIter *iter, 1111 DBusString *data, 1112 DBusValidity *expected_validity) 1113{ 1114 int body_seq; 1115 int byte_seq; 1116 int change_seq; 1117 dbus_uint32_t v_UINT32; 1118 int byte_order; 1119 const UIntChange *change; 1120 int base_depth; 1121 1122 /* Outer loop is each body, next loop is each change, 1123 * inner loop is each change location 1124 */ 1125 1126 base_depth = iter->depth; 1127 1128 next_body: 1129 _dbus_assert (iter->depth == (base_depth + 0)); 1130 _dbus_string_set_length (data, 0); 1131 body_seq = iter_get_sequence (iter); 1132 1133 if (!generate_many_bodies (iter, data, expected_validity)) 1134 return FALSE; 1135 1136 _dbus_assert (iter->depth == (base_depth + 0)); 1137 1138 iter_set_sequence (iter, body_seq); /* undo the "next" from generate_many_bodies */ 1139 iter_recurse (iter); 1140 next_change: 1141 _dbus_assert (iter->depth == (base_depth + 1)); 1142 change_seq = iter_get_sequence (iter); 1143 1144 if (change_seq == _DBUS_N_ELEMENTS (uint32_changes)) 1145 { 1146 /* Reset change count */ 1147 iter_set_sequence (iter, 0); 1148 iter_unrecurse (iter); 1149 iter_next (iter); 1150 goto next_body; 1151 } 1152 1153 _dbus_assert (iter->depth == (base_depth + 1)); 1154 1155 iter_recurse (iter); 1156 _dbus_assert (iter->depth == (base_depth + 2)); 1157 byte_seq = iter_get_sequence (iter); 1158 /* skip 4 bytes at a time */ 1159 iter_next (iter); 1160 iter_next (iter); 1161 iter_next (iter); 1162 iter_next (iter); 1163 iter_unrecurse (iter); 1164 1165 _dbus_assert (_DBUS_ALIGN_VALUE (byte_seq, 4) == (unsigned) byte_seq); 1166 if (byte_seq >= (_dbus_string_get_length (data) - 4)) 1167 { 1168 /* reset byte count */ 1169 _dbus_assert (iter->depth == (base_depth + 1)); 1170 iter_recurse (iter); 1171 _dbus_assert (iter->depth == (base_depth + 2)); 1172 iter_set_sequence (iter, 0); 1173 iter_unrecurse (iter); 1174 _dbus_assert (iter->depth == (base_depth + 1)); 1175 iter_next (iter); 1176 goto next_change; 1177 } 1178 1179 _dbus_assert (byte_seq <= (_dbus_string_get_length (data) - 4)); 1180 1181 byte_order = _dbus_string_get_byte (data, BYTE_ORDER_OFFSET); 1182 1183 v_UINT32 = _dbus_marshal_read_uint32 (data, byte_seq, byte_order, NULL); 1184 1185 change = &uint32_changes[change_seq]; 1186 1187 if (change->type == CHANGE_TYPE_ADJUST) 1188 { 1189 v_UINT32 += (int) change->value; 1190 } 1191 else 1192 { 1193 v_UINT32 = change->value; 1194 } 1195 1196#if 0 1197 printf ("body %d change %d pos %d ", 1198 body_seq, change_seq, byte_seq); 1199 1200 if (change->type == CHANGE_TYPE_ADJUST) 1201 printf ("adjust by %d", (int) change->value); 1202 else 1203 printf ("set to %u", change->value); 1204 1205 printf (" \t%u -> %u\n", 1206 _dbus_marshal_read_uint32 (data, byte_seq, byte_order, NULL), 1207 v_UINT32); 1208#endif 1209 1210 _dbus_marshal_set_uint32 (data, byte_seq, v_UINT32, byte_order); 1211 *expected_validity = DBUS_VALIDITY_UNKNOWN; 1212 1213 _dbus_assert (iter->depth == (base_depth + 1)); 1214 iter_unrecurse (iter); 1215 _dbus_assert (iter->depth == (base_depth + 0)); 1216 1217 return TRUE; 1218} 1219 1220typedef struct 1221{ 1222 const char *name; 1223 DBusMessageGeneratorFunc func; 1224} DBusMessageGenerator; 1225 1226static const DBusMessageGenerator generators[] = { 1227 { "trivial example of each message type", generate_trivial }, 1228 { "assorted arguments", generate_many_bodies }, 1229 { "assorted special cases", generate_special }, 1230 { "each uint32 modified", generate_uint32_changed }, 1231 { "wrong body lengths", generate_wrong_length }, 1232 { "each byte modified", generate_byte_changed }, 1233#if 0 1234 /* This is really expensive and doesn't add too much coverage */ 1235 { "change each typecode", generate_typecode_changed } 1236#endif 1237}; 1238 1239void 1240_dbus_message_data_free (DBusMessageData *data) 1241{ 1242 _dbus_string_free (&data->data); 1243} 1244 1245void 1246_dbus_message_data_iter_init (DBusMessageDataIter *iter) 1247{ 1248 int i; 1249 1250 iter->depth = 0; 1251 i = 0; 1252 while (i < _DBUS_MESSAGE_DATA_MAX_NESTING) 1253 { 1254 iter->sequence_nos[i] = 0; 1255 ++i; 1256 } 1257 iter->count = 0; 1258} 1259 1260dbus_bool_t 1261_dbus_message_data_iter_get_and_next (DBusMessageDataIter *iter, 1262 DBusMessageData *data) 1263{ 1264 DBusMessageGeneratorFunc func; 1265 int generator; 1266 1267 restart: 1268 generator = iter_get_sequence (iter); 1269 1270 if (generator == _DBUS_N_ELEMENTS (generators)) 1271 return FALSE; 1272 1273 iter_recurse (iter); 1274 1275 if (iter_first_in_series (iter)) 1276 { 1277 printf (" testing message loading: %s ", generators[generator].name); 1278 fflush (stdout); 1279 } 1280 1281 func = generators[generator].func; 1282 1283 if (!_dbus_string_init (&data->data)) 1284 _dbus_assert_not_reached ("oom"); 1285 1286 if ((*func)(iter, &data->data, &data->expected_validity)) 1287 ; 1288 else 1289 { 1290 iter_set_sequence (iter, 0); 1291 iter_unrecurse (iter); 1292 iter_next (iter); /* next generator */ 1293 _dbus_string_free (&data->data); 1294 printf ("%d test loads cumulative\n", iter->count); 1295 goto restart; 1296 } 1297 iter_unrecurse (iter); 1298 1299 iter->count += 1; 1300 return TRUE; 1301} 1302 1303#endif /* !DOXYGEN_SHOULD_SKIP_THIS */ 1304 1305#endif /* DBUS_BUILD_TESTS */ 1306