dbus-marshal-validate-util.c

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

Generated on Tue Jul 7 15:13:59 2009 for D-BUS by  doxygen 1.4.6