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