D-Bus 1.4.14
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-message-factory.c Generator of valid and invalid message data for test suite 00003 * 00004 * Copyright (C) 2005 Red Hat Inc. 00005 * 00006 * Licensed under the Academic Free License version 2.1 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 * 00022 */ 00023 #include <config.h> 00024 00025 #ifndef DOXYGEN_SHOULD_SKIP_THIS 00026 00027 #ifdef DBUS_BUILD_TESTS 00028 #include "dbus-message-factory.h" 00029 #include "dbus-message-private.h" 00030 #include "dbus-test.h" 00031 #include <stdio.h> 00032 00033 typedef enum 00034 { 00035 CHANGE_TYPE_ADJUST, 00036 CHANGE_TYPE_ABSOLUTE 00037 } ChangeType; 00038 00039 #define BYTE_ORDER_OFFSET 0 00040 #define TYPE_OFFSET 1 00041 #define BODY_LENGTH_OFFSET 4 00042 #define FIELDS_ARRAY_LENGTH_OFFSET 12 00043 00044 static void 00045 iter_recurse (DBusMessageDataIter *iter) 00046 { 00047 iter->depth += 1; 00048 _dbus_assert (iter->depth < _DBUS_MESSAGE_DATA_MAX_NESTING); 00049 _dbus_assert (iter->sequence_nos[iter->depth] >= 0); 00050 } 00051 00052 static int 00053 iter_get_sequence (DBusMessageDataIter *iter) 00054 { 00055 _dbus_assert (iter->sequence_nos[iter->depth] >= 0); 00056 return iter->sequence_nos[iter->depth]; 00057 } 00058 00059 static void 00060 iter_set_sequence (DBusMessageDataIter *iter, 00061 int sequence) 00062 { 00063 _dbus_assert (sequence >= 0); 00064 iter->sequence_nos[iter->depth] = sequence; 00065 } 00066 00067 static void 00068 iter_unrecurse (DBusMessageDataIter *iter) 00069 { 00070 iter->depth -= 1; 00071 _dbus_assert (iter->depth >= 0); 00072 } 00073 00074 static void 00075 iter_next (DBusMessageDataIter *iter) 00076 { 00077 iter->sequence_nos[iter->depth] += 1; 00078 } 00079 00080 static dbus_bool_t 00081 iter_first_in_series (DBusMessageDataIter *iter) 00082 { 00083 int i; 00084 00085 i = iter->depth; 00086 while (i < _DBUS_MESSAGE_DATA_MAX_NESTING) 00087 { 00088 if (iter->sequence_nos[i] != 0) 00089 return FALSE; 00090 ++i; 00091 } 00092 return TRUE; 00093 } 00094 00095 typedef dbus_bool_t (* DBusInnerGeneratorFunc) (DBusMessageDataIter *iter, 00096 DBusMessage **message_p); 00097 typedef dbus_bool_t (* DBusMessageGeneratorFunc) (DBusMessageDataIter *iter, 00098 DBusString *data, 00099 DBusValidity *expected_validity); 00100 00101 static void 00102 set_reply_serial (DBusMessage *message) 00103 { 00104 if (message == NULL) 00105 _dbus_assert_not_reached ("oom"); 00106 if (!dbus_message_set_reply_serial (message, 100)) 00107 _dbus_assert_not_reached ("oom"); 00108 } 00109 00110 static dbus_bool_t 00111 generate_trivial_inner (DBusMessageDataIter *iter, 00112 DBusMessage **message_p) 00113 { 00114 DBusMessage *message; 00115 00116 switch (iter_get_sequence (iter)) 00117 { 00118 case 0: 00119 message = dbus_message_new_method_call ("org.freedesktop.TextEditor", 00120 "/foo/bar", 00121 "org.freedesktop.DocumentFactory", 00122 "Create"); 00123 break; 00124 case 1: 00125 message = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_RETURN); 00126 set_reply_serial (message); 00127 break; 00128 case 2: 00129 message = dbus_message_new_signal ("/foo/bar", 00130 "org.freedesktop.DocumentFactory", 00131 "Created"); 00132 break; 00133 case 3: 00134 message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR); 00135 00136 if (!dbus_message_set_error_name (message, 00137 "org.freedesktop.TestErrorName")) 00138 _dbus_assert_not_reached ("oom"); 00139 00140 { 00141 DBusMessageIter iter; 00142 const char *v_STRING = "This is an error"; 00143 00144 dbus_message_iter_init_append (message, &iter); 00145 if (!dbus_message_iter_append_basic (&iter, 00146 DBUS_TYPE_STRING, 00147 &v_STRING)) 00148 _dbus_assert_not_reached ("oom"); 00149 } 00150 00151 set_reply_serial (message); 00152 break; 00153 default: 00154 return FALSE; 00155 } 00156 00157 if (message == NULL) 00158 _dbus_assert_not_reached ("oom"); 00159 00160 *message_p = message; 00161 00162 return TRUE; 00163 } 00164 00165 static dbus_bool_t 00166 generate_many_bodies_inner (DBusMessageDataIter *iter, 00167 DBusMessage **message_p) 00168 { 00169 DBusMessage *message; 00170 DBusString signature; 00171 DBusString body; 00172 00173 /* Keeping this small makes things go faster */ 00174 message = dbus_message_new_method_call ("o.z.F", 00175 "/", 00176 "o.z.B", 00177 "Nah"); 00178 if (message == NULL) 00179 _dbus_assert_not_reached ("oom"); 00180 00181 set_reply_serial (message); 00182 00183 if (!_dbus_string_init (&signature) || !_dbus_string_init (&body)) 00184 _dbus_assert_not_reached ("oom"); 00185 00186 if (dbus_internal_do_not_use_generate_bodies (iter_get_sequence (iter), 00187 message->byte_order, 00188 &signature, &body)) 00189 { 00190 const char *v_SIGNATURE; 00191 00192 v_SIGNATURE = _dbus_string_get_const_data (&signature); 00193 if (!_dbus_header_set_field_basic (&message->header, 00194 DBUS_HEADER_FIELD_SIGNATURE, 00195 DBUS_TYPE_SIGNATURE, 00196 &v_SIGNATURE)) 00197 _dbus_assert_not_reached ("oom"); 00198 00199 if (!_dbus_string_move (&body, 0, &message->body, 0)) 00200 _dbus_assert_not_reached ("oom"); 00201 00202 _dbus_marshal_set_uint32 (&message->header.data, BODY_LENGTH_OFFSET, 00203 _dbus_string_get_length (&message->body), 00204 message->byte_order); 00205 00206 *message_p = message; 00207 } 00208 else 00209 { 00210 dbus_message_unref (message); 00211 *message_p = NULL; 00212 } 00213 00214 _dbus_string_free (&signature); 00215 _dbus_string_free (&body); 00216 00217 return *message_p != NULL; 00218 } 00219 00220 static void 00221 generate_from_message (DBusString *data, 00222 DBusValidity *expected_validity, 00223 DBusMessage *message) 00224 { 00225 dbus_message_set_serial (message, 1); 00226 dbus_message_lock (message); 00227 00228 *expected_validity = DBUS_VALID; 00229 00230 /* move for efficiency, since we'll nuke the message anyway */ 00231 if (!_dbus_string_move (&message->header.data, 0, 00232 data, 0)) 00233 _dbus_assert_not_reached ("oom"); 00234 00235 if (!_dbus_string_copy (&message->body, 0, 00236 data, _dbus_string_get_length (data))) 00237 _dbus_assert_not_reached ("oom"); 00238 } 00239 00240 static dbus_bool_t 00241 generate_outer (DBusMessageDataIter *iter, 00242 DBusString *data, 00243 DBusValidity *expected_validity, 00244 DBusInnerGeneratorFunc func) 00245 { 00246 DBusMessage *message; 00247 00248 message = NULL; 00249 if (!(*func)(iter, &message)) 00250 return FALSE; 00251 00252 iter_next (iter); 00253 00254 _dbus_assert (message != NULL); 00255 00256 generate_from_message (data, expected_validity, message); 00257 00258 dbus_message_unref (message); 00259 00260 return TRUE; 00261 } 00262 00263 static dbus_bool_t 00264 generate_trivial (DBusMessageDataIter *iter, 00265 DBusString *data, 00266 DBusValidity *expected_validity) 00267 { 00268 return generate_outer (iter, data, expected_validity, 00269 generate_trivial_inner); 00270 } 00271 00272 static dbus_bool_t 00273 generate_many_bodies (DBusMessageDataIter *iter, 00274 DBusString *data, 00275 DBusValidity *expected_validity) 00276 { 00277 return generate_outer (iter, data, expected_validity, 00278 generate_many_bodies_inner); 00279 } 00280 00281 static DBusMessage* 00282 simple_method_call (void) 00283 { 00284 DBusMessage *message; 00285 /* Keeping this small makes stuff go faster */ 00286 message = dbus_message_new_method_call ("o.b.Q", 00287 "/f/b", 00288 "o.b.Z", 00289 "Fro"); 00290 if (message == NULL) 00291 _dbus_assert_not_reached ("oom"); 00292 return message; 00293 } 00294 00295 static DBusMessage* 00296 simple_signal (void) 00297 { 00298 DBusMessage *message; 00299 message = dbus_message_new_signal ("/f/b", 00300 "o.b.Z", 00301 "Fro"); 00302 if (message == NULL) 00303 _dbus_assert_not_reached ("oom"); 00304 return message; 00305 } 00306 00307 static DBusMessage* 00308 simple_method_return (void) 00309 { 00310 DBusMessage *message; 00311 message = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_RETURN); 00312 if (message == NULL) 00313 _dbus_assert_not_reached ("oom"); 00314 00315 set_reply_serial (message); 00316 00317 return message; 00318 } 00319 00320 static DBusMessage* 00321 simple_error (void) 00322 { 00323 DBusMessage *message; 00324 message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR); 00325 if (message == NULL) 00326 _dbus_assert_not_reached ("oom"); 00327 00328 if (!dbus_message_set_error_name (message, "foo.bar")) 00329 _dbus_assert_not_reached ("oom"); 00330 00331 set_reply_serial (message); 00332 00333 return message; 00334 } 00335 00336 static DBusMessage* 00337 message_with_nesting_levels (int levels) 00338 { 00339 DBusMessage *message; 00340 dbus_int32_t v_INT32; 00341 DBusMessageIter *parents; 00342 DBusMessageIter *children; 00343 int i; 00344 00345 /* If levels is higher it breaks sig_refcount in DBusMessageRealIter 00346 * in dbus-message.c, this assert is just to help you know you need 00347 * to fix that if you hit it 00348 */ 00349 _dbus_assert (levels < 256); 00350 00351 parents = dbus_new(DBusMessageIter, levels + 1); 00352 children = dbus_new(DBusMessageIter, levels + 1); 00353 00354 v_INT32 = 42; 00355 message = simple_method_call (); 00356 00357 i = 0; 00358 dbus_message_iter_init_append (message, &parents[i]); 00359 while (i < levels) 00360 { 00361 dbus_message_iter_open_container (&parents[i], DBUS_TYPE_VARIANT, 00362 i == (levels - 1) ? 00363 DBUS_TYPE_INT32_AS_STRING : 00364 DBUS_TYPE_VARIANT_AS_STRING, 00365 &children[i]); 00366 ++i; 00367 parents[i] = children[i-1]; 00368 } 00369 --i; 00370 dbus_message_iter_append_basic (&children[i], DBUS_TYPE_INT32, &v_INT32); 00371 while (i >= 0) 00372 { 00373 dbus_message_iter_close_container (&parents[i], &children[i]); 00374 --i; 00375 } 00376 00377 dbus_free(parents); 00378 dbus_free(children); 00379 00380 return message; 00381 } 00382 00383 static dbus_bool_t 00384 generate_special (DBusMessageDataIter *iter, 00385 DBusString *data, 00386 DBusValidity *expected_validity) 00387 { 00388 int item_seq; 00389 DBusMessage *message; 00390 int pos; 00391 dbus_int32_t v_INT32; 00392 00393 _dbus_assert (_dbus_string_get_length (data) == 0); 00394 00395 message = NULL; 00396 pos = -1; 00397 v_INT32 = 42; 00398 item_seq = iter_get_sequence (iter); 00399 00400 if (item_seq == 0) 00401 { 00402 message = simple_method_call (); 00403 if (!dbus_message_append_args (message, 00404 DBUS_TYPE_INT32, &v_INT32, 00405 DBUS_TYPE_INT32, &v_INT32, 00406 DBUS_TYPE_INT32, &v_INT32, 00407 DBUS_TYPE_INVALID)) 00408 _dbus_assert_not_reached ("oom"); 00409 00410 _dbus_header_get_field_raw (&message->header, 00411 DBUS_HEADER_FIELD_SIGNATURE, 00412 NULL, &pos); 00413 generate_from_message (data, expected_validity, message); 00414 00415 /* set an invalid typecode */ 00416 _dbus_string_set_byte (data, pos + 1, '$'); 00417 00418 *expected_validity = DBUS_INVALID_UNKNOWN_TYPECODE; 00419 } 00420 else if (item_seq == 1) 00421 { 00422 char long_sig[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH+2]; 00423 const char *v_STRING; 00424 int i; 00425 00426 message = simple_method_call (); 00427 if (!dbus_message_append_args (message, 00428 DBUS_TYPE_INT32, &v_INT32, 00429 DBUS_TYPE_INT32, &v_INT32, 00430 DBUS_TYPE_INT32, &v_INT32, 00431 DBUS_TYPE_INVALID)) 00432 _dbus_assert_not_reached ("oom"); 00433 00434 i = 0; 00435 while (i < (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH + 1)) 00436 { 00437 long_sig[i] = DBUS_TYPE_ARRAY; 00438 ++i; 00439 } 00440 long_sig[i] = DBUS_TYPE_INVALID; 00441 00442 v_STRING = long_sig; 00443 if (!_dbus_header_set_field_basic (&message->header, 00444 DBUS_HEADER_FIELD_SIGNATURE, 00445 DBUS_TYPE_SIGNATURE, 00446 &v_STRING)) 00447 _dbus_assert_not_reached ("oom"); 00448 00449 _dbus_header_get_field_raw (&message->header, 00450 DBUS_HEADER_FIELD_SIGNATURE, 00451 NULL, &pos); 00452 generate_from_message (data, expected_validity, message); 00453 00454 *expected_validity = DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION; 00455 } 00456 else if (item_seq == 2) 00457 { 00458 char long_sig[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*2+4]; 00459 const char *v_STRING; 00460 int i; 00461 00462 message = simple_method_call (); 00463 if (!dbus_message_append_args (message, 00464 DBUS_TYPE_INT32, &v_INT32, 00465 DBUS_TYPE_INT32, &v_INT32, 00466 DBUS_TYPE_INT32, &v_INT32, 00467 DBUS_TYPE_INVALID)) 00468 _dbus_assert_not_reached ("oom"); 00469 00470 i = 0; 00471 while (i <= (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH + 1)) 00472 { 00473 long_sig[i] = DBUS_STRUCT_BEGIN_CHAR; 00474 ++i; 00475 } 00476 00477 long_sig[i] = DBUS_TYPE_INT32; 00478 ++i; 00479 00480 while (i < (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*2 + 3)) 00481 { 00482 long_sig[i] = DBUS_STRUCT_END_CHAR; 00483 ++i; 00484 } 00485 long_sig[i] = DBUS_TYPE_INVALID; 00486 00487 v_STRING = long_sig; 00488 if (!_dbus_header_set_field_basic (&message->header, 00489 DBUS_HEADER_FIELD_SIGNATURE, 00490 DBUS_TYPE_SIGNATURE, 00491 &v_STRING)) 00492 _dbus_assert_not_reached ("oom"); 00493 00494 _dbus_header_get_field_raw (&message->header, 00495 DBUS_HEADER_FIELD_SIGNATURE, 00496 NULL, &pos); 00497 generate_from_message (data, expected_validity, message); 00498 00499 *expected_validity = DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION; 00500 } 00501 else if (item_seq == 3) 00502 { 00503 message = simple_method_call (); 00504 if (!dbus_message_append_args (message, 00505 DBUS_TYPE_INT32, &v_INT32, 00506 DBUS_TYPE_INT32, &v_INT32, 00507 DBUS_TYPE_INT32, &v_INT32, 00508 DBUS_TYPE_INVALID)) 00509 _dbus_assert_not_reached ("oom"); 00510 00511 _dbus_header_get_field_raw (&message->header, 00512 DBUS_HEADER_FIELD_SIGNATURE, 00513 NULL, &pos); 00514 generate_from_message (data, expected_validity, message); 00515 00516 _dbus_string_set_byte (data, pos + 1, DBUS_STRUCT_BEGIN_CHAR); 00517 00518 *expected_validity = DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED; 00519 } 00520 else if (item_seq == 4) 00521 { 00522 message = simple_method_call (); 00523 if (!dbus_message_append_args (message, 00524 DBUS_TYPE_INT32, &v_INT32, 00525 DBUS_TYPE_INT32, &v_INT32, 00526 DBUS_TYPE_INT32, &v_INT32, 00527 DBUS_TYPE_INVALID)) 00528 _dbus_assert_not_reached ("oom"); 00529 00530 _dbus_header_get_field_raw (&message->header, 00531 DBUS_HEADER_FIELD_SIGNATURE, 00532 NULL, &pos); 00533 generate_from_message (data, expected_validity, message); 00534 00535 _dbus_string_set_byte (data, pos + 1, DBUS_STRUCT_END_CHAR); 00536 00537 *expected_validity = DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED; 00538 } 00539 else if (item_seq == 5) 00540 { 00541 message = simple_method_call (); 00542 if (!dbus_message_append_args (message, 00543 DBUS_TYPE_INT32, &v_INT32, 00544 DBUS_TYPE_INT32, &v_INT32, 00545 DBUS_TYPE_INT32, &v_INT32, 00546 DBUS_TYPE_INVALID)) 00547 _dbus_assert_not_reached ("oom"); 00548 00549 _dbus_header_get_field_raw (&message->header, 00550 DBUS_HEADER_FIELD_SIGNATURE, 00551 NULL, &pos); 00552 generate_from_message (data, expected_validity, message); 00553 00554 _dbus_string_set_byte (data, pos + 1, DBUS_STRUCT_BEGIN_CHAR); 00555 _dbus_string_set_byte (data, pos + 2, DBUS_STRUCT_END_CHAR); 00556 00557 *expected_validity = DBUS_INVALID_STRUCT_HAS_NO_FIELDS; 00558 } 00559 else if (item_seq == 6) 00560 { 00561 message = simple_method_call (); 00562 generate_from_message (data, expected_validity, message); 00563 00564 _dbus_string_set_byte (data, TYPE_OFFSET, DBUS_MESSAGE_TYPE_INVALID); 00565 00566 *expected_validity = DBUS_INVALID_BAD_MESSAGE_TYPE; 00567 } 00568 else if (item_seq == 7) 00569 { 00570 /* Messages of unknown type are considered valid */ 00571 message = simple_method_call (); 00572 generate_from_message (data, expected_validity, message); 00573 00574 _dbus_string_set_byte (data, TYPE_OFFSET, 100); 00575 00576 *expected_validity = DBUS_VALID; 00577 } 00578 else if (item_seq == 8) 00579 { 00580 message = simple_method_call (); 00581 generate_from_message (data, expected_validity, message); 00582 00583 _dbus_marshal_set_uint32 (data, BODY_LENGTH_OFFSET, 00584 DBUS_MAXIMUM_MESSAGE_LENGTH / 2 + 4, 00585 message->byte_order); 00586 _dbus_marshal_set_uint32 (data, FIELDS_ARRAY_LENGTH_OFFSET, 00587 DBUS_MAXIMUM_MESSAGE_LENGTH / 2 + 4, 00588 message->byte_order); 00589 *expected_validity = DBUS_INVALID_MESSAGE_TOO_LONG; 00590 } 00591 else if (item_seq == 9) 00592 { 00593 const char *v_STRING = "not a valid bus name"; 00594 message = simple_method_call (); 00595 00596 if (!_dbus_header_set_field_basic (&message->header, 00597 DBUS_HEADER_FIELD_SENDER, 00598 DBUS_TYPE_STRING, &v_STRING)) 00599 _dbus_assert_not_reached ("oom"); 00600 00601 generate_from_message (data, expected_validity, message); 00602 00603 *expected_validity = DBUS_INVALID_BAD_SENDER; 00604 } 00605 else if (item_seq == 10) 00606 { 00607 message = simple_method_call (); 00608 00609 if (!dbus_message_set_interface (message, DBUS_INTERFACE_LOCAL)) 00610 _dbus_assert_not_reached ("oom"); 00611 00612 generate_from_message (data, expected_validity, message); 00613 00614 *expected_validity = DBUS_INVALID_USES_LOCAL_INTERFACE; 00615 } 00616 else if (item_seq == 11) 00617 { 00618 message = simple_method_call (); 00619 00620 if (!dbus_message_set_path (message, DBUS_PATH_LOCAL)) 00621 _dbus_assert_not_reached ("oom"); 00622 00623 generate_from_message (data, expected_validity, message); 00624 00625 *expected_validity = DBUS_INVALID_USES_LOCAL_PATH; 00626 } 00627 else if (item_seq == 12) 00628 { 00629 /* Method calls don't have to have interface */ 00630 message = simple_method_call (); 00631 00632 if (!dbus_message_set_interface (message, NULL)) 00633 _dbus_assert_not_reached ("oom"); 00634 00635 generate_from_message (data, expected_validity, message); 00636 00637 *expected_validity = DBUS_VALID; 00638 } 00639 else if (item_seq == 13) 00640 { 00641 /* Signals require an interface */ 00642 message = simple_signal (); 00643 00644 if (!dbus_message_set_interface (message, NULL)) 00645 _dbus_assert_not_reached ("oom"); 00646 00647 generate_from_message (data, expected_validity, message); 00648 00649 *expected_validity = DBUS_INVALID_MISSING_INTERFACE; 00650 } 00651 else if (item_seq == 14) 00652 { 00653 message = simple_method_return (); 00654 00655 if (!_dbus_header_delete_field (&message->header, DBUS_HEADER_FIELD_REPLY_SERIAL)) 00656 _dbus_assert_not_reached ("oom"); 00657 00658 generate_from_message (data, expected_validity, message); 00659 00660 *expected_validity = DBUS_INVALID_MISSING_REPLY_SERIAL; 00661 } 00662 else if (item_seq == 15) 00663 { 00664 message = simple_error (); 00665 00666 if (!dbus_message_set_error_name (message, NULL)) 00667 _dbus_assert_not_reached ("oom"); 00668 00669 generate_from_message (data, expected_validity, message); 00670 00671 *expected_validity = DBUS_INVALID_MISSING_ERROR_NAME; 00672 } 00673 else if (item_seq == 16) 00674 { 00675 char long_sig[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*4+10]; 00676 const char *v_STRING; 00677 int i; 00678 int n_begins; 00679 00680 message = simple_method_call (); 00681 if (!dbus_message_append_args (message, 00682 DBUS_TYPE_INT32, &v_INT32, 00683 DBUS_TYPE_INT32, &v_INT32, 00684 DBUS_TYPE_INT32, &v_INT32, 00685 DBUS_TYPE_INVALID)) 00686 _dbus_assert_not_reached ("oom"); 00687 00688 i = 0; 00689 while (i <= (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*3 + 3)) 00690 { 00691 long_sig[i] = DBUS_TYPE_ARRAY; 00692 ++i; 00693 long_sig[i] = DBUS_DICT_ENTRY_BEGIN_CHAR; 00694 ++i; 00695 long_sig[i] = DBUS_TYPE_INT32; 00696 ++i; 00697 } 00698 n_begins = i / 3; 00699 00700 long_sig[i] = DBUS_TYPE_INT32; 00701 ++i; 00702 00703 while (n_begins > 0) 00704 { 00705 long_sig[i] = DBUS_DICT_ENTRY_END_CHAR; 00706 ++i; 00707 n_begins -= 1; 00708 } 00709 long_sig[i] = DBUS_TYPE_INVALID; 00710 00711 v_STRING = long_sig; 00712 if (!_dbus_header_set_field_basic (&message->header, 00713 DBUS_HEADER_FIELD_SIGNATURE, 00714 DBUS_TYPE_SIGNATURE, 00715 &v_STRING)) 00716 _dbus_assert_not_reached ("oom"); 00717 00718 _dbus_header_get_field_raw (&message->header, 00719 DBUS_HEADER_FIELD_SIGNATURE, 00720 NULL, &pos); 00721 generate_from_message (data, expected_validity, message); 00722 00723 *expected_validity = DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION; 00724 } 00725 else if (item_seq == 17) 00726 { 00727 message = simple_method_call (); 00728 if (!dbus_message_append_args (message, 00729 DBUS_TYPE_INT32, &v_INT32, 00730 DBUS_TYPE_INT32, &v_INT32, 00731 DBUS_TYPE_INT32, &v_INT32, 00732 DBUS_TYPE_INVALID)) 00733 _dbus_assert_not_reached ("oom"); 00734 00735 _dbus_header_get_field_raw (&message->header, 00736 DBUS_HEADER_FIELD_SIGNATURE, 00737 NULL, &pos); 00738 generate_from_message (data, expected_validity, message); 00739 00740 _dbus_string_set_byte (data, pos + 1, DBUS_TYPE_ARRAY); 00741 _dbus_string_set_byte (data, pos + 2, DBUS_DICT_ENTRY_BEGIN_CHAR); 00742 00743 *expected_validity = DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED; 00744 } 00745 else if (item_seq == 18) 00746 { 00747 message = simple_method_call (); 00748 if (!dbus_message_append_args (message, 00749 DBUS_TYPE_INT32, &v_INT32, 00750 DBUS_TYPE_INT32, &v_INT32, 00751 DBUS_TYPE_INT32, &v_INT32, 00752 DBUS_TYPE_INVALID)) 00753 _dbus_assert_not_reached ("oom"); 00754 00755 _dbus_header_get_field_raw (&message->header, 00756 DBUS_HEADER_FIELD_SIGNATURE, 00757 NULL, &pos); 00758 generate_from_message (data, expected_validity, message); 00759 00760 _dbus_string_set_byte (data, pos + 1, DBUS_DICT_ENTRY_END_CHAR); 00761 00762 *expected_validity = DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED; 00763 } 00764 else if (item_seq == 19) 00765 { 00766 message = simple_method_call (); 00767 if (!dbus_message_append_args (message, 00768 DBUS_TYPE_INT32, &v_INT32, 00769 DBUS_TYPE_INT32, &v_INT32, 00770 DBUS_TYPE_INT32, &v_INT32, 00771 DBUS_TYPE_INVALID)) 00772 _dbus_assert_not_reached ("oom"); 00773 00774 _dbus_header_get_field_raw (&message->header, 00775 DBUS_HEADER_FIELD_SIGNATURE, 00776 NULL, &pos); 00777 generate_from_message (data, expected_validity, message); 00778 00779 _dbus_string_set_byte (data, pos + 1, DBUS_TYPE_ARRAY); 00780 _dbus_string_set_byte (data, pos + 2, DBUS_DICT_ENTRY_BEGIN_CHAR); 00781 _dbus_string_set_byte (data, pos + 3, DBUS_DICT_ENTRY_END_CHAR); 00782 00783 *expected_validity = DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS; 00784 } 00785 else if (item_seq == 20) 00786 { 00787 /* 64 levels of nesting is OK */ 00788 message = message_with_nesting_levels(64); 00789 00790 generate_from_message (data, expected_validity, message); 00791 00792 *expected_validity = DBUS_VALID; 00793 } 00794 else if (item_seq == 21) 00795 { 00796 /* 65 levels of nesting is not OK */ 00797 message = message_with_nesting_levels(65); 00798 00799 generate_from_message (data, expected_validity, message); 00800 00801 *expected_validity = DBUS_INVALID_NESTED_TOO_DEEPLY; 00802 } 00803 else 00804 { 00805 return FALSE; 00806 } 00807 00808 if (message) 00809 dbus_message_unref (message); 00810 00811 iter_next (iter); 00812 return TRUE; 00813 } 00814 00815 static dbus_bool_t 00816 generate_wrong_length (DBusMessageDataIter *iter, 00817 DBusString *data, 00818 DBusValidity *expected_validity) 00819 { 00820 int lengths[] = { -42, -17, -16, -15, -9, -8, -7, -6, -5, -4, -3, -2, -1, 00821 1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 16, 30 }; 00822 int adjust; 00823 int len_seq; 00824 00825 restart: 00826 len_seq = iter_get_sequence (iter); 00827 if (len_seq == _DBUS_N_ELEMENTS (lengths)) 00828 return FALSE; 00829 00830 _dbus_assert (len_seq < _DBUS_N_ELEMENTS (lengths)); 00831 00832 iter_recurse (iter); 00833 if (!generate_many_bodies (iter, data, expected_validity)) 00834 { 00835 iter_set_sequence (iter, 0); /* reset to first body */ 00836 iter_unrecurse (iter); 00837 iter_next (iter); /* next length adjustment */ 00838 goto restart; 00839 } 00840 iter_unrecurse (iter); 00841 00842 adjust = lengths[len_seq]; 00843 00844 if (adjust < 0) 00845 { 00846 if ((_dbus_string_get_length (data) + adjust) < DBUS_MINIMUM_HEADER_SIZE) 00847 _dbus_string_set_length (data, DBUS_MINIMUM_HEADER_SIZE); 00848 else 00849 _dbus_string_shorten (data, - adjust); 00850 *expected_validity = DBUS_INVALID_FOR_UNKNOWN_REASON; 00851 } 00852 else 00853 { 00854 if (!_dbus_string_lengthen (data, adjust)) 00855 _dbus_assert_not_reached ("oom"); 00856 *expected_validity = DBUS_INVALID_TOO_MUCH_DATA; 00857 } 00858 00859 /* Fixup lengths */ 00860 { 00861 int old_body_len; 00862 int new_body_len; 00863 int byte_order; 00864 00865 _dbus_assert (_dbus_string_get_length (data) >= DBUS_MINIMUM_HEADER_SIZE); 00866 00867 byte_order = _dbus_string_get_byte (data, BYTE_ORDER_OFFSET); 00868 old_body_len = _dbus_marshal_read_uint32 (data, 00869 BODY_LENGTH_OFFSET, 00870 byte_order, 00871 NULL); 00872 _dbus_assert (old_body_len < _dbus_string_get_length (data)); 00873 new_body_len = old_body_len + adjust; 00874 if (new_body_len < 0) 00875 { 00876 new_body_len = 0; 00877 /* we just munged the header, and aren't sure how */ 00878 *expected_validity = DBUS_VALIDITY_UNKNOWN; 00879 } 00880 00881 _dbus_verbose ("changing body len from %u to %u by adjust %d\n", 00882 old_body_len, new_body_len, adjust); 00883 00884 _dbus_marshal_set_uint32 (data, BODY_LENGTH_OFFSET, 00885 new_body_len, 00886 byte_order); 00887 } 00888 00889 return TRUE; 00890 } 00891 00892 static dbus_bool_t 00893 generate_byte_changed (DBusMessageDataIter *iter, 00894 DBusString *data, 00895 DBusValidity *expected_validity) 00896 { 00897 int byte_seq; 00898 int v_BYTE; 00899 00900 /* This is a little convoluted to make the bodies the 00901 * outer loop and each byte of each body the inner 00902 * loop 00903 */ 00904 00905 restart: 00906 if (!generate_many_bodies (iter, data, expected_validity)) 00907 return FALSE; 00908 00909 iter_recurse (iter); 00910 byte_seq = iter_get_sequence (iter); 00911 iter_next (iter); 00912 iter_unrecurse (iter); 00913 00914 if (byte_seq == _dbus_string_get_length (data)) 00915 { 00916 _dbus_string_set_length (data, 0); 00917 /* reset byte count */ 00918 iter_recurse (iter); 00919 iter_set_sequence (iter, 0); 00920 iter_unrecurse (iter); 00921 goto restart; 00922 } 00923 else 00924 { 00925 /* Undo the "next" in generate_many_bodies */ 00926 iter_set_sequence (iter, iter_get_sequence (iter) - 1); 00927 } 00928 00929 _dbus_assert (byte_seq < _dbus_string_get_length (data)); 00930 v_BYTE = _dbus_string_get_byte (data, byte_seq); 00931 v_BYTE += byte_seq; /* arbitrary but deterministic change to the byte */ 00932 _dbus_string_set_byte (data, byte_seq, v_BYTE); 00933 *expected_validity = DBUS_VALIDITY_UNKNOWN; 00934 00935 return TRUE; 00936 } 00937 00938 static dbus_bool_t 00939 find_next_typecode (DBusMessageDataIter *iter, 00940 DBusString *data, 00941 DBusValidity *expected_validity) 00942 { 00943 int body_seq; 00944 int byte_seq; 00945 int base_depth; 00946 00947 base_depth = iter->depth; 00948 00949 restart: 00950 _dbus_assert (iter->depth == (base_depth + 0)); 00951 _dbus_string_set_length (data, 0); 00952 00953 body_seq = iter_get_sequence (iter); 00954 00955 if (!generate_many_bodies (iter, data, expected_validity)) 00956 return FALSE; 00957 /* Undo the "next" in generate_many_bodies */ 00958 iter_set_sequence (iter, body_seq); 00959 00960 iter_recurse (iter); 00961 while (TRUE) 00962 { 00963 _dbus_assert (iter->depth == (base_depth + 1)); 00964 00965 byte_seq = iter_get_sequence (iter); 00966 00967 _dbus_assert (byte_seq <= _dbus_string_get_length (data)); 00968 00969 if (byte_seq == _dbus_string_get_length (data)) 00970 { 00971 /* reset byte count */ 00972 iter_set_sequence (iter, 0); 00973 iter_unrecurse (iter); 00974 _dbus_assert (iter->depth == (base_depth + 0)); 00975 iter_next (iter); /* go to the next body */ 00976 goto restart; 00977 } 00978 00979 _dbus_assert (byte_seq < _dbus_string_get_length (data)); 00980 00981 if (_dbus_type_is_valid (_dbus_string_get_byte (data, byte_seq))) 00982 break; 00983 else 00984 iter_next (iter); 00985 } 00986 00987 _dbus_assert (byte_seq == iter_get_sequence (iter)); 00988 _dbus_assert (byte_seq < _dbus_string_get_length (data)); 00989 00990 iter_unrecurse (iter); 00991 00992 _dbus_assert (iter->depth == (base_depth + 0)); 00993 00994 return TRUE; 00995 } 00996 00997 static const int typecodes[] = { 00998 DBUS_TYPE_INVALID, 00999 DBUS_TYPE_BYTE, 01000 DBUS_TYPE_BOOLEAN, 01001 DBUS_TYPE_INT16, 01002 DBUS_TYPE_UINT16, 01003 DBUS_TYPE_INT32, 01004 DBUS_TYPE_UINT32, 01005 DBUS_TYPE_INT64, 01006 DBUS_TYPE_UINT64, 01007 DBUS_TYPE_DOUBLE, 01008 DBUS_TYPE_STRING, 01009 DBUS_TYPE_OBJECT_PATH, 01010 DBUS_TYPE_SIGNATURE, 01011 DBUS_TYPE_ARRAY, 01012 DBUS_TYPE_VARIANT, 01013 DBUS_STRUCT_BEGIN_CHAR, 01014 DBUS_STRUCT_END_CHAR, 01015 DBUS_DICT_ENTRY_BEGIN_CHAR, 01016 DBUS_DICT_ENTRY_END_CHAR, 01017 DBUS_TYPE_UNIX_FD, 01018 255 /* random invalid typecode */ 01019 }; 01020 01021 static dbus_bool_t 01022 generate_typecode_changed (DBusMessageDataIter *iter, 01023 DBusString *data, 01024 DBusValidity *expected_validity) 01025 { 01026 int byte_seq; 01027 int typecode_seq; 01028 int base_depth; 01029 01030 base_depth = iter->depth; 01031 01032 restart: 01033 _dbus_assert (iter->depth == (base_depth + 0)); 01034 _dbus_string_set_length (data, 0); 01035 01036 if (!find_next_typecode (iter, data, expected_validity)) 01037 return FALSE; 01038 01039 iter_recurse (iter); 01040 byte_seq = iter_get_sequence (iter); 01041 01042 _dbus_assert (byte_seq < _dbus_string_get_length (data)); 01043 01044 iter_recurse (iter); 01045 typecode_seq = iter_get_sequence (iter); 01046 iter_next (iter); 01047 01048 _dbus_assert (typecode_seq <= _DBUS_N_ELEMENTS (typecodes)); 01049 01050 if (typecode_seq == _DBUS_N_ELEMENTS (typecodes)) 01051 { 01052 _dbus_assert (iter->depth == (base_depth + 2)); 01053 iter_set_sequence (iter, 0); /* reset typecode sequence */ 01054 iter_unrecurse (iter); 01055 _dbus_assert (iter->depth == (base_depth + 1)); 01056 iter_next (iter); /* go to the next byte_seq */ 01057 iter_unrecurse (iter); 01058 _dbus_assert (iter->depth == (base_depth + 0)); 01059 goto restart; 01060 } 01061 01062 _dbus_assert (iter->depth == (base_depth + 2)); 01063 iter_unrecurse (iter); 01064 _dbus_assert (iter->depth == (base_depth + 1)); 01065 iter_unrecurse (iter); 01066 _dbus_assert (iter->depth == (base_depth + 0)); 01067 01068 #if 0 01069 printf ("Changing byte %d in message %d to %c\n", 01070 byte_seq, iter_get_sequence (iter), typecodes[typecode_seq]); 01071 #endif 01072 01073 _dbus_string_set_byte (data, byte_seq, typecodes[typecode_seq]); 01074 *expected_validity = DBUS_VALIDITY_UNKNOWN; 01075 return TRUE; 01076 } 01077 01078 typedef struct 01079 { 01080 ChangeType type; 01081 dbus_uint32_t value; /* cast to signed for adjusts */ 01082 } UIntChange; 01083 01084 static const UIntChange uint32_changes[] = { 01085 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) -1 }, 01086 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) -2 }, 01087 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) -3 }, 01088 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) 1 }, 01089 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) 2 }, 01090 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) 3 }, 01091 { CHANGE_TYPE_ABSOLUTE, _DBUS_UINT32_MAX }, 01092 { CHANGE_TYPE_ABSOLUTE, 0 }, 01093 { CHANGE_TYPE_ABSOLUTE, 1 }, 01094 { CHANGE_TYPE_ABSOLUTE, _DBUS_UINT32_MAX - 1 }, 01095 { CHANGE_TYPE_ABSOLUTE, _DBUS_UINT32_MAX - 5 } 01096 }; 01097 01098 static dbus_bool_t 01099 generate_uint32_changed (DBusMessageDataIter *iter, 01100 DBusString *data, 01101 DBusValidity *expected_validity) 01102 { 01103 int body_seq; 01104 int byte_seq; 01105 int change_seq; 01106 dbus_uint32_t v_UINT32; 01107 int byte_order; 01108 const UIntChange *change; 01109 int base_depth; 01110 01111 /* Outer loop is each body, next loop is each change, 01112 * inner loop is each change location 01113 */ 01114 01115 base_depth = iter->depth; 01116 01117 next_body: 01118 _dbus_assert (iter->depth == (base_depth + 0)); 01119 _dbus_string_set_length (data, 0); 01120 body_seq = iter_get_sequence (iter); 01121 01122 if (!generate_many_bodies (iter, data, expected_validity)) 01123 return FALSE; 01124 01125 _dbus_assert (iter->depth == (base_depth + 0)); 01126 01127 iter_set_sequence (iter, body_seq); /* undo the "next" from generate_many_bodies */ 01128 iter_recurse (iter); 01129 next_change: 01130 _dbus_assert (iter->depth == (base_depth + 1)); 01131 change_seq = iter_get_sequence (iter); 01132 01133 if (change_seq == _DBUS_N_ELEMENTS (uint32_changes)) 01134 { 01135 /* Reset change count */ 01136 iter_set_sequence (iter, 0); 01137 iter_unrecurse (iter); 01138 iter_next (iter); 01139 goto next_body; 01140 } 01141 01142 _dbus_assert (iter->depth == (base_depth + 1)); 01143 01144 iter_recurse (iter); 01145 _dbus_assert (iter->depth == (base_depth + 2)); 01146 byte_seq = iter_get_sequence (iter); 01147 /* skip 4 bytes at a time */ 01148 iter_next (iter); 01149 iter_next (iter); 01150 iter_next (iter); 01151 iter_next (iter); 01152 iter_unrecurse (iter); 01153 01154 _dbus_assert (_DBUS_ALIGN_VALUE (byte_seq, 4) == (unsigned) byte_seq); 01155 if (byte_seq >= (_dbus_string_get_length (data) - 4)) 01156 { 01157 /* reset byte count */ 01158 _dbus_assert (iter->depth == (base_depth + 1)); 01159 iter_recurse (iter); 01160 _dbus_assert (iter->depth == (base_depth + 2)); 01161 iter_set_sequence (iter, 0); 01162 iter_unrecurse (iter); 01163 _dbus_assert (iter->depth == (base_depth + 1)); 01164 iter_next (iter); 01165 goto next_change; 01166 } 01167 01168 _dbus_assert (byte_seq <= (_dbus_string_get_length (data) - 4)); 01169 01170 byte_order = _dbus_string_get_byte (data, BYTE_ORDER_OFFSET); 01171 01172 v_UINT32 = _dbus_marshal_read_uint32 (data, byte_seq, byte_order, NULL); 01173 01174 change = &uint32_changes[change_seq]; 01175 01176 if (change->type == CHANGE_TYPE_ADJUST) 01177 { 01178 v_UINT32 += (int) change->value; 01179 } 01180 else 01181 { 01182 v_UINT32 = change->value; 01183 } 01184 01185 #if 0 01186 printf ("body %d change %d pos %d ", 01187 body_seq, change_seq, byte_seq); 01188 01189 if (change->type == CHANGE_TYPE_ADJUST) 01190 printf ("adjust by %d", (int) change->value); 01191 else 01192 printf ("set to %u", change->value); 01193 01194 printf (" \t%u -> %u\n", 01195 _dbus_marshal_read_uint32 (data, byte_seq, byte_order, NULL), 01196 v_UINT32); 01197 #endif 01198 01199 _dbus_marshal_set_uint32 (data, byte_seq, v_UINT32, byte_order); 01200 *expected_validity = DBUS_VALIDITY_UNKNOWN; 01201 01202 _dbus_assert (iter->depth == (base_depth + 1)); 01203 iter_unrecurse (iter); 01204 _dbus_assert (iter->depth == (base_depth + 0)); 01205 01206 return TRUE; 01207 } 01208 01209 typedef struct 01210 { 01211 const char *name; 01212 DBusMessageGeneratorFunc func; 01213 } DBusMessageGenerator; 01214 01215 static const DBusMessageGenerator generators[] = { 01216 { "trivial example of each message type", generate_trivial }, 01217 { "assorted arguments", generate_many_bodies }, 01218 { "assorted special cases", generate_special }, 01219 { "each uint32 modified", generate_uint32_changed }, 01220 { "wrong body lengths", generate_wrong_length }, 01221 { "each byte modified", generate_byte_changed }, 01222 #if 0 01223 /* This is really expensive and doesn't add too much coverage */ 01224 { "change each typecode", generate_typecode_changed } 01225 #endif 01226 }; 01227 01228 void 01229 _dbus_message_data_free (DBusMessageData *data) 01230 { 01231 _dbus_string_free (&data->data); 01232 } 01233 01234 void 01235 _dbus_message_data_iter_init (DBusMessageDataIter *iter) 01236 { 01237 int i; 01238 01239 iter->depth = 0; 01240 i = 0; 01241 while (i < _DBUS_MESSAGE_DATA_MAX_NESTING) 01242 { 01243 iter->sequence_nos[i] = 0; 01244 ++i; 01245 } 01246 iter->count = 0; 01247 } 01248 01249 dbus_bool_t 01250 _dbus_message_data_iter_get_and_next (DBusMessageDataIter *iter, 01251 DBusMessageData *data) 01252 { 01253 DBusMessageGeneratorFunc func; 01254 int generator; 01255 01256 restart: 01257 generator = iter_get_sequence (iter); 01258 01259 if (generator == _DBUS_N_ELEMENTS (generators)) 01260 return FALSE; 01261 01262 iter_recurse (iter); 01263 01264 if (iter_first_in_series (iter)) 01265 { 01266 printf (" testing message loading: %s ", generators[generator].name); 01267 fflush (stdout); 01268 } 01269 01270 func = generators[generator].func; 01271 01272 if (!_dbus_string_init (&data->data)) 01273 _dbus_assert_not_reached ("oom"); 01274 01275 if ((*func)(iter, &data->data, &data->expected_validity)) 01276 ; 01277 else 01278 { 01279 iter_set_sequence (iter, 0); 01280 iter_unrecurse (iter); 01281 iter_next (iter); /* next generator */ 01282 _dbus_string_free (&data->data); 01283 printf ("%d test loads cumulative\n", iter->count); 01284 goto restart; 01285 } 01286 iter_unrecurse (iter); 01287 01288 iter->count += 1; 01289 return TRUE; 01290 } 01291 01292 #endif /* !DOXYGEN_SHOULD_SKIP_THIS */ 01293 01294 #endif /* DBUS_BUILD_TESTS */