D-Bus 1.4.0
|
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 dbus_bool_t 00337 generate_special (DBusMessageDataIter *iter, 00338 DBusString *data, 00339 DBusValidity *expected_validity) 00340 { 00341 int item_seq; 00342 DBusMessage *message; 00343 int pos; 00344 dbus_int32_t v_INT32; 00345 00346 _dbus_assert (_dbus_string_get_length (data) == 0); 00347 00348 message = NULL; 00349 pos = -1; 00350 v_INT32 = 42; 00351 item_seq = iter_get_sequence (iter); 00352 00353 if (item_seq == 0) 00354 { 00355 message = simple_method_call (); 00356 if (!dbus_message_append_args (message, 00357 DBUS_TYPE_INT32, &v_INT32, 00358 DBUS_TYPE_INT32, &v_INT32, 00359 DBUS_TYPE_INT32, &v_INT32, 00360 DBUS_TYPE_INVALID)) 00361 _dbus_assert_not_reached ("oom"); 00362 00363 _dbus_header_get_field_raw (&message->header, 00364 DBUS_HEADER_FIELD_SIGNATURE, 00365 NULL, &pos); 00366 generate_from_message (data, expected_validity, message); 00367 00368 /* set an invalid typecode */ 00369 _dbus_string_set_byte (data, pos + 1, '$'); 00370 00371 *expected_validity = DBUS_INVALID_UNKNOWN_TYPECODE; 00372 } 00373 else if (item_seq == 1) 00374 { 00375 char long_sig[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH+2]; 00376 const char *v_STRING; 00377 int i; 00378 00379 message = simple_method_call (); 00380 if (!dbus_message_append_args (message, 00381 DBUS_TYPE_INT32, &v_INT32, 00382 DBUS_TYPE_INT32, &v_INT32, 00383 DBUS_TYPE_INT32, &v_INT32, 00384 DBUS_TYPE_INVALID)) 00385 _dbus_assert_not_reached ("oom"); 00386 00387 i = 0; 00388 while (i < (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH + 1)) 00389 { 00390 long_sig[i] = DBUS_TYPE_ARRAY; 00391 ++i; 00392 } 00393 long_sig[i] = DBUS_TYPE_INVALID; 00394 00395 v_STRING = long_sig; 00396 if (!_dbus_header_set_field_basic (&message->header, 00397 DBUS_HEADER_FIELD_SIGNATURE, 00398 DBUS_TYPE_SIGNATURE, 00399 &v_STRING)) 00400 _dbus_assert_not_reached ("oom"); 00401 00402 _dbus_header_get_field_raw (&message->header, 00403 DBUS_HEADER_FIELD_SIGNATURE, 00404 NULL, &pos); 00405 generate_from_message (data, expected_validity, message); 00406 00407 *expected_validity = DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION; 00408 } 00409 else if (item_seq == 2) 00410 { 00411 char long_sig[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*2+4]; 00412 const char *v_STRING; 00413 int i; 00414 00415 message = simple_method_call (); 00416 if (!dbus_message_append_args (message, 00417 DBUS_TYPE_INT32, &v_INT32, 00418 DBUS_TYPE_INT32, &v_INT32, 00419 DBUS_TYPE_INT32, &v_INT32, 00420 DBUS_TYPE_INVALID)) 00421 _dbus_assert_not_reached ("oom"); 00422 00423 i = 0; 00424 while (i <= (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH + 1)) 00425 { 00426 long_sig[i] = DBUS_STRUCT_BEGIN_CHAR; 00427 ++i; 00428 } 00429 00430 long_sig[i] = DBUS_TYPE_INT32; 00431 ++i; 00432 00433 while (i < (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*2 + 3)) 00434 { 00435 long_sig[i] = DBUS_STRUCT_END_CHAR; 00436 ++i; 00437 } 00438 long_sig[i] = DBUS_TYPE_INVALID; 00439 00440 v_STRING = long_sig; 00441 if (!_dbus_header_set_field_basic (&message->header, 00442 DBUS_HEADER_FIELD_SIGNATURE, 00443 DBUS_TYPE_SIGNATURE, 00444 &v_STRING)) 00445 _dbus_assert_not_reached ("oom"); 00446 00447 _dbus_header_get_field_raw (&message->header, 00448 DBUS_HEADER_FIELD_SIGNATURE, 00449 NULL, &pos); 00450 generate_from_message (data, expected_validity, message); 00451 00452 *expected_validity = DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION; 00453 } 00454 else if (item_seq == 3) 00455 { 00456 message = simple_method_call (); 00457 if (!dbus_message_append_args (message, 00458 DBUS_TYPE_INT32, &v_INT32, 00459 DBUS_TYPE_INT32, &v_INT32, 00460 DBUS_TYPE_INT32, &v_INT32, 00461 DBUS_TYPE_INVALID)) 00462 _dbus_assert_not_reached ("oom"); 00463 00464 _dbus_header_get_field_raw (&message->header, 00465 DBUS_HEADER_FIELD_SIGNATURE, 00466 NULL, &pos); 00467 generate_from_message (data, expected_validity, message); 00468 00469 _dbus_string_set_byte (data, pos + 1, DBUS_STRUCT_BEGIN_CHAR); 00470 00471 *expected_validity = DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED; 00472 } 00473 else if (item_seq == 4) 00474 { 00475 message = simple_method_call (); 00476 if (!dbus_message_append_args (message, 00477 DBUS_TYPE_INT32, &v_INT32, 00478 DBUS_TYPE_INT32, &v_INT32, 00479 DBUS_TYPE_INT32, &v_INT32, 00480 DBUS_TYPE_INVALID)) 00481 _dbus_assert_not_reached ("oom"); 00482 00483 _dbus_header_get_field_raw (&message->header, 00484 DBUS_HEADER_FIELD_SIGNATURE, 00485 NULL, &pos); 00486 generate_from_message (data, expected_validity, message); 00487 00488 _dbus_string_set_byte (data, pos + 1, DBUS_STRUCT_END_CHAR); 00489 00490 *expected_validity = DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED; 00491 } 00492 else if (item_seq == 5) 00493 { 00494 message = simple_method_call (); 00495 if (!dbus_message_append_args (message, 00496 DBUS_TYPE_INT32, &v_INT32, 00497 DBUS_TYPE_INT32, &v_INT32, 00498 DBUS_TYPE_INT32, &v_INT32, 00499 DBUS_TYPE_INVALID)) 00500 _dbus_assert_not_reached ("oom"); 00501 00502 _dbus_header_get_field_raw (&message->header, 00503 DBUS_HEADER_FIELD_SIGNATURE, 00504 NULL, &pos); 00505 generate_from_message (data, expected_validity, message); 00506 00507 _dbus_string_set_byte (data, pos + 1, DBUS_STRUCT_BEGIN_CHAR); 00508 _dbus_string_set_byte (data, pos + 2, DBUS_STRUCT_END_CHAR); 00509 00510 *expected_validity = DBUS_INVALID_STRUCT_HAS_NO_FIELDS; 00511 } 00512 else if (item_seq == 6) 00513 { 00514 message = simple_method_call (); 00515 generate_from_message (data, expected_validity, message); 00516 00517 _dbus_string_set_byte (data, TYPE_OFFSET, DBUS_MESSAGE_TYPE_INVALID); 00518 00519 *expected_validity = DBUS_INVALID_BAD_MESSAGE_TYPE; 00520 } 00521 else if (item_seq == 7) 00522 { 00523 /* Messages of unknown type are considered valid */ 00524 message = simple_method_call (); 00525 generate_from_message (data, expected_validity, message); 00526 00527 _dbus_string_set_byte (data, TYPE_OFFSET, 100); 00528 00529 *expected_validity = DBUS_VALID; 00530 } 00531 else if (item_seq == 8) 00532 { 00533 message = simple_method_call (); 00534 generate_from_message (data, expected_validity, message); 00535 00536 _dbus_marshal_set_uint32 (data, BODY_LENGTH_OFFSET, 00537 DBUS_MAXIMUM_MESSAGE_LENGTH / 2 + 4, 00538 message->byte_order); 00539 _dbus_marshal_set_uint32 (data, FIELDS_ARRAY_LENGTH_OFFSET, 00540 DBUS_MAXIMUM_MESSAGE_LENGTH / 2 + 4, 00541 message->byte_order); 00542 *expected_validity = DBUS_INVALID_MESSAGE_TOO_LONG; 00543 } 00544 else if (item_seq == 9) 00545 { 00546 const char *v_STRING = "not a valid bus name"; 00547 message = simple_method_call (); 00548 00549 if (!_dbus_header_set_field_basic (&message->header, 00550 DBUS_HEADER_FIELD_SENDER, 00551 DBUS_TYPE_STRING, &v_STRING)) 00552 _dbus_assert_not_reached ("oom"); 00553 00554 generate_from_message (data, expected_validity, message); 00555 00556 *expected_validity = DBUS_INVALID_BAD_SENDER; 00557 } 00558 else if (item_seq == 10) 00559 { 00560 message = simple_method_call (); 00561 00562 if (!dbus_message_set_interface (message, DBUS_INTERFACE_LOCAL)) 00563 _dbus_assert_not_reached ("oom"); 00564 00565 generate_from_message (data, expected_validity, message); 00566 00567 *expected_validity = DBUS_INVALID_USES_LOCAL_INTERFACE; 00568 } 00569 else if (item_seq == 11) 00570 { 00571 message = simple_method_call (); 00572 00573 if (!dbus_message_set_path (message, DBUS_PATH_LOCAL)) 00574 _dbus_assert_not_reached ("oom"); 00575 00576 generate_from_message (data, expected_validity, message); 00577 00578 *expected_validity = DBUS_INVALID_USES_LOCAL_PATH; 00579 } 00580 else if (item_seq == 12) 00581 { 00582 /* Method calls don't have to have interface */ 00583 message = simple_method_call (); 00584 00585 if (!dbus_message_set_interface (message, NULL)) 00586 _dbus_assert_not_reached ("oom"); 00587 00588 generate_from_message (data, expected_validity, message); 00589 00590 *expected_validity = DBUS_VALID; 00591 } 00592 else if (item_seq == 13) 00593 { 00594 /* Signals require an interface */ 00595 message = simple_signal (); 00596 00597 if (!dbus_message_set_interface (message, NULL)) 00598 _dbus_assert_not_reached ("oom"); 00599 00600 generate_from_message (data, expected_validity, message); 00601 00602 *expected_validity = DBUS_INVALID_MISSING_INTERFACE; 00603 } 00604 else if (item_seq == 14) 00605 { 00606 message = simple_method_return (); 00607 00608 if (!_dbus_header_delete_field (&message->header, DBUS_HEADER_FIELD_REPLY_SERIAL)) 00609 _dbus_assert_not_reached ("oom"); 00610 00611 generate_from_message (data, expected_validity, message); 00612 00613 *expected_validity = DBUS_INVALID_MISSING_REPLY_SERIAL; 00614 } 00615 else if (item_seq == 15) 00616 { 00617 message = simple_error (); 00618 00619 if (!dbus_message_set_error_name (message, NULL)) 00620 _dbus_assert_not_reached ("oom"); 00621 00622 generate_from_message (data, expected_validity, message); 00623 00624 *expected_validity = DBUS_INVALID_MISSING_ERROR_NAME; 00625 } 00626 else if (item_seq == 16) 00627 { 00628 char long_sig[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*4+10]; 00629 const char *v_STRING; 00630 int i; 00631 int n_begins; 00632 00633 message = simple_method_call (); 00634 if (!dbus_message_append_args (message, 00635 DBUS_TYPE_INT32, &v_INT32, 00636 DBUS_TYPE_INT32, &v_INT32, 00637 DBUS_TYPE_INT32, &v_INT32, 00638 DBUS_TYPE_INVALID)) 00639 _dbus_assert_not_reached ("oom"); 00640 00641 i = 0; 00642 while (i <= (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*3 + 3)) 00643 { 00644 long_sig[i] = DBUS_TYPE_ARRAY; 00645 ++i; 00646 long_sig[i] = DBUS_DICT_ENTRY_BEGIN_CHAR; 00647 ++i; 00648 long_sig[i] = DBUS_TYPE_INT32; 00649 ++i; 00650 } 00651 n_begins = i / 3; 00652 00653 long_sig[i] = DBUS_TYPE_INT32; 00654 ++i; 00655 00656 while (n_begins > 0) 00657 { 00658 long_sig[i] = DBUS_DICT_ENTRY_END_CHAR; 00659 ++i; 00660 n_begins -= 1; 00661 } 00662 long_sig[i] = DBUS_TYPE_INVALID; 00663 00664 v_STRING = long_sig; 00665 if (!_dbus_header_set_field_basic (&message->header, 00666 DBUS_HEADER_FIELD_SIGNATURE, 00667 DBUS_TYPE_SIGNATURE, 00668 &v_STRING)) 00669 _dbus_assert_not_reached ("oom"); 00670 00671 _dbus_header_get_field_raw (&message->header, 00672 DBUS_HEADER_FIELD_SIGNATURE, 00673 NULL, &pos); 00674 generate_from_message (data, expected_validity, message); 00675 00676 *expected_validity = DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION; 00677 } 00678 else if (item_seq == 17) 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 _dbus_header_get_field_raw (&message->header, 00689 DBUS_HEADER_FIELD_SIGNATURE, 00690 NULL, &pos); 00691 generate_from_message (data, expected_validity, message); 00692 00693 _dbus_string_set_byte (data, pos + 1, DBUS_TYPE_ARRAY); 00694 _dbus_string_set_byte (data, pos + 2, DBUS_DICT_ENTRY_BEGIN_CHAR); 00695 00696 *expected_validity = DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED; 00697 } 00698 else if (item_seq == 18) 00699 { 00700 message = simple_method_call (); 00701 if (!dbus_message_append_args (message, 00702 DBUS_TYPE_INT32, &v_INT32, 00703 DBUS_TYPE_INT32, &v_INT32, 00704 DBUS_TYPE_INT32, &v_INT32, 00705 DBUS_TYPE_INVALID)) 00706 _dbus_assert_not_reached ("oom"); 00707 00708 _dbus_header_get_field_raw (&message->header, 00709 DBUS_HEADER_FIELD_SIGNATURE, 00710 NULL, &pos); 00711 generate_from_message (data, expected_validity, message); 00712 00713 _dbus_string_set_byte (data, pos + 1, DBUS_DICT_ENTRY_END_CHAR); 00714 00715 *expected_validity = DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED; 00716 } 00717 else if (item_seq == 19) 00718 { 00719 message = simple_method_call (); 00720 if (!dbus_message_append_args (message, 00721 DBUS_TYPE_INT32, &v_INT32, 00722 DBUS_TYPE_INT32, &v_INT32, 00723 DBUS_TYPE_INT32, &v_INT32, 00724 DBUS_TYPE_INVALID)) 00725 _dbus_assert_not_reached ("oom"); 00726 00727 _dbus_header_get_field_raw (&message->header, 00728 DBUS_HEADER_FIELD_SIGNATURE, 00729 NULL, &pos); 00730 generate_from_message (data, expected_validity, message); 00731 00732 _dbus_string_set_byte (data, pos + 1, DBUS_TYPE_ARRAY); 00733 _dbus_string_set_byte (data, pos + 2, DBUS_DICT_ENTRY_BEGIN_CHAR); 00734 _dbus_string_set_byte (data, pos + 3, DBUS_DICT_ENTRY_END_CHAR); 00735 00736 *expected_validity = DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS; 00737 } 00738 else 00739 { 00740 return FALSE; 00741 } 00742 00743 if (message) 00744 dbus_message_unref (message); 00745 00746 iter_next (iter); 00747 return TRUE; 00748 } 00749 00750 static dbus_bool_t 00751 generate_wrong_length (DBusMessageDataIter *iter, 00752 DBusString *data, 00753 DBusValidity *expected_validity) 00754 { 00755 int lengths[] = { -42, -17, -16, -15, -9, -8, -7, -6, -5, -4, -3, -2, -1, 00756 1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 16, 30 }; 00757 int adjust; 00758 int len_seq; 00759 00760 restart: 00761 len_seq = iter_get_sequence (iter); 00762 if (len_seq == _DBUS_N_ELEMENTS (lengths)) 00763 return FALSE; 00764 00765 _dbus_assert (len_seq < _DBUS_N_ELEMENTS (lengths)); 00766 00767 iter_recurse (iter); 00768 if (!generate_many_bodies (iter, data, expected_validity)) 00769 { 00770 iter_set_sequence (iter, 0); /* reset to first body */ 00771 iter_unrecurse (iter); 00772 iter_next (iter); /* next length adjustment */ 00773 goto restart; 00774 } 00775 iter_unrecurse (iter); 00776 00777 adjust = lengths[len_seq]; 00778 00779 if (adjust < 0) 00780 { 00781 if ((_dbus_string_get_length (data) + adjust) < DBUS_MINIMUM_HEADER_SIZE) 00782 _dbus_string_set_length (data, DBUS_MINIMUM_HEADER_SIZE); 00783 else 00784 _dbus_string_shorten (data, - adjust); 00785 *expected_validity = DBUS_INVALID_FOR_UNKNOWN_REASON; 00786 } 00787 else 00788 { 00789 if (!_dbus_string_lengthen (data, adjust)) 00790 _dbus_assert_not_reached ("oom"); 00791 *expected_validity = DBUS_INVALID_TOO_MUCH_DATA; 00792 } 00793 00794 /* Fixup lengths */ 00795 { 00796 int old_body_len; 00797 int new_body_len; 00798 int byte_order; 00799 00800 _dbus_assert (_dbus_string_get_length (data) >= DBUS_MINIMUM_HEADER_SIZE); 00801 00802 byte_order = _dbus_string_get_byte (data, BYTE_ORDER_OFFSET); 00803 old_body_len = _dbus_marshal_read_uint32 (data, 00804 BODY_LENGTH_OFFSET, 00805 byte_order, 00806 NULL); 00807 _dbus_assert (old_body_len < _dbus_string_get_length (data)); 00808 new_body_len = old_body_len + adjust; 00809 if (new_body_len < 0) 00810 { 00811 new_body_len = 0; 00812 /* we just munged the header, and aren't sure how */ 00813 *expected_validity = DBUS_VALIDITY_UNKNOWN; 00814 } 00815 00816 _dbus_verbose ("changing body len from %u to %u by adjust %d\n", 00817 old_body_len, new_body_len, adjust); 00818 00819 _dbus_marshal_set_uint32 (data, BODY_LENGTH_OFFSET, 00820 new_body_len, 00821 byte_order); 00822 } 00823 00824 return TRUE; 00825 } 00826 00827 static dbus_bool_t 00828 generate_byte_changed (DBusMessageDataIter *iter, 00829 DBusString *data, 00830 DBusValidity *expected_validity) 00831 { 00832 int byte_seq; 00833 int v_BYTE; 00834 00835 /* This is a little convoluted to make the bodies the 00836 * outer loop and each byte of each body the inner 00837 * loop 00838 */ 00839 00840 restart: 00841 if (!generate_many_bodies (iter, data, expected_validity)) 00842 return FALSE; 00843 00844 iter_recurse (iter); 00845 byte_seq = iter_get_sequence (iter); 00846 iter_next (iter); 00847 iter_unrecurse (iter); 00848 00849 if (byte_seq == _dbus_string_get_length (data)) 00850 { 00851 _dbus_string_set_length (data, 0); 00852 /* reset byte count */ 00853 iter_recurse (iter); 00854 iter_set_sequence (iter, 0); 00855 iter_unrecurse (iter); 00856 goto restart; 00857 } 00858 else 00859 { 00860 /* Undo the "next" in generate_many_bodies */ 00861 iter_set_sequence (iter, iter_get_sequence (iter) - 1); 00862 } 00863 00864 _dbus_assert (byte_seq < _dbus_string_get_length (data)); 00865 v_BYTE = _dbus_string_get_byte (data, byte_seq); 00866 v_BYTE += byte_seq; /* arbitrary but deterministic change to the byte */ 00867 _dbus_string_set_byte (data, byte_seq, v_BYTE); 00868 *expected_validity = DBUS_VALIDITY_UNKNOWN; 00869 00870 return TRUE; 00871 } 00872 00873 static dbus_bool_t 00874 find_next_typecode (DBusMessageDataIter *iter, 00875 DBusString *data, 00876 DBusValidity *expected_validity) 00877 { 00878 int body_seq; 00879 int byte_seq; 00880 int base_depth; 00881 00882 base_depth = iter->depth; 00883 00884 restart: 00885 _dbus_assert (iter->depth == (base_depth + 0)); 00886 _dbus_string_set_length (data, 0); 00887 00888 body_seq = iter_get_sequence (iter); 00889 00890 if (!generate_many_bodies (iter, data, expected_validity)) 00891 return FALSE; 00892 /* Undo the "next" in generate_many_bodies */ 00893 iter_set_sequence (iter, body_seq); 00894 00895 iter_recurse (iter); 00896 while (TRUE) 00897 { 00898 _dbus_assert (iter->depth == (base_depth + 1)); 00899 00900 byte_seq = iter_get_sequence (iter); 00901 00902 _dbus_assert (byte_seq <= _dbus_string_get_length (data)); 00903 00904 if (byte_seq == _dbus_string_get_length (data)) 00905 { 00906 /* reset byte count */ 00907 iter_set_sequence (iter, 0); 00908 iter_unrecurse (iter); 00909 _dbus_assert (iter->depth == (base_depth + 0)); 00910 iter_next (iter); /* go to the next body */ 00911 goto restart; 00912 } 00913 00914 _dbus_assert (byte_seq < _dbus_string_get_length (data)); 00915 00916 if (_dbus_type_is_valid (_dbus_string_get_byte (data, byte_seq))) 00917 break; 00918 else 00919 iter_next (iter); 00920 } 00921 00922 _dbus_assert (byte_seq == iter_get_sequence (iter)); 00923 _dbus_assert (byte_seq < _dbus_string_get_length (data)); 00924 00925 iter_unrecurse (iter); 00926 00927 _dbus_assert (iter->depth == (base_depth + 0)); 00928 00929 return TRUE; 00930 } 00931 00932 static const int typecodes[] = { 00933 DBUS_TYPE_INVALID, 00934 DBUS_TYPE_BYTE, 00935 DBUS_TYPE_BOOLEAN, 00936 DBUS_TYPE_INT16, 00937 DBUS_TYPE_UINT16, 00938 DBUS_TYPE_INT32, 00939 DBUS_TYPE_UINT32, 00940 DBUS_TYPE_INT64, 00941 DBUS_TYPE_UINT64, 00942 DBUS_TYPE_DOUBLE, 00943 DBUS_TYPE_STRING, 00944 DBUS_TYPE_OBJECT_PATH, 00945 DBUS_TYPE_SIGNATURE, 00946 DBUS_TYPE_ARRAY, 00947 DBUS_TYPE_VARIANT, 00948 DBUS_STRUCT_BEGIN_CHAR, 00949 DBUS_STRUCT_END_CHAR, 00950 DBUS_DICT_ENTRY_BEGIN_CHAR, 00951 DBUS_DICT_ENTRY_END_CHAR, 00952 DBUS_TYPE_UNIX_FD, 00953 255 /* random invalid typecode */ 00954 }; 00955 00956 static dbus_bool_t 00957 generate_typecode_changed (DBusMessageDataIter *iter, 00958 DBusString *data, 00959 DBusValidity *expected_validity) 00960 { 00961 int byte_seq; 00962 int typecode_seq; 00963 int base_depth; 00964 00965 base_depth = iter->depth; 00966 00967 restart: 00968 _dbus_assert (iter->depth == (base_depth + 0)); 00969 _dbus_string_set_length (data, 0); 00970 00971 if (!find_next_typecode (iter, data, expected_validity)) 00972 return FALSE; 00973 00974 iter_recurse (iter); 00975 byte_seq = iter_get_sequence (iter); 00976 00977 _dbus_assert (byte_seq < _dbus_string_get_length (data)); 00978 00979 iter_recurse (iter); 00980 typecode_seq = iter_get_sequence (iter); 00981 iter_next (iter); 00982 00983 _dbus_assert (typecode_seq <= _DBUS_N_ELEMENTS (typecodes)); 00984 00985 if (typecode_seq == _DBUS_N_ELEMENTS (typecodes)) 00986 { 00987 _dbus_assert (iter->depth == (base_depth + 2)); 00988 iter_set_sequence (iter, 0); /* reset typecode sequence */ 00989 iter_unrecurse (iter); 00990 _dbus_assert (iter->depth == (base_depth + 1)); 00991 iter_next (iter); /* go to the next byte_seq */ 00992 iter_unrecurse (iter); 00993 _dbus_assert (iter->depth == (base_depth + 0)); 00994 goto restart; 00995 } 00996 00997 _dbus_assert (iter->depth == (base_depth + 2)); 00998 iter_unrecurse (iter); 00999 _dbus_assert (iter->depth == (base_depth + 1)); 01000 iter_unrecurse (iter); 01001 _dbus_assert (iter->depth == (base_depth + 0)); 01002 01003 #if 0 01004 printf ("Changing byte %d in message %d to %c\n", 01005 byte_seq, iter_get_sequence (iter), typecodes[typecode_seq]); 01006 #endif 01007 01008 _dbus_string_set_byte (data, byte_seq, typecodes[typecode_seq]); 01009 *expected_validity = DBUS_VALIDITY_UNKNOWN; 01010 return TRUE; 01011 } 01012 01013 typedef struct 01014 { 01015 ChangeType type; 01016 dbus_uint32_t value; /* cast to signed for adjusts */ 01017 } UIntChange; 01018 01019 static const UIntChange uint32_changes[] = { 01020 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) -1 }, 01021 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) -2 }, 01022 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) -3 }, 01023 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) 1 }, 01024 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) 2 }, 01025 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) 3 }, 01026 { CHANGE_TYPE_ABSOLUTE, _DBUS_UINT32_MAX }, 01027 { CHANGE_TYPE_ABSOLUTE, 0 }, 01028 { CHANGE_TYPE_ABSOLUTE, 1 }, 01029 { CHANGE_TYPE_ABSOLUTE, _DBUS_UINT32_MAX - 1 }, 01030 { CHANGE_TYPE_ABSOLUTE, _DBUS_UINT32_MAX - 5 } 01031 }; 01032 01033 static dbus_bool_t 01034 generate_uint32_changed (DBusMessageDataIter *iter, 01035 DBusString *data, 01036 DBusValidity *expected_validity) 01037 { 01038 int body_seq; 01039 int byte_seq; 01040 int change_seq; 01041 dbus_uint32_t v_UINT32; 01042 int byte_order; 01043 const UIntChange *change; 01044 int base_depth; 01045 01046 /* Outer loop is each body, next loop is each change, 01047 * inner loop is each change location 01048 */ 01049 01050 base_depth = iter->depth; 01051 01052 next_body: 01053 _dbus_assert (iter->depth == (base_depth + 0)); 01054 _dbus_string_set_length (data, 0); 01055 body_seq = iter_get_sequence (iter); 01056 01057 if (!generate_many_bodies (iter, data, expected_validity)) 01058 return FALSE; 01059 01060 _dbus_assert (iter->depth == (base_depth + 0)); 01061 01062 iter_set_sequence (iter, body_seq); /* undo the "next" from generate_many_bodies */ 01063 iter_recurse (iter); 01064 next_change: 01065 _dbus_assert (iter->depth == (base_depth + 1)); 01066 change_seq = iter_get_sequence (iter); 01067 01068 if (change_seq == _DBUS_N_ELEMENTS (uint32_changes)) 01069 { 01070 /* Reset change count */ 01071 iter_set_sequence (iter, 0); 01072 iter_unrecurse (iter); 01073 iter_next (iter); 01074 goto next_body; 01075 } 01076 01077 _dbus_assert (iter->depth == (base_depth + 1)); 01078 01079 iter_recurse (iter); 01080 _dbus_assert (iter->depth == (base_depth + 2)); 01081 byte_seq = iter_get_sequence (iter); 01082 /* skip 4 bytes at a time */ 01083 iter_next (iter); 01084 iter_next (iter); 01085 iter_next (iter); 01086 iter_next (iter); 01087 iter_unrecurse (iter); 01088 01089 _dbus_assert (_DBUS_ALIGN_VALUE (byte_seq, 4) == (unsigned) byte_seq); 01090 if (byte_seq >= (_dbus_string_get_length (data) - 4)) 01091 { 01092 /* reset byte count */ 01093 _dbus_assert (iter->depth == (base_depth + 1)); 01094 iter_recurse (iter); 01095 _dbus_assert (iter->depth == (base_depth + 2)); 01096 iter_set_sequence (iter, 0); 01097 iter_unrecurse (iter); 01098 _dbus_assert (iter->depth == (base_depth + 1)); 01099 iter_next (iter); 01100 goto next_change; 01101 } 01102 01103 _dbus_assert (byte_seq <= (_dbus_string_get_length (data) - 4)); 01104 01105 byte_order = _dbus_string_get_byte (data, BYTE_ORDER_OFFSET); 01106 01107 v_UINT32 = _dbus_marshal_read_uint32 (data, byte_seq, byte_order, NULL); 01108 01109 change = &uint32_changes[change_seq]; 01110 01111 if (change->type == CHANGE_TYPE_ADJUST) 01112 { 01113 v_UINT32 += (int) change->value; 01114 } 01115 else 01116 { 01117 v_UINT32 = change->value; 01118 } 01119 01120 #if 0 01121 printf ("body %d change %d pos %d ", 01122 body_seq, change_seq, byte_seq); 01123 01124 if (change->type == CHANGE_TYPE_ADJUST) 01125 printf ("adjust by %d", (int) change->value); 01126 else 01127 printf ("set to %u", change->value); 01128 01129 printf (" \t%u -> %u\n", 01130 _dbus_marshal_read_uint32 (data, byte_seq, byte_order, NULL), 01131 v_UINT32); 01132 #endif 01133 01134 _dbus_marshal_set_uint32 (data, byte_seq, v_UINT32, byte_order); 01135 *expected_validity = DBUS_VALIDITY_UNKNOWN; 01136 01137 _dbus_assert (iter->depth == (base_depth + 1)); 01138 iter_unrecurse (iter); 01139 _dbus_assert (iter->depth == (base_depth + 0)); 01140 01141 return TRUE; 01142 } 01143 01144 typedef struct 01145 { 01146 const char *name; 01147 DBusMessageGeneratorFunc func; 01148 } DBusMessageGenerator; 01149 01150 static const DBusMessageGenerator generators[] = { 01151 { "trivial example of each message type", generate_trivial }, 01152 { "assorted arguments", generate_many_bodies }, 01153 { "assorted special cases", generate_special }, 01154 { "each uint32 modified", generate_uint32_changed }, 01155 { "wrong body lengths", generate_wrong_length }, 01156 { "each byte modified", generate_byte_changed }, 01157 #if 0 01158 /* This is really expensive and doesn't add too much coverage */ 01159 { "change each typecode", generate_typecode_changed } 01160 #endif 01161 }; 01162 01163 void 01164 _dbus_message_data_free (DBusMessageData *data) 01165 { 01166 _dbus_string_free (&data->data); 01167 } 01168 01169 void 01170 _dbus_message_data_iter_init (DBusMessageDataIter *iter) 01171 { 01172 int i; 01173 01174 iter->depth = 0; 01175 i = 0; 01176 while (i < _DBUS_MESSAGE_DATA_MAX_NESTING) 01177 { 01178 iter->sequence_nos[i] = 0; 01179 ++i; 01180 } 01181 iter->count = 0; 01182 } 01183 01184 dbus_bool_t 01185 _dbus_message_data_iter_get_and_next (DBusMessageDataIter *iter, 01186 DBusMessageData *data) 01187 { 01188 DBusMessageGeneratorFunc func; 01189 int generator; 01190 01191 restart: 01192 generator = iter_get_sequence (iter); 01193 01194 if (generator == _DBUS_N_ELEMENTS (generators)) 01195 return FALSE; 01196 01197 iter_recurse (iter); 01198 01199 if (iter_first_in_series (iter)) 01200 { 01201 printf (" testing message loading: %s ", generators[generator].name); 01202 fflush (stdout); 01203 } 01204 01205 func = generators[generator].func; 01206 01207 if (!_dbus_string_init (&data->data)) 01208 _dbus_assert_not_reached ("oom"); 01209 01210 if ((*func)(iter, &data->data, &data->expected_validity)) 01211 ; 01212 else 01213 { 01214 iter_set_sequence (iter, 0); 01215 iter_unrecurse (iter); 01216 iter_next (iter); /* next generator */ 01217 _dbus_string_free (&data->data); 01218 printf ("%d test loads cumulative\n", iter->count); 01219 goto restart; 01220 } 01221 iter_unrecurse (iter); 01222 01223 iter->count += 1; 01224 return TRUE; 01225 } 01226 01227 #endif /* !DOXYGEN_SHOULD_SKIP_THIS */ 01228 01229 #endif /* DBUS_BUILD_TESTS */