Home | History | Annotate | Download | only in dbus
      1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
      2 /* dbus-marshal-validate-util.c Would be in dbus-marshal-validate.c, but only used by tests/bus
      3  *
      4  * Copyright (C) 2005 Red Hat, Inc.
      5  *
      6  * Licensed under the Academic Free License version 2.1
      7  *
      8  * This program is free software; you can redistribute it and/or modify
      9  * it under the terms of the GNU General Public License as published by
     10  * the Free Software Foundation; either version 2 of the License, or
     11  * (at your option) any later version.
     12  *
     13  * This program is distributed in the hope that it will be useful,
     14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  * GNU General Public License for more details.
     17  *
     18  * You should have received a copy of the GNU General Public License
     19  * along with this program; if not, write to the Free Software
     20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
     21  *
     22  */
     23 
     24 #include <config.h>
     25 #ifdef DBUS_BUILD_TESTS
     26 
     27 #ifndef DOXYGEN_SHOULD_SKIP_THIS
     28 
     29 #include "dbus-internals.h"
     30 #include "dbus-marshal-validate.h"
     31 #include "dbus-marshal-recursive.h"
     32 
     33 #include "dbus-test.h"
     34 #include <stdio.h>
     35 
     36 typedef struct
     37 {
     38   const char *data;
     39   DBusValidity expected;
     40 } ValidityTest;
     41 
     42 static void
     43 run_validity_tests (const ValidityTest *tests,
     44                     int                 n_tests,
     45                     DBusValidity (* func) (const DBusString*,int,int))
     46 {
     47   int i;
     48 
     49   for (i = 0; i < n_tests; i++)
     50     {
     51       DBusString str;
     52       DBusValidity v;
     53 
     54       _dbus_string_init_const (&str, tests[i].data);
     55 
     56       v = (*func) (&str, 0, _dbus_string_get_length (&str));
     57 
     58       if (v != tests[i].expected)
     59         {
     60           _dbus_warn ("Improper validation result %d for '%s'\n",
     61                       v, tests[i].data);
     62           _dbus_assert_not_reached ("test failed");
     63         }
     64 
     65       ++i;
     66     }
     67 }
     68 
     69 static const ValidityTest signature_tests[] = {
     70   { "", DBUS_VALID },
     71   { "i", DBUS_VALID },
     72   { "ai", DBUS_VALID },
     73   { "(i)", DBUS_VALID },
     74   { "w", DBUS_INVALID_UNKNOWN_TYPECODE },
     75   { "a", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
     76   { "aaaaaa", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
     77   { "ii(ii)a", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
     78   { "ia", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
     79   /* DBUS_INVALID_SIGNATURE_TOO_LONG, */ /* too hard to test this way */
     80   { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
     81     DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION },
     82   { "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((ii))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))",
     83     DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION },
     84   { ")", DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED },
     85   { "i)", DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED },
     86   { "a)", DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED },
     87   { "(", DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED },
     88   { "(i", DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED },
     89   { "(iiiii", DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED },
     90   { "(ai", DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED },
     91   { "()", DBUS_INVALID_STRUCT_HAS_NO_FIELDS },
     92   { "(())", DBUS_INVALID_STRUCT_HAS_NO_FIELDS },
     93   { "a()", DBUS_INVALID_STRUCT_HAS_NO_FIELDS },
     94   { "i()", DBUS_INVALID_STRUCT_HAS_NO_FIELDS },
     95   { "()i", DBUS_INVALID_STRUCT_HAS_NO_FIELDS },
     96   { "(a)", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
     97   { "a{ia}", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
     98   { "a{}", DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS },
     99   { "a{aii}", DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE },
    100   /* { "a{i}", DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD }, */
    101   /* { "{is}", DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY }, */
    102   /* { "a{isi}", DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS }, */
    103 };
    104 
    105 dbus_bool_t
    106 _dbus_marshal_validate_test (void)
    107 {
    108   DBusString str;
    109   int i;
    110 
    111   const char *valid_paths[] = {
    112     "/",
    113     "/foo/bar",
    114     "/foo",
    115     "/foo/bar/baz"
    116   };
    117   const char *invalid_paths[] = {
    118     "bar",
    119     "bar/baz",
    120     "/foo/bar/",
    121     "/foo/"
    122     "foo/",
    123     "boo//blah",
    124     "//",
    125     "///",
    126     "foo///blah/",
    127     "Hello World",
    128     "",
    129     "   ",
    130     "foo bar"
    131   };
    132 
    133   const char *valid_interfaces[] = {
    134     "org.freedesktop.Foo",
    135     "Bar.Baz",
    136     "Blah.Blah.Blah.Blah.Blah",
    137     "a.b",
    138     "a.b.c.d.e.f.g",
    139     "a0.b1.c2.d3.e4.f5.g6",
    140     "abc123.foo27"
    141   };
    142   const char *invalid_interfaces[] = {
    143     ".",
    144     "",
    145     "..",
    146     ".Foo.Bar",
    147     "..Foo.Bar",
    148     "Foo.Bar.",
    149     "Foo.Bar..",
    150     "Foo",
    151     "9foo.bar.baz",
    152     "foo.bar..baz",
    153     "foo.bar...baz",
    154     "foo.bar.b..blah",
    155     ":",
    156     ":0-1",
    157     "10",
    158     ":11.34324",
    159     "0.0.0",
    160     "0..0",
    161     "foo.Bar.%",
    162     "foo.Bar!!",
    163     "!Foo.bar.bz",
    164     "foo.$.blah",
    165     "",
    166     "   ",
    167     "foo bar"
    168   };
    169 
    170   const char *valid_unique_names[] = {
    171     ":0",
    172     ":a",
    173     ":",
    174     ":.a",
    175     ":.1",
    176     ":0.1",
    177     ":000.2222",
    178     ":.blah",
    179     ":abce.freedesktop.blah"
    180   };
    181   const char *invalid_unique_names[] = {
    182     //":-",
    183     ":!",
    184     //":0-10",
    185     ":blah.",
    186     ":blah.",
    187     ":blah..org",
    188     ":blah.org..",
    189     ":..blah.org",
    190     "",
    191     "   ",
    192     "foo bar"
    193   };
    194 
    195   const char *valid_members[] = {
    196     "Hello",
    197     "Bar",
    198     "foobar",
    199     "_foobar",
    200     "foo89"
    201   };
    202 
    203   const char *invalid_members[] = {
    204     "9Hello",
    205     "10",
    206     "1",
    207     "foo-bar",
    208     "blah.org",
    209     ".blah",
    210     "blah.",
    211     "Hello.",
    212     "!foo",
    213     "",
    214     "   ",
    215     "foo bar"
    216   };
    217 
    218   const char *valid_signatures[] = {
    219     "",
    220     "sss",
    221     "i",
    222     "b"
    223   };
    224 
    225   const char *invalid_signatures[] = {
    226     " ",
    227     "not a valid signature",
    228     "123",
    229     ".",
    230     "(",
    231     "a{(ii)i}" /* https://bugs.freedesktop.org/show_bug.cgi?id=17803 */
    232   };
    233 
    234   /* Signature with reason */
    235 
    236   run_validity_tests (signature_tests, _DBUS_N_ELEMENTS (signature_tests),
    237                       _dbus_validate_signature_with_reason);
    238 
    239   /* Path validation */
    240   i = 0;
    241   while (i < (int) _DBUS_N_ELEMENTS (valid_paths))
    242     {
    243       _dbus_string_init_const (&str, valid_paths[i]);
    244 
    245       if (!_dbus_validate_path (&str, 0,
    246                                 _dbus_string_get_length (&str)))
    247         {
    248           _dbus_warn ("Path \"%s\" should have been valid\n", valid_paths[i]);
    249           _dbus_assert_not_reached ("invalid path");
    250         }
    251 
    252       ++i;
    253     }
    254 
    255   i = 0;
    256   while (i < (int) _DBUS_N_ELEMENTS (invalid_paths))
    257     {
    258       _dbus_string_init_const (&str, invalid_paths[i]);
    259 
    260       if (_dbus_validate_path (&str, 0,
    261                                _dbus_string_get_length (&str)))
    262         {
    263           _dbus_warn ("Path \"%s\" should have been invalid\n", invalid_paths[i]);
    264           _dbus_assert_not_reached ("valid path");
    265         }
    266 
    267       ++i;
    268     }
    269 
    270   /* Interface validation */
    271   i = 0;
    272   while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
    273     {
    274       _dbus_string_init_const (&str, valid_interfaces[i]);
    275 
    276       if (!_dbus_validate_interface (&str, 0,
    277                                      _dbus_string_get_length (&str)))
    278         {
    279           _dbus_warn ("Interface \"%s\" should have been valid\n", valid_interfaces[i]);
    280           _dbus_assert_not_reached ("invalid interface");
    281         }
    282 
    283       ++i;
    284     }
    285 
    286   i = 0;
    287   while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
    288     {
    289       _dbus_string_init_const (&str, invalid_interfaces[i]);
    290 
    291       if (_dbus_validate_interface (&str, 0,
    292                                     _dbus_string_get_length (&str)))
    293         {
    294           _dbus_warn ("Interface \"%s\" should have been invalid\n", invalid_interfaces[i]);
    295           _dbus_assert_not_reached ("valid interface");
    296         }
    297 
    298       ++i;
    299     }
    300 
    301   /* Bus name validation (check that valid interfaces are valid bus names,
    302    * and invalid interfaces are invalid services except if they start with ':')
    303    */
    304   i = 0;
    305   while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
    306     {
    307       _dbus_string_init_const (&str, valid_interfaces[i]);
    308 
    309       if (!_dbus_validate_bus_name (&str, 0,
    310                                    _dbus_string_get_length (&str)))
    311         {
    312           _dbus_warn ("Bus name \"%s\" should have been valid\n", valid_interfaces[i]);
    313           _dbus_assert_not_reached ("invalid bus name");
    314         }
    315 
    316       ++i;
    317     }
    318 
    319   i = 0;
    320   while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
    321     {
    322       if (invalid_interfaces[i][0] != ':')
    323         {
    324           _dbus_string_init_const (&str, invalid_interfaces[i]);
    325 
    326           if (_dbus_validate_bus_name (&str, 0,
    327                                        _dbus_string_get_length (&str)))
    328             {
    329               _dbus_warn ("Bus name \"%s\" should have been invalid\n", invalid_interfaces[i]);
    330               _dbus_assert_not_reached ("valid bus name");
    331             }
    332         }
    333 
    334       ++i;
    335     }
    336 
    337   /* unique name validation */
    338   i = 0;
    339   while (i < (int) _DBUS_N_ELEMENTS (valid_unique_names))
    340     {
    341       _dbus_string_init_const (&str, valid_unique_names[i]);
    342 
    343       if (!_dbus_validate_bus_name (&str, 0,
    344                                     _dbus_string_get_length (&str)))
    345         {
    346           _dbus_warn ("Bus name \"%s\" should have been valid\n", valid_unique_names[i]);
    347           _dbus_assert_not_reached ("invalid unique name");
    348         }
    349 
    350       ++i;
    351     }
    352 
    353   i = 0;
    354   while (i < (int) _DBUS_N_ELEMENTS (invalid_unique_names))
    355     {
    356       _dbus_string_init_const (&str, invalid_unique_names[i]);
    357 
    358       if (_dbus_validate_bus_name (&str, 0,
    359                                    _dbus_string_get_length (&str)))
    360         {
    361           _dbus_warn ("Bus name \"%s\" should have been invalid\n", invalid_unique_names[i]);
    362           _dbus_assert_not_reached ("valid unique name");
    363         }
    364 
    365       ++i;
    366     }
    367 
    368 
    369   /* Error name validation (currently identical to interfaces)
    370    */
    371   i = 0;
    372   while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
    373     {
    374       _dbus_string_init_const (&str, valid_interfaces[i]);
    375 
    376       if (!_dbus_validate_error_name (&str, 0,
    377                                       _dbus_string_get_length (&str)))
    378         {
    379           _dbus_warn ("Error name \"%s\" should have been valid\n", valid_interfaces[i]);
    380           _dbus_assert_not_reached ("invalid error name");
    381         }
    382 
    383       ++i;
    384     }
    385 
    386   i = 0;
    387   while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
    388     {
    389       if (invalid_interfaces[i][0] != ':')
    390         {
    391           _dbus_string_init_const (&str, invalid_interfaces[i]);
    392 
    393           if (_dbus_validate_error_name (&str, 0,
    394                                          _dbus_string_get_length (&str)))
    395             {
    396               _dbus_warn ("Error name \"%s\" should have been invalid\n", invalid_interfaces[i]);
    397               _dbus_assert_not_reached ("valid error name");
    398             }
    399         }
    400 
    401       ++i;
    402     }
    403 
    404   /* Member validation */
    405   i = 0;
    406   while (i < (int) _DBUS_N_ELEMENTS (valid_members))
    407     {
    408       _dbus_string_init_const (&str, valid_members[i]);
    409 
    410       if (!_dbus_validate_member (&str, 0,
    411                                   _dbus_string_get_length (&str)))
    412         {
    413           _dbus_warn ("Member \"%s\" should have been valid\n", valid_members[i]);
    414           _dbus_assert_not_reached ("invalid member");
    415         }
    416 
    417       ++i;
    418     }
    419 
    420   i = 0;
    421   while (i < (int) _DBUS_N_ELEMENTS (invalid_members))
    422     {
    423       _dbus_string_init_const (&str, invalid_members[i]);
    424 
    425       if (_dbus_validate_member (&str, 0,
    426                                  _dbus_string_get_length (&str)))
    427         {
    428           _dbus_warn ("Member \"%s\" should have been invalid\n", invalid_members[i]);
    429           _dbus_assert_not_reached ("valid member");
    430         }
    431 
    432       ++i;
    433     }
    434 
    435   /* Signature validation */
    436   i = 0;
    437   while (i < (int) _DBUS_N_ELEMENTS (valid_signatures))
    438     {
    439       _dbus_string_init_const (&str, valid_signatures[i]);
    440 
    441       if (!_dbus_validate_signature (&str, 0,
    442                                      _dbus_string_get_length (&str)))
    443         {
    444           _dbus_warn ("Signature \"%s\" should have been valid\n", valid_signatures[i]);
    445           _dbus_assert_not_reached ("invalid signature");
    446         }
    447 
    448       ++i;
    449     }
    450 
    451   i = 0;
    452   while (i < (int) _DBUS_N_ELEMENTS (invalid_signatures))
    453     {
    454       _dbus_string_init_const (&str, invalid_signatures[i]);
    455 
    456       if (_dbus_validate_signature (&str, 0,
    457                                     _dbus_string_get_length (&str)))
    458         {
    459           _dbus_warn ("Signature \"%s\" should have been invalid\n", invalid_signatures[i]);
    460           _dbus_assert_not_reached ("valid signature");
    461         }
    462 
    463       ++i;
    464     }
    465 
    466   /* Validate claimed length longer than real length */
    467   _dbus_string_init_const (&str, "abc.efg");
    468   if (_dbus_validate_bus_name (&str, 0, 8))
    469     _dbus_assert_not_reached ("validated too-long string");
    470   if (_dbus_validate_interface (&str, 0, 8))
    471     _dbus_assert_not_reached ("validated too-long string");
    472   if (_dbus_validate_error_name (&str, 0, 8))
    473     _dbus_assert_not_reached ("validated too-long string");
    474 
    475   _dbus_string_init_const (&str, "abc");
    476   if (_dbus_validate_member (&str, 0, 4))
    477     _dbus_assert_not_reached ("validated too-long string");
    478 
    479   _dbus_string_init_const (&str, "sss");
    480   if (_dbus_validate_signature (&str, 0, 4))
    481     _dbus_assert_not_reached ("validated too-long signature");
    482 
    483   /* Validate string exceeding max name length */
    484   if (!_dbus_string_init (&str))
    485     _dbus_assert_not_reached ("no memory");
    486 
    487   while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
    488     if (!_dbus_string_append (&str, "abc.def"))
    489       _dbus_assert_not_reached ("no memory");
    490 
    491   if (_dbus_validate_bus_name (&str, 0, _dbus_string_get_length (&str)))
    492     _dbus_assert_not_reached ("validated overmax string");
    493   if (_dbus_validate_interface (&str, 0, _dbus_string_get_length (&str)))
    494     _dbus_assert_not_reached ("validated overmax string");
    495   if (_dbus_validate_error_name (&str, 0, _dbus_string_get_length (&str)))
    496     _dbus_assert_not_reached ("validated overmax string");
    497 
    498   /* overlong member */
    499   _dbus_string_set_length (&str, 0);
    500   while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
    501     if (!_dbus_string_append (&str, "abc"))
    502       _dbus_assert_not_reached ("no memory");
    503 
    504   if (_dbus_validate_member (&str, 0, _dbus_string_get_length (&str)))
    505     _dbus_assert_not_reached ("validated overmax string");
    506 
    507   /* overlong unique name */
    508   _dbus_string_set_length (&str, 0);
    509   _dbus_string_append (&str, ":");
    510   while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
    511     if (!_dbus_string_append (&str, "abc"))
    512       _dbus_assert_not_reached ("no memory");
    513 
    514   if (_dbus_validate_bus_name (&str, 0, _dbus_string_get_length (&str)))
    515     _dbus_assert_not_reached ("validated overmax string");
    516 
    517   _dbus_string_free (&str);
    518 
    519   /* Body validation; test basic validation of valid bodies for both endian */
    520 
    521   {
    522     int sequence;
    523     DBusString signature;
    524     DBusString body;
    525 
    526     if (!_dbus_string_init (&signature) || !_dbus_string_init (&body))
    527       _dbus_assert_not_reached ("oom");
    528 
    529     sequence = 0;
    530     while (dbus_internal_do_not_use_generate_bodies (sequence,
    531                                                      DBUS_LITTLE_ENDIAN,
    532                                                      &signature, &body))
    533       {
    534         DBusValidity validity;
    535 
    536         validity = _dbus_validate_body_with_reason (&signature, 0,
    537                                                     DBUS_LITTLE_ENDIAN,
    538                                                     NULL, &body, 0,
    539                                                     _dbus_string_get_length (&body));
    540         if (validity != DBUS_VALID)
    541           {
    542             _dbus_warn ("invalid code %d expected valid on sequence %d little endian\n",
    543                         validity, sequence);
    544             _dbus_verbose_bytes_of_string (&signature, 0, _dbus_string_get_length (&signature));
    545             _dbus_verbose_bytes_of_string (&body, 0, _dbus_string_get_length (&body));
    546             _dbus_assert_not_reached ("test failed");
    547           }
    548 
    549         _dbus_string_set_length (&signature, 0);
    550         _dbus_string_set_length (&body, 0);
    551         ++sequence;
    552       }
    553 
    554     sequence = 0;
    555     while (dbus_internal_do_not_use_generate_bodies (sequence,
    556                                                      DBUS_BIG_ENDIAN,
    557                                                      &signature, &body))
    558       {
    559         DBusValidity validity;
    560 
    561         validity = _dbus_validate_body_with_reason (&signature, 0,
    562                                                     DBUS_BIG_ENDIAN,
    563                                                     NULL, &body, 0,
    564                                                     _dbus_string_get_length (&body));
    565         if (validity != DBUS_VALID)
    566           {
    567             _dbus_warn ("invalid code %d expected valid on sequence %d big endian\n",
    568                         validity, sequence);
    569             _dbus_verbose_bytes_of_string (&signature, 0, _dbus_string_get_length (&signature));
    570             _dbus_verbose_bytes_of_string (&body, 0, _dbus_string_get_length (&body));
    571             _dbus_assert_not_reached ("test failed");
    572           }
    573 
    574         _dbus_string_set_length (&signature, 0);
    575         _dbus_string_set_length (&body, 0);
    576         ++sequence;
    577       }
    578 
    579     _dbus_string_free (&signature);
    580     _dbus_string_free (&body);
    581   }
    582 
    583   return TRUE;
    584 }
    585 
    586 #endif /* !DOXYGEN_SHOULD_SKIP_THIS */
    587 
    588 #endif /* DBUS_BUILD_TESTS */
    589