D-Bus  1.10.12
dbus-marshal-validate-util.c
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-marshal-validate-util.c Would be in dbus-marshal-validate.c, but only used by tests/bus
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 
00024 #include <config.h>
00025 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
00026 
00027 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00028 
00029 #include "dbus-internals.h"
00030 #include "dbus-marshal-validate.h"
00031 #include "dbus-marshal-recursive.h"
00032 
00033 #include "dbus-test.h"
00034 #include <stdio.h>
00035 
00036 typedef struct
00037 {
00038   const char *data;
00039   DBusValidity expected;
00040 } ValidityTest;
00041 
00042 static void
00043 run_validity_tests (const ValidityTest *tests,
00044                     int                 n_tests,
00045                     DBusValidity (* func) (const DBusString*,int,int))
00046 {
00047   int i;
00048 
00049   for (i = 0; i < n_tests; i++)
00050     {
00051       DBusString str;
00052       DBusValidity v;
00053 
00054       _dbus_string_init_const (&str, tests[i].data);
00055 
00056       v = (*func) (&str, 0, _dbus_string_get_length (&str));
00057 
00058       if (v != tests[i].expected)
00059         {
00060           _dbus_warn ("Improper validation result %d for '%s'\n",
00061                       v, tests[i].data);
00062           _dbus_assert_not_reached ("test failed");
00063         }
00064     }
00065 }
00066 
00067 static const ValidityTest signature_tests[] = {
00068   { "", DBUS_VALID },
00069   { "i", DBUS_VALID },
00070   { "ai", DBUS_VALID },
00071   { "(i)", DBUS_VALID },
00072   { "w", DBUS_INVALID_UNKNOWN_TYPECODE },
00073   { "a", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
00074   { "aaaaaa", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
00075   { "ii(ii)a", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
00076   { "ia", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
00077   /* DBUS_INVALID_SIGNATURE_TOO_LONG, */ /* too hard to test this way */
00078   { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
00079     DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION },
00080   { "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((ii))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))",
00081     DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION },
00082   { ")", DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED },
00083   { "i)", DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED },
00084   { "a)", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
00085   { "(", DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED },
00086   { "(i", DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED },
00087   { "(iiiii", DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED },
00088   { "(ai", DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED },
00089   { "()", DBUS_INVALID_STRUCT_HAS_NO_FIELDS },
00090   { "(())", DBUS_INVALID_STRUCT_HAS_NO_FIELDS },
00091   { "a()", DBUS_INVALID_STRUCT_HAS_NO_FIELDS },
00092   { "i()", DBUS_INVALID_STRUCT_HAS_NO_FIELDS },
00093   { "()i", DBUS_INVALID_STRUCT_HAS_NO_FIELDS },
00094   { "(a)", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
00095   { "a{ia}", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
00096   { "a{}", DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS },
00097   { "a{aii}", DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE },
00098   /* { "a{i}", DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD }, */
00099   /* { "{is}", DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY }, */
00100   /* { "a{isi}", DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS }, */
00101 };
00102 
00103 dbus_bool_t
00104 _dbus_marshal_validate_test (void)
00105 {
00106   DBusString str;
00107   int i;
00108 
00109   const char *valid_paths[] = {
00110     "/",
00111     "/foo/bar",
00112     "/foo",
00113     "/foo/bar/baz"
00114   };
00115   const char *invalid_paths[] = {
00116     "bar",
00117     "bar/baz",
00118     "/foo/bar/",
00119     "/foo/",
00120     "foo/",
00121     "boo//blah",
00122     "//",
00123     "///",
00124     "foo///blah/",
00125     "Hello World",
00126     "",
00127     "   ",
00128     "foo bar"
00129   };
00130 
00131   const char *valid_interfaces[] = {
00132     "org.freedesktop.Foo",
00133     "Bar.Baz",
00134     "Blah.Blah.Blah.Blah.Blah",
00135     "a.b",
00136     "a.b.c.d.e.f.g",
00137     "a0.b1.c2.d3.e4.f5.g6",
00138     "abc123.foo27"
00139   };
00140   const char *invalid_interfaces[] = {
00141     ".",
00142     "",
00143     "..",
00144     ".Foo.Bar",
00145     "..Foo.Bar",
00146     "Foo.Bar.",
00147     "Foo.Bar..",
00148     "Foo",
00149     "9foo.bar.baz",
00150     "foo.bar..baz",
00151     "foo.bar...baz",
00152     "foo.bar.b..blah",
00153     ":",
00154     ":0-1",
00155     "10",
00156     ":11.34324",
00157     "0.0.0",
00158     "0..0",
00159     "foo.Bar.%",
00160     "foo.Bar!!",
00161     "!Foo.bar.bz",
00162     "foo.$.blah",
00163     "",
00164     "   ",
00165     "foo bar"
00166   };
00167 
00168   const char *valid_unique_names[] = {
00169     ":0",
00170     ":a",
00171     ":",
00172     ":.a",
00173     ":.1",
00174     ":0.1",
00175     ":000.2222",
00176     ":.blah",
00177     ":abce.freedesktop.blah"
00178   };
00179   const char *invalid_unique_names[] = {
00180     //":-",
00181     ":!",
00182     //":0-10",
00183     ":blah.",
00184     ":blah.",
00185     ":blah..org",
00186     ":blah.org..",
00187     ":..blah.org",
00188     "",
00189     "   ",
00190     "foo bar"
00191   };
00192 
00193   const char *valid_members[] = {
00194     "Hello",
00195     "Bar",
00196     "foobar",
00197     "_foobar",
00198     "foo89"
00199   };
00200 
00201   const char *invalid_members[] = {
00202     "9Hello",
00203     "10",
00204     "1",
00205     "foo-bar",
00206     "blah.org",
00207     ".blah",
00208     "blah.",
00209     "Hello.",
00210     "!foo",
00211     "",
00212     "   ",
00213     "foo bar"
00214   };
00215 
00216   const char *valid_signatures[] = {
00217     "",
00218     "sss",
00219     "i",
00220     "b"
00221   };
00222 
00223   const char *invalid_signatures[] = {
00224     " ",
00225     "not a valid signature",
00226     "123",
00227     ".",
00228     "(",
00229     "a{(ii)i}" /* https://bugs.freedesktop.org/show_bug.cgi?id=17803 */
00230   };
00231 
00232   /* Signature with reason */
00233 
00234   run_validity_tests (signature_tests, _DBUS_N_ELEMENTS (signature_tests),
00235                       _dbus_validate_signature_with_reason);
00236 
00237   /* Path validation */
00238   i = 0;
00239   while (i < (int) _DBUS_N_ELEMENTS (valid_paths))
00240     {
00241       _dbus_string_init_const (&str, valid_paths[i]);
00242 
00243       if (!_dbus_validate_path (&str, 0,
00244                                 _dbus_string_get_length (&str)))
00245         {
00246           _dbus_warn ("Path \"%s\" should have been valid\n", valid_paths[i]);
00247           _dbus_assert_not_reached ("invalid path");
00248         }
00249 
00250       ++i;
00251     }
00252 
00253   i = 0;
00254   while (i < (int) _DBUS_N_ELEMENTS (invalid_paths))
00255     {
00256       _dbus_string_init_const (&str, invalid_paths[i]);
00257 
00258       if (_dbus_validate_path (&str, 0,
00259                                _dbus_string_get_length (&str)))
00260         {
00261           _dbus_warn ("Path \"%s\" should have been invalid\n", invalid_paths[i]);
00262           _dbus_assert_not_reached ("valid path");
00263         }
00264 
00265       ++i;
00266     }
00267 
00268   /* Interface validation */
00269   i = 0;
00270   while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
00271     {
00272       _dbus_string_init_const (&str, valid_interfaces[i]);
00273 
00274       if (!_dbus_validate_interface (&str, 0,
00275                                      _dbus_string_get_length (&str)))
00276         {
00277           _dbus_warn ("Interface \"%s\" should have been valid\n", valid_interfaces[i]);
00278           _dbus_assert_not_reached ("invalid interface");
00279         }
00280 
00281       ++i;
00282     }
00283 
00284   i = 0;
00285   while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
00286     {
00287       _dbus_string_init_const (&str, invalid_interfaces[i]);
00288 
00289       if (_dbus_validate_interface (&str, 0,
00290                                     _dbus_string_get_length (&str)))
00291         {
00292           _dbus_warn ("Interface \"%s\" should have been invalid\n", invalid_interfaces[i]);
00293           _dbus_assert_not_reached ("valid interface");
00294         }
00295 
00296       ++i;
00297     }
00298 
00299   /* Bus name validation (check that valid interfaces are valid bus names,
00300    * and invalid interfaces are invalid services except if they start with ':')
00301    */
00302   i = 0;
00303   while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
00304     {
00305       _dbus_string_init_const (&str, valid_interfaces[i]);
00306 
00307       if (!_dbus_validate_bus_name (&str, 0,
00308                                    _dbus_string_get_length (&str)))
00309         {
00310           _dbus_warn ("Bus name \"%s\" should have been valid\n", valid_interfaces[i]);
00311           _dbus_assert_not_reached ("invalid bus name");
00312         }
00313 
00314       ++i;
00315     }
00316 
00317   i = 0;
00318   while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
00319     {
00320       if (invalid_interfaces[i][0] != ':')
00321         {
00322           _dbus_string_init_const (&str, invalid_interfaces[i]);
00323 
00324           if (_dbus_validate_bus_name (&str, 0,
00325                                        _dbus_string_get_length (&str)))
00326             {
00327               _dbus_warn ("Bus name \"%s\" should have been invalid\n", invalid_interfaces[i]);
00328               _dbus_assert_not_reached ("valid bus name");
00329             }
00330         }
00331 
00332       ++i;
00333     }
00334 
00335   /* unique name validation */
00336   i = 0;
00337   while (i < (int) _DBUS_N_ELEMENTS (valid_unique_names))
00338     {
00339       _dbus_string_init_const (&str, valid_unique_names[i]);
00340 
00341       if (!_dbus_validate_bus_name (&str, 0,
00342                                     _dbus_string_get_length (&str)))
00343         {
00344           _dbus_warn ("Bus name \"%s\" should have been valid\n", valid_unique_names[i]);
00345           _dbus_assert_not_reached ("invalid unique name");
00346         }
00347 
00348       ++i;
00349     }
00350 
00351   i = 0;
00352   while (i < (int) _DBUS_N_ELEMENTS (invalid_unique_names))
00353     {
00354       _dbus_string_init_const (&str, invalid_unique_names[i]);
00355 
00356       if (_dbus_validate_bus_name (&str, 0,
00357                                    _dbus_string_get_length (&str)))
00358         {
00359           _dbus_warn ("Bus name \"%s\" should have been invalid\n", invalid_unique_names[i]);
00360           _dbus_assert_not_reached ("valid unique name");
00361         }
00362 
00363       ++i;
00364     }
00365 
00366 
00367   /* Error name validation (currently identical to interfaces)
00368    */
00369   i = 0;
00370   while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
00371     {
00372       _dbus_string_init_const (&str, valid_interfaces[i]);
00373 
00374       if (!_dbus_validate_error_name (&str, 0,
00375                                       _dbus_string_get_length (&str)))
00376         {
00377           _dbus_warn ("Error name \"%s\" should have been valid\n", valid_interfaces[i]);
00378           _dbus_assert_not_reached ("invalid error name");
00379         }
00380 
00381       ++i;
00382     }
00383 
00384   i = 0;
00385   while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
00386     {
00387       if (invalid_interfaces[i][0] != ':')
00388         {
00389           _dbus_string_init_const (&str, invalid_interfaces[i]);
00390 
00391           if (_dbus_validate_error_name (&str, 0,
00392                                          _dbus_string_get_length (&str)))
00393             {
00394               _dbus_warn ("Error name \"%s\" should have been invalid\n", invalid_interfaces[i]);
00395               _dbus_assert_not_reached ("valid error name");
00396             }
00397         }
00398 
00399       ++i;
00400     }
00401 
00402   /* Member validation */
00403   i = 0;
00404   while (i < (int) _DBUS_N_ELEMENTS (valid_members))
00405     {
00406       _dbus_string_init_const (&str, valid_members[i]);
00407 
00408       if (!_dbus_validate_member (&str, 0,
00409                                   _dbus_string_get_length (&str)))
00410         {
00411           _dbus_warn ("Member \"%s\" should have been valid\n", valid_members[i]);
00412           _dbus_assert_not_reached ("invalid member");
00413         }
00414 
00415       ++i;
00416     }
00417 
00418   i = 0;
00419   while (i < (int) _DBUS_N_ELEMENTS (invalid_members))
00420     {
00421       _dbus_string_init_const (&str, invalid_members[i]);
00422 
00423       if (_dbus_validate_member (&str, 0,
00424                                  _dbus_string_get_length (&str)))
00425         {
00426           _dbus_warn ("Member \"%s\" should have been invalid\n", invalid_members[i]);
00427           _dbus_assert_not_reached ("valid member");
00428         }
00429 
00430       ++i;
00431     }
00432 
00433   /* Signature validation */
00434   i = 0;
00435   while (i < (int) _DBUS_N_ELEMENTS (valid_signatures))
00436     {
00437       _dbus_string_init_const (&str, valid_signatures[i]);
00438 
00439       if (!_dbus_validate_signature (&str, 0,
00440                                      _dbus_string_get_length (&str)))
00441         {
00442           _dbus_warn ("Signature \"%s\" should have been valid\n", valid_signatures[i]);
00443           _dbus_assert_not_reached ("invalid signature");
00444         }
00445 
00446       ++i;
00447     }
00448 
00449   i = 0;
00450   while (i < (int) _DBUS_N_ELEMENTS (invalid_signatures))
00451     {
00452       _dbus_string_init_const (&str, invalid_signatures[i]);
00453 
00454       if (_dbus_validate_signature (&str, 0,
00455                                     _dbus_string_get_length (&str)))
00456         {
00457           _dbus_warn ("Signature \"%s\" should have been invalid\n", invalid_signatures[i]);
00458           _dbus_assert_not_reached ("valid signature");
00459         }
00460 
00461       ++i;
00462     }
00463 
00464   /* Validate claimed length longer than real length */
00465   _dbus_string_init_const (&str, "abc.efg");
00466   if (_dbus_validate_bus_name (&str, 0, 8))
00467     _dbus_assert_not_reached ("validated too-long string");
00468   if (_dbus_validate_interface (&str, 0, 8))
00469     _dbus_assert_not_reached ("validated too-long string");
00470   if (_dbus_validate_error_name (&str, 0, 8))
00471     _dbus_assert_not_reached ("validated too-long string");
00472 
00473   _dbus_string_init_const (&str, "abc");
00474   if (_dbus_validate_member (&str, 0, 4))
00475     _dbus_assert_not_reached ("validated too-long string");
00476 
00477   _dbus_string_init_const (&str, "sss");
00478   if (_dbus_validate_signature (&str, 0, 4))
00479     _dbus_assert_not_reached ("validated too-long signature");
00480 
00481   /* Validate string exceeding max name length */
00482   if (!_dbus_string_init (&str))
00483     _dbus_assert_not_reached ("no memory");
00484 
00485   while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
00486     if (!_dbus_string_append (&str, "abc.def"))
00487       _dbus_assert_not_reached ("no memory");
00488 
00489   if (_dbus_validate_bus_name (&str, 0, _dbus_string_get_length (&str)))
00490     _dbus_assert_not_reached ("validated overmax string");
00491   if (_dbus_validate_interface (&str, 0, _dbus_string_get_length (&str)))
00492     _dbus_assert_not_reached ("validated overmax string");
00493   if (_dbus_validate_error_name (&str, 0, _dbus_string_get_length (&str)))
00494     _dbus_assert_not_reached ("validated overmax string");
00495 
00496   /* overlong member */
00497   _dbus_string_set_length (&str, 0);
00498   while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
00499     if (!_dbus_string_append (&str, "abc"))
00500       _dbus_assert_not_reached ("no memory");
00501 
00502   if (_dbus_validate_member (&str, 0, _dbus_string_get_length (&str)))
00503     _dbus_assert_not_reached ("validated overmax string");
00504 
00505   /* overlong unique name */
00506   _dbus_string_set_length (&str, 0);
00507   _dbus_string_append (&str, ":");
00508   while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
00509     if (!_dbus_string_append (&str, "abc"))
00510       _dbus_assert_not_reached ("no memory");
00511 
00512   if (_dbus_validate_bus_name (&str, 0, _dbus_string_get_length (&str)))
00513     _dbus_assert_not_reached ("validated overmax string");
00514 
00515   _dbus_string_free (&str);
00516 
00517   /* Body validation; test basic validation of valid bodies for both endian */
00518   
00519   {
00520     int sequence;
00521     DBusString signature;
00522     DBusString body;
00523 
00524     if (!_dbus_string_init (&signature) || !_dbus_string_init (&body))
00525       _dbus_assert_not_reached ("oom");
00526 
00527     sequence = 0;
00528     while (dbus_internal_do_not_use_generate_bodies (sequence,
00529                                                      DBUS_LITTLE_ENDIAN,
00530                                                      &signature, &body))
00531       {
00532         DBusValidity validity;
00533 
00534         validity = _dbus_validate_body_with_reason (&signature, 0,
00535                                                     DBUS_LITTLE_ENDIAN,
00536                                                     NULL, &body, 0,
00537                                                     _dbus_string_get_length (&body));
00538         if (validity != DBUS_VALID)
00539           {
00540             _dbus_warn ("invalid code %d expected valid on sequence %d little endian\n",
00541                         validity, sequence);
00542             _dbus_verbose_bytes_of_string (&signature, 0, _dbus_string_get_length (&signature));
00543             _dbus_verbose_bytes_of_string (&body, 0, _dbus_string_get_length (&body));
00544             _dbus_assert_not_reached ("test failed");
00545           }
00546 
00547         _dbus_string_set_length (&signature, 0);
00548         _dbus_string_set_length (&body, 0);
00549         ++sequence;
00550       }
00551                                                      
00552     sequence = 0;
00553     while (dbus_internal_do_not_use_generate_bodies (sequence,
00554                                                      DBUS_BIG_ENDIAN,
00555                                                      &signature, &body))
00556       {
00557         DBusValidity validity;
00558 
00559         validity = _dbus_validate_body_with_reason (&signature, 0,
00560                                                     DBUS_BIG_ENDIAN,
00561                                                     NULL, &body, 0,
00562                                                     _dbus_string_get_length (&body));
00563         if (validity != DBUS_VALID)
00564           {
00565             _dbus_warn ("invalid code %d expected valid on sequence %d big endian\n",
00566                         validity, sequence);
00567             _dbus_verbose_bytes_of_string (&signature, 0, _dbus_string_get_length (&signature));
00568             _dbus_verbose_bytes_of_string (&body, 0, _dbus_string_get_length (&body));
00569             _dbus_assert_not_reached ("test failed");
00570           }
00571 
00572         _dbus_string_set_length (&signature, 0);
00573         _dbus_string_set_length (&body, 0);
00574         ++sequence;
00575       }
00576 
00577     _dbus_string_free (&signature);
00578     _dbus_string_free (&body);
00579   }
00580   
00581   return TRUE;
00582 }
00583 
00584 #endif /* !DOXYGEN_SHOULD_SKIP_THIS */
00585 
00586 #endif /* DBUS_ENABLE_EMBEDDED_TESTS */