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

Generated on Tue Feb 24 16:40:39 2009 for D-Bus by  doxygen 1.5.1