D-Bus  1.4.16
dbus-marshal-validate.c
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-marshal-validate.c Validation routines for marshaled data
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 #include "dbus-internals.h"
00026 #include "dbus-marshal-validate.h"
00027 #include "dbus-marshal-recursive.h"
00028 #include "dbus-marshal-basic.h"
00029 #include "dbus-signature.h"
00030 #include "dbus-string.h"
00031 
00050 DBusValidity
00051 _dbus_validate_signature_with_reason (const DBusString *type_str,
00052                                       int               type_pos,
00053                                       int               len)
00054 {
00055   const unsigned char *p;
00056   const unsigned char *end;
00057   int last;
00058   int struct_depth;
00059   int array_depth;
00060   int dict_entry_depth;
00061   DBusValidity result;
00062 
00063   int element_count;
00064   DBusList *element_count_stack;
00065 
00066   result = DBUS_VALID;
00067   element_count_stack = NULL;
00068 
00069   if (!_dbus_list_append (&element_count_stack, _DBUS_INT_TO_POINTER (0)))
00070     {
00071       result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR;
00072       goto out;
00073     }
00074 
00075   _dbus_assert (type_str != NULL);
00076   _dbus_assert (type_pos < _DBUS_INT32_MAX - len);
00077   _dbus_assert (len >= 0);
00078   _dbus_assert (type_pos >= 0);
00079 
00080   if (len > DBUS_MAXIMUM_SIGNATURE_LENGTH)
00081     {
00082       result = DBUS_INVALID_SIGNATURE_TOO_LONG;
00083       goto out;
00084     }
00085 
00086   p = _dbus_string_get_const_data_len (type_str, type_pos, 0);
00087 
00088   end = _dbus_string_get_const_data_len (type_str, type_pos + len, 0);
00089   struct_depth = 0;
00090   array_depth = 0;
00091   dict_entry_depth = 0;
00092   last = DBUS_TYPE_INVALID;
00093 
00094   while (p != end)
00095     {
00096       switch (*p)
00097         {
00098         case DBUS_TYPE_BYTE:
00099         case DBUS_TYPE_BOOLEAN:
00100         case DBUS_TYPE_INT16:
00101         case DBUS_TYPE_UINT16:
00102         case DBUS_TYPE_INT32:
00103         case DBUS_TYPE_UINT32:
00104         case DBUS_TYPE_UNIX_FD:
00105         case DBUS_TYPE_INT64:
00106         case DBUS_TYPE_UINT64:
00107         case DBUS_TYPE_DOUBLE:
00108         case DBUS_TYPE_STRING:
00109         case DBUS_TYPE_OBJECT_PATH:
00110         case DBUS_TYPE_SIGNATURE:
00111         case DBUS_TYPE_VARIANT:
00112           break;
00113 
00114         case DBUS_TYPE_ARRAY:
00115           array_depth += 1;
00116           if (array_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH)
00117             {
00118               result = DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION;
00119               goto out;
00120             }
00121           break;
00122 
00123         case DBUS_STRUCT_BEGIN_CHAR:
00124           struct_depth += 1;
00125 
00126           if (struct_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH)
00127             {
00128               result = DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION;
00129               goto out;
00130             }
00131           
00132           if (!_dbus_list_append (&element_count_stack, 
00133                              _DBUS_INT_TO_POINTER (0)))
00134             {
00135               result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR;
00136               goto out;
00137             }
00138 
00139           break;
00140 
00141         case DBUS_STRUCT_END_CHAR:
00142           if (struct_depth == 0)
00143             {
00144               result = DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED;
00145               goto out;
00146             }
00147 
00148           if (last == DBUS_STRUCT_BEGIN_CHAR)
00149             {
00150               result = DBUS_INVALID_STRUCT_HAS_NO_FIELDS;
00151               goto out;
00152             }
00153 
00154           _dbus_list_pop_last (&element_count_stack);
00155 
00156           struct_depth -= 1;
00157           break;
00158 
00159         case DBUS_DICT_ENTRY_BEGIN_CHAR:
00160           if (last != DBUS_TYPE_ARRAY)
00161             {
00162               result = DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY;
00163               goto out;
00164             }
00165             
00166           dict_entry_depth += 1;
00167 
00168           if (dict_entry_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH)
00169             {
00170               result = DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION;
00171               goto out;
00172             }
00173 
00174           if (!_dbus_list_append (&element_count_stack, 
00175                              _DBUS_INT_TO_POINTER (0)))
00176             {
00177               result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR;
00178               goto out;
00179             }
00180 
00181           break;
00182 
00183         case DBUS_DICT_ENTRY_END_CHAR:
00184           if (dict_entry_depth == 0)
00185             {
00186               result = DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED;
00187               goto out;
00188             }
00189             
00190           dict_entry_depth -= 1;
00191 
00192           element_count = 
00193             _DBUS_POINTER_TO_INT (_dbus_list_pop_last (&element_count_stack));
00194 
00195           if (element_count != 2)
00196             {
00197               if (element_count == 0)
00198                 result = DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS;
00199               else if (element_count == 1)
00200                 result = DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD;
00201               else
00202                 result = DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS;
00203               
00204               goto out;
00205             }
00206           break;
00207           
00208         case DBUS_TYPE_STRUCT:     /* doesn't appear in signatures */
00209         case DBUS_TYPE_DICT_ENTRY: /* ditto */
00210         default:
00211           result = DBUS_INVALID_UNKNOWN_TYPECODE;
00212           goto out;
00213         }
00214 
00215       if (*p != DBUS_TYPE_ARRAY && 
00216           *p != DBUS_DICT_ENTRY_BEGIN_CHAR && 
00217           *p != DBUS_STRUCT_BEGIN_CHAR) 
00218         {
00219           element_count = 
00220             _DBUS_POINTER_TO_INT (_dbus_list_pop_last (&element_count_stack));
00221 
00222           ++element_count;
00223 
00224           if (!_dbus_list_append (&element_count_stack, 
00225                              _DBUS_INT_TO_POINTER (element_count)))
00226             {
00227               result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR;
00228               goto out;
00229             }
00230         }
00231       
00232       if (array_depth > 0)
00233         {
00234           if (*p == DBUS_TYPE_ARRAY && p != end)
00235             {
00236                const char *p1;
00237                p1 = p + 1;
00238                if (*p1 == DBUS_STRUCT_END_CHAR ||
00239                    *p1 == DBUS_DICT_ENTRY_END_CHAR)
00240                  {
00241                    result = DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE;
00242                    goto out;
00243                  }
00244             }
00245           else
00246             {
00247               array_depth = 0;
00248             }
00249         }
00250 
00251       if (last == DBUS_DICT_ENTRY_BEGIN_CHAR)
00252         {
00253           if (!(_dbus_type_is_valid (*p) && dbus_type_is_basic (*p)))
00254             {
00255               result = DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE;
00256               goto out;
00257             }
00258         }
00259 
00260       last = *p;
00261       ++p;
00262     }
00263 
00264 
00265   if (array_depth > 0)
00266     {
00267       result = DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE;
00268       goto out;
00269     }
00270     
00271   if (struct_depth > 0)
00272     {
00273        result = DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED;
00274        goto out;
00275     }
00276     
00277   if (dict_entry_depth > 0)
00278     {
00279       result =  DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED;
00280       goto out;
00281     }
00282     
00283   _dbus_assert (last != DBUS_TYPE_ARRAY);
00284   _dbus_assert (last != DBUS_STRUCT_BEGIN_CHAR);
00285   _dbus_assert (last != DBUS_DICT_ENTRY_BEGIN_CHAR);
00286 
00287   result = DBUS_VALID;
00288 
00289 out:
00290   _dbus_list_clear (&element_count_stack);
00291   return result;
00292 }
00293 
00294 /* note: this function is also used to validate the header's values,
00295  * since the header is a valid body with a particular signature.
00296  */
00297 static DBusValidity
00298 validate_body_helper (DBusTypeReader       *reader,
00299                       int                   byte_order,
00300                       dbus_bool_t           walk_reader_to_end,
00301                       int                   total_depth,
00302                       const unsigned char  *p,
00303                       const unsigned char  *end,
00304                       const unsigned char **new_p)
00305 {
00306   int current_type;
00307 
00308   /* The spec allows arrays and structs to each nest 32, for total
00309    * nesting of 2*32. We want to impose the same limit on "dynamic"
00310    * value nesting (not visible in the signature) which is introduced
00311    * by DBUS_TYPE_VARIANT.
00312    */
00313   if (total_depth > (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH * 2))
00314     {
00315       return DBUS_INVALID_NESTED_TOO_DEEPLY;
00316     }
00317 
00318   while ((current_type = _dbus_type_reader_get_current_type (reader)) != DBUS_TYPE_INVALID)
00319     {
00320       const unsigned char *a;
00321       int alignment;
00322 
00323 #if 0
00324       _dbus_verbose ("   validating value of type %s type reader %p type_pos %d p %p end %p %d remain\n",
00325                      _dbus_type_to_string (current_type), reader, reader->type_pos, p, end,
00326                      (int) (end - p));
00327 #endif
00328 
00329       /* Guarantee that p has one byte to look at */
00330       if (p == end)
00331         return DBUS_INVALID_NOT_ENOUGH_DATA;
00332 
00333       switch (current_type)
00334         {
00335         case DBUS_TYPE_BYTE:
00336           ++p;
00337           break;
00338 
00339         case DBUS_TYPE_BOOLEAN:
00340         case DBUS_TYPE_INT16:
00341         case DBUS_TYPE_UINT16:
00342         case DBUS_TYPE_INT32:
00343         case DBUS_TYPE_UINT32:
00344         case DBUS_TYPE_UNIX_FD:
00345         case DBUS_TYPE_INT64:
00346         case DBUS_TYPE_UINT64:
00347         case DBUS_TYPE_DOUBLE:
00348           alignment = _dbus_type_get_alignment (current_type);
00349           a = _DBUS_ALIGN_ADDRESS (p, alignment);
00350           if (a >= end)
00351             return DBUS_INVALID_NOT_ENOUGH_DATA;
00352           while (p != a)
00353             {
00354               if (*p != '\0')
00355                 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
00356               ++p;
00357             }
00358           
00359           if (current_type == DBUS_TYPE_BOOLEAN)
00360             {
00361               dbus_uint32_t v = _dbus_unpack_uint32 (byte_order,
00362                                                      p);
00363               if (!(v == 0 || v == 1))
00364                 return DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE;
00365             }
00366           
00367           p += alignment;
00368           break;
00369 
00370         case DBUS_TYPE_ARRAY:
00371         case DBUS_TYPE_STRING:
00372         case DBUS_TYPE_OBJECT_PATH:
00373           {
00374             dbus_uint32_t claimed_len;
00375 
00376             a = _DBUS_ALIGN_ADDRESS (p, 4);
00377             if (a + 4 > end)
00378               return DBUS_INVALID_NOT_ENOUGH_DATA;
00379             while (p != a)
00380               {
00381                 if (*p != '\0')
00382                   return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
00383                 ++p;
00384               }
00385 
00386             claimed_len = _dbus_unpack_uint32 (byte_order, p);
00387             p += 4;
00388 
00389             /* p may now be == end */
00390             _dbus_assert (p <= end);
00391 
00392             if (current_type == DBUS_TYPE_ARRAY)
00393               {
00394                 int array_elem_type = _dbus_type_reader_get_element_type (reader);
00395 
00396                 if (!_dbus_type_is_valid (array_elem_type))
00397                   {
00398                     return DBUS_INVALID_UNKNOWN_TYPECODE;
00399                   }
00400 
00401                 alignment = _dbus_type_get_alignment (array_elem_type);
00402 
00403                 a = _DBUS_ALIGN_ADDRESS (p, alignment);
00404 
00405                 /* a may now be == end */
00406                 if (a > end)
00407                   return DBUS_INVALID_NOT_ENOUGH_DATA;
00408 
00409                 while (p != a)
00410                   {
00411                     if (*p != '\0')
00412                       return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
00413                     ++p;
00414                   }
00415               }
00416 
00417             if (claimed_len > (unsigned long) (end - p))
00418               return DBUS_INVALID_LENGTH_OUT_OF_BOUNDS;
00419 
00420             if (current_type == DBUS_TYPE_OBJECT_PATH)
00421               {
00422                 DBusString str;
00423                 _dbus_string_init_const_len (&str, p, claimed_len);
00424                 if (!_dbus_validate_path (&str, 0,
00425                                           _dbus_string_get_length (&str)))
00426                   return DBUS_INVALID_BAD_PATH;
00427 
00428                 p += claimed_len;
00429               }
00430             else if (current_type == DBUS_TYPE_STRING)
00431               {
00432                 DBusString str;
00433                 _dbus_string_init_const_len (&str, p, claimed_len);
00434                 if (!_dbus_string_validate_utf8 (&str, 0,
00435                                                  _dbus_string_get_length (&str)))
00436                   return DBUS_INVALID_BAD_UTF8_IN_STRING;
00437 
00438                 p += claimed_len;
00439               }
00440             else if (current_type == DBUS_TYPE_ARRAY && claimed_len > 0)
00441               {
00442                 DBusTypeReader sub;
00443                 DBusValidity validity;
00444                 const unsigned char *array_end;
00445                 int array_elem_type;
00446 
00447                 if (claimed_len > DBUS_MAXIMUM_ARRAY_LENGTH)
00448                   return DBUS_INVALID_ARRAY_LENGTH_EXCEEDS_MAXIMUM;
00449                 
00450                 /* Remember that the reader is types only, so we can't
00451                  * use it to iterate over elements. It stays the same
00452                  * for all elements.
00453                  */
00454                 _dbus_type_reader_recurse (reader, &sub);
00455 
00456                 array_end = p + claimed_len;
00457 
00458                 array_elem_type = _dbus_type_reader_get_element_type (reader);
00459 
00460                 /* avoid recursive call to validate_body_helper if this is an array
00461                  * of fixed-size elements
00462                  */ 
00463                 if (dbus_type_is_fixed (array_elem_type))
00464                   {
00465                     /* bools need to be handled differently, because they can
00466                      * have an invalid value
00467                      */
00468                     if (array_elem_type == DBUS_TYPE_BOOLEAN)
00469                       {
00470                         dbus_uint32_t v;
00471                         alignment = _dbus_type_get_alignment (array_elem_type);
00472 
00473                         while (p < array_end)
00474                           {
00475                             v = _dbus_unpack_uint32 (byte_order, p);
00476 
00477                             if (!(v == 0 || v == 1))
00478                               return DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE;
00479 
00480                             p += alignment;
00481                           }
00482                       }
00483 
00484                     else
00485                       {
00486                         p = array_end;
00487                       }
00488                   }
00489 
00490                 else
00491                   {
00492                     while (p < array_end)
00493                       {
00494                         validity = validate_body_helper (&sub, byte_order, FALSE,
00495                                                          total_depth + 1,
00496                                                          p, end, &p);
00497                         if (validity != DBUS_VALID)
00498                           return validity;
00499                       }
00500                   }
00501 
00502                 if (p != array_end)
00503                   return DBUS_INVALID_ARRAY_LENGTH_INCORRECT;
00504               }
00505 
00506             /* check nul termination */
00507             if (current_type != DBUS_TYPE_ARRAY)
00508               {
00509                 if (p == end)
00510                   return DBUS_INVALID_NOT_ENOUGH_DATA;
00511 
00512                 if (*p != '\0')
00513                   return DBUS_INVALID_STRING_MISSING_NUL;
00514                 ++p;
00515               }
00516           }
00517           break;
00518 
00519         case DBUS_TYPE_SIGNATURE:
00520           {
00521             dbus_uint32_t claimed_len;
00522             DBusString str;
00523             DBusValidity validity;
00524 
00525             claimed_len = *p;
00526             ++p;
00527 
00528             /* 1 is for nul termination */
00529             if (claimed_len + 1 > (unsigned long) (end - p))
00530               return DBUS_INVALID_SIGNATURE_LENGTH_OUT_OF_BOUNDS;
00531 
00532             _dbus_string_init_const_len (&str, p, claimed_len);
00533             validity =
00534               _dbus_validate_signature_with_reason (&str, 0,
00535                                                     _dbus_string_get_length (&str));
00536 
00537             if (validity != DBUS_VALID)
00538               return validity;
00539 
00540             p += claimed_len;
00541 
00542             _dbus_assert (p < end);
00543             if (*p != DBUS_TYPE_INVALID)
00544               return DBUS_INVALID_SIGNATURE_MISSING_NUL;
00545 
00546             ++p;
00547 
00548             _dbus_verbose ("p = %p end = %p claimed_len %u\n", p, end, claimed_len);
00549           }
00550           break;
00551 
00552         case DBUS_TYPE_VARIANT:
00553           {
00554             /* 1 byte sig len, sig typecodes, align to
00555              * contained-type-boundary, values.
00556              */
00557 
00558             /* In addition to normal signature validation, we need to be sure
00559              * the signature contains only a single (possibly container) type.
00560              */
00561             dbus_uint32_t claimed_len;
00562             DBusString sig;
00563             DBusTypeReader sub;
00564             DBusValidity validity;
00565             int contained_alignment;
00566             int contained_type;
00567             DBusValidity reason;
00568 
00569             claimed_len = *p;
00570             ++p;
00571 
00572             /* + 1 for nul */
00573             if (claimed_len + 1 > (unsigned long) (end - p))
00574               return DBUS_INVALID_VARIANT_SIGNATURE_LENGTH_OUT_OF_BOUNDS;
00575 
00576             _dbus_string_init_const_len (&sig, p, claimed_len);
00577             reason = _dbus_validate_signature_with_reason (&sig, 0,
00578                                            _dbus_string_get_length (&sig));
00579             if (!(reason == DBUS_VALID))
00580               {
00581                 if (reason == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
00582                   return reason;
00583                 else 
00584                   return DBUS_INVALID_VARIANT_SIGNATURE_BAD;
00585               }
00586 
00587             p += claimed_len;
00588             
00589             if (*p != DBUS_TYPE_INVALID)
00590               return DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL;
00591             ++p;
00592 
00593             contained_type = _dbus_first_type_in_signature (&sig, 0);
00594             if (contained_type == DBUS_TYPE_INVALID)
00595               return DBUS_INVALID_VARIANT_SIGNATURE_EMPTY;
00596             
00597             contained_alignment = _dbus_type_get_alignment (contained_type);
00598             
00599             a = _DBUS_ALIGN_ADDRESS (p, contained_alignment);
00600             if (a > end)
00601               return DBUS_INVALID_NOT_ENOUGH_DATA;
00602             while (p != a)
00603               {
00604                 if (*p != '\0')
00605                   return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
00606                 ++p;
00607               }
00608 
00609             _dbus_type_reader_init_types_only (&sub, &sig, 0);
00610 
00611             _dbus_assert (_dbus_type_reader_get_current_type (&sub) != DBUS_TYPE_INVALID);
00612 
00613             validity = validate_body_helper (&sub, byte_order, FALSE,
00614                                              total_depth + 1,
00615                                              p, end, &p);
00616             if (validity != DBUS_VALID)
00617               return validity;
00618 
00619             if (_dbus_type_reader_next (&sub))
00620               return DBUS_INVALID_VARIANT_SIGNATURE_SPECIFIES_MULTIPLE_VALUES;
00621 
00622             _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_INVALID);
00623           }
00624           break;
00625 
00626         case DBUS_TYPE_DICT_ENTRY:
00627         case DBUS_TYPE_STRUCT:
00628           {
00629             DBusTypeReader sub;
00630             DBusValidity validity;
00631 
00632             a = _DBUS_ALIGN_ADDRESS (p, 8);
00633             if (a > end)
00634               return DBUS_INVALID_NOT_ENOUGH_DATA;
00635             while (p != a)
00636               {
00637                 if (*p != '\0')
00638                   return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
00639                 ++p;
00640               }
00641 
00642             _dbus_type_reader_recurse (reader, &sub);
00643 
00644             validity = validate_body_helper (&sub, byte_order, TRUE,
00645                                              total_depth + 1,
00646                                              p, end, &p);
00647             if (validity != DBUS_VALID)
00648               return validity;
00649           }
00650           break;
00651 
00652         default:
00653           _dbus_assert_not_reached ("invalid typecode in supposedly-validated signature");
00654           break;
00655         }
00656 
00657 #if 0
00658       _dbus_verbose ("   validated value of type %s type reader %p type_pos %d p %p end %p %d remain\n",
00659                      _dbus_type_to_string (current_type), reader, reader->type_pos, p, end,
00660                      (int) (end - p));
00661 #endif
00662 
00663       if (p > end)
00664         {
00665           _dbus_verbose ("not enough data!!! p = %p end = %p end-p = %d\n",
00666                          p, end, (int) (end - p));
00667           return DBUS_INVALID_NOT_ENOUGH_DATA;
00668         }
00669 
00670       if (walk_reader_to_end)
00671         _dbus_type_reader_next (reader);
00672       else
00673         break;
00674     }
00675 
00676   if (new_p)
00677     *new_p = p;
00678 
00679   return DBUS_VALID;
00680 }
00681 
00702 DBusValidity
00703 _dbus_validate_body_with_reason (const DBusString *expected_signature,
00704                                  int               expected_signature_start,
00705                                  int               byte_order,
00706                                  int              *bytes_remaining,
00707                                  const DBusString *value_str,
00708                                  int               value_pos,
00709                                  int               len)
00710 {
00711   DBusTypeReader reader;
00712   const unsigned char *p;
00713   const unsigned char *end;
00714   DBusValidity validity;
00715 
00716   _dbus_assert (len >= 0);
00717   _dbus_assert (value_pos >= 0);
00718   _dbus_assert (value_pos <= _dbus_string_get_length (value_str) - len);
00719 
00720   _dbus_verbose ("validating body from pos %d len %d sig '%s'\n",
00721                  value_pos, len, _dbus_string_get_const_data_len (expected_signature,
00722                                                                   expected_signature_start,
00723                                                                   0));
00724 
00725   _dbus_type_reader_init_types_only (&reader,
00726                                      expected_signature, expected_signature_start);
00727 
00728   p = _dbus_string_get_const_data_len (value_str, value_pos, len);
00729   end = p + len;
00730 
00731   validity = validate_body_helper (&reader, byte_order, TRUE, 0, p, end, &p);
00732   if (validity != DBUS_VALID)
00733     return validity;
00734   
00735   if (bytes_remaining)
00736     {
00737       *bytes_remaining = end - p;
00738       return DBUS_VALID;
00739     }
00740   else if (p < end)
00741     return DBUS_INVALID_TOO_MUCH_DATA;
00742   else
00743     {
00744       _dbus_assert (p == end);
00745       return DBUS_VALID;
00746     }
00747 }
00748 
00753 #define VALID_INITIAL_NAME_CHARACTER(c)         \
00754   ( ((c) >= 'A' && (c) <= 'Z') ||               \
00755     ((c) >= 'a' && (c) <= 'z') ||               \
00756     ((c) == '_') )
00757 
00762 #define VALID_NAME_CHARACTER(c)                 \
00763   ( ((c) >= '0' && (c) <= '9') ||               \
00764     ((c) >= 'A' && (c) <= 'Z') ||               \
00765     ((c) >= 'a' && (c) <= 'z') ||               \
00766     ((c) == '_') )
00767 
00784 dbus_bool_t
00785 _dbus_validate_path (const DBusString  *str,
00786                      int                start,
00787                      int                len)
00788 {
00789   const unsigned char *s;
00790   const unsigned char *end;
00791   const unsigned char *last_slash;
00792 
00793   _dbus_assert (start >= 0);
00794   _dbus_assert (len >= 0);
00795   _dbus_assert (start <= _dbus_string_get_length (str));
00796   
00797   if (len > _dbus_string_get_length (str) - start)
00798     return FALSE;
00799 
00800   if (len == 0)
00801     return FALSE;
00802 
00803   s = _dbus_string_get_const_data (str) + start;
00804   end = s + len;
00805 
00806   if (*s != '/')
00807     return FALSE;
00808   last_slash = s;
00809   ++s;
00810 
00811   while (s != end)
00812     {
00813       if (*s == '/')
00814         {
00815           if ((s - last_slash) < 2)
00816             return FALSE; /* no empty path components allowed */
00817 
00818           last_slash = s;
00819         }
00820       else
00821         {
00822           if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
00823             return FALSE;
00824         }
00825 
00826       ++s;
00827     }
00828 
00829   if ((end - last_slash) < 2 &&
00830       len > 1)
00831     return FALSE; /* trailing slash not allowed unless the string is "/" */
00832 
00833   return TRUE;
00834 }
00835 
00836 const char *
00837 _dbus_validity_to_error_message (DBusValidity validity)
00838 {
00839   switch (validity)
00840     {
00841     case DBUS_VALIDITY_UNKNOWN_OOM_ERROR:                          return "Out of memory";
00842     case DBUS_INVALID_FOR_UNKNOWN_REASON:                          return "Unknown reason";
00843     case DBUS_VALID_BUT_INCOMPLETE:                                return "Valid but incomplete";
00844     case DBUS_VALIDITY_UNKNOWN:                                    return "Validity unknown";
00845     case DBUS_VALID:                                               return "Valid";
00846     case DBUS_INVALID_UNKNOWN_TYPECODE:                            return "Unknown typecode";
00847     case DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE:                  return "Missing array element type";
00848     case DBUS_INVALID_SIGNATURE_TOO_LONG:                          return "Signature is too long";
00849     case DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION:            return "Exceeded maximum array recursion";
00850     case DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION:           return "Exceeded maximum struct recursion";
00851     case DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED:                return "Struct ended but not started";
00852     case DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED:                return "Struct started but not ended";
00853     case DBUS_INVALID_STRUCT_HAS_NO_FIELDS:                        return "Struct has no fields";
00854     case DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL:                   return "Alignment padding not null";
00855     case DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE:                     return "Boolean is not zero or one";
00856     case DBUS_INVALID_NOT_ENOUGH_DATA:                             return "Not enough data";
00857     case DBUS_INVALID_TOO_MUCH_DATA:                               return "Too much data";
00858     case DBUS_INVALID_BAD_BYTE_ORDER:                              return "Bad byte order";
00859     case DBUS_INVALID_BAD_PROTOCOL_VERSION:                        return "Bad protocol version";
00860     case DBUS_INVALID_BAD_MESSAGE_TYPE:                            return "Bad message type";
00861     case DBUS_INVALID_BAD_SERIAL:                                  return "Bad serial";
00862     case DBUS_INVALID_INSANE_FIELDS_ARRAY_LENGTH:                  return "Insane fields array length";
00863     case DBUS_INVALID_INSANE_BODY_LENGTH:                          return "Insane body length";
00864     case DBUS_INVALID_MESSAGE_TOO_LONG:                            return "Message too long";
00865     case DBUS_INVALID_HEADER_FIELD_CODE:                           return "Header field code";
00866     case DBUS_INVALID_HEADER_FIELD_HAS_WRONG_TYPE:                 return "Header field has wrong type";
00867     case DBUS_INVALID_USES_LOCAL_INTERFACE:                        return "Uses local interface";
00868     case DBUS_INVALID_USES_LOCAL_PATH:                             return "Uses local path";
00869     case DBUS_INVALID_HEADER_FIELD_APPEARS_TWICE:                  return "Header field appears twice";
00870     case DBUS_INVALID_BAD_DESTINATION:                             return "Bad destination";
00871     case DBUS_INVALID_BAD_INTERFACE:                               return "Bad interface";
00872     case DBUS_INVALID_BAD_MEMBER:                                  return "Bad member";
00873     case DBUS_INVALID_BAD_ERROR_NAME:                              return "Bad error name";
00874     case DBUS_INVALID_BAD_SENDER:                                  return "Bad sender";
00875     case DBUS_INVALID_MISSING_PATH:                                return "Missing path";
00876     case DBUS_INVALID_MISSING_INTERFACE:                           return "Missing interface";
00877     case DBUS_INVALID_MISSING_MEMBER:                              return "Missing member";
00878     case DBUS_INVALID_MISSING_ERROR_NAME:                          return "Missing error name";
00879     case DBUS_INVALID_MISSING_REPLY_SERIAL:                        return "Missing reply serial";
00880     case DBUS_INVALID_LENGTH_OUT_OF_BOUNDS:                        return "Length out of bounds";
00881     case DBUS_INVALID_ARRAY_LENGTH_EXCEEDS_MAXIMUM:                return "Array length exceeds maximum";
00882     case DBUS_INVALID_BAD_PATH:                                    return "Bad path";
00883     case DBUS_INVALID_SIGNATURE_LENGTH_OUT_OF_BOUNDS:              return "Signature length out of bounds";
00884     case DBUS_INVALID_BAD_UTF8_IN_STRING:                          return "Bad utf8 in string";
00885     case DBUS_INVALID_ARRAY_LENGTH_INCORRECT:                      return "Array length incorrect";
00886     case DBUS_INVALID_VARIANT_SIGNATURE_LENGTH_OUT_OF_BOUNDS:      return "Variant signature length out of bounds";
00887     case DBUS_INVALID_VARIANT_SIGNATURE_BAD:                       return "Variant signature bad";
00888     case DBUS_INVALID_VARIANT_SIGNATURE_EMPTY:                     return "Variant signature empty";
00889     case DBUS_INVALID_VARIANT_SIGNATURE_SPECIFIES_MULTIPLE_VALUES: return "Variant signature specifies multiple values";
00890     case DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL:               return "Variant signature missing nul";
00891     case DBUS_INVALID_STRING_MISSING_NUL:                          return "String missing nul";
00892     case DBUS_INVALID_SIGNATURE_MISSING_NUL:                       return "Signature missing nul";
00893     case DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION:       return "Exceeded maximum dict entry recursion";
00894     case DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED:            return "Dict entry ended but not started";
00895     case DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED:            return "Dict entry started but not ended";
00896     case DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS:                    return "Dict entry has no fields";
00897     case DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD:               return "Dict entry has only one field";
00898     case DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS:              return "Dict entry has too many fields";
00899     case DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY:                 return "Dict entry not inside array";
00900     case DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE:                 return "Dict key must be basic type";
00901     case DBUS_INVALID_NESTED_TOO_DEEPLY:                           return "Variants cannot be used to create a hugely recursive tree of values";
00902     default:
00903       return "Invalid";
00904     }
00905 }
00906 
00920 dbus_bool_t
00921 _dbus_validate_interface (const DBusString  *str,
00922                           int                start,
00923                           int                len)
00924 {
00925   const unsigned char *s;
00926   const unsigned char *end;
00927   const unsigned char *iface;
00928   const unsigned char *last_dot;
00929 
00930   _dbus_assert (start >= 0);
00931   _dbus_assert (len >= 0);
00932   _dbus_assert (start <= _dbus_string_get_length (str));
00933 
00934   if (len > _dbus_string_get_length (str) - start)
00935     return FALSE;
00936 
00937   if (len > DBUS_MAXIMUM_NAME_LENGTH)
00938     return FALSE;
00939 
00940   if (len == 0)
00941     return FALSE;
00942 
00943   last_dot = NULL;
00944   iface = _dbus_string_get_const_data (str) + start;
00945   end = iface + len;
00946   s = iface;
00947 
00948   /* check special cases of first char so it doesn't have to be done
00949    * in the loop. Note we know len > 0
00950    */
00951   if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */
00952     return FALSE;
00953   else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s)))
00954     return FALSE;
00955   else
00956     ++s;
00957 
00958   while (s != end)
00959     {
00960       if (*s == '.')
00961         {
00962           if (_DBUS_UNLIKELY ((s + 1) == end))
00963             return FALSE;
00964           else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*(s + 1))))
00965             return FALSE;
00966           last_dot = s;
00967           ++s; /* we just validated the next char, so skip two */
00968         }
00969       else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
00970         {
00971           return FALSE;
00972         }
00973 
00974       ++s;
00975     }
00976 
00977   if (_DBUS_UNLIKELY (last_dot == NULL))
00978     return FALSE;
00979 
00980   return TRUE;
00981 }
00982 
00996 dbus_bool_t
00997 _dbus_validate_member (const DBusString  *str,
00998                        int                start,
00999                        int                len)
01000 {
01001   const unsigned char *s;
01002   const unsigned char *end;
01003   const unsigned char *member;
01004 
01005   _dbus_assert (start >= 0);
01006   _dbus_assert (len >= 0);
01007   _dbus_assert (start <= _dbus_string_get_length (str));
01008 
01009   if (len > _dbus_string_get_length (str) - start)
01010     return FALSE;
01011 
01012   if (len > DBUS_MAXIMUM_NAME_LENGTH)
01013     return FALSE;
01014 
01015   if (len == 0)
01016     return FALSE;
01017 
01018   member = _dbus_string_get_const_data (str) + start;
01019   end = member + len;
01020   s = member;
01021 
01022   /* check special cases of first char so it doesn't have to be done
01023    * in the loop. Note we know len > 0
01024    */
01025 
01026   if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s)))
01027     return FALSE;
01028   else
01029     ++s;
01030 
01031   while (s != end)
01032     {
01033       if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
01034         {
01035           return FALSE;
01036         }
01037 
01038       ++s;
01039     }
01040 
01041   return TRUE;
01042 }
01043 
01057 dbus_bool_t
01058 _dbus_validate_error_name (const DBusString  *str,
01059                            int                start,
01060                            int                len)
01061 {
01062   /* Same restrictions as interface name at the moment */
01063   return _dbus_validate_interface (str, start, len);
01064 }
01065 
01070 #define VALID_INITIAL_BUS_NAME_CHARACTER(c)         \
01071   ( ((c) >= 'A' && (c) <= 'Z') ||               \
01072     ((c) >= 'a' && (c) <= 'z') ||               \
01073     ((c) == '_') || ((c) == '-'))
01074 
01079 #define VALID_BUS_NAME_CHARACTER(c)                 \
01080   ( ((c) >= '0' && (c) <= '9') ||               \
01081     ((c) >= 'A' && (c) <= 'Z') ||               \
01082     ((c) >= 'a' && (c) <= 'z') ||               \
01083     ((c) == '_') || ((c) == '-'))
01084 
01098 dbus_bool_t
01099 _dbus_validate_bus_name (const DBusString  *str,
01100                          int                start,
01101                          int                len)
01102 {
01103   const unsigned char *s;
01104   const unsigned char *end;
01105   const unsigned char *iface;
01106   const unsigned char *last_dot;
01107 
01108   _dbus_assert (start >= 0);
01109   _dbus_assert (len >= 0);
01110   _dbus_assert (start <= _dbus_string_get_length (str));
01111 
01112   if (len > _dbus_string_get_length (str) - start)
01113     return FALSE;
01114 
01115   if (len > DBUS_MAXIMUM_NAME_LENGTH)
01116     return FALSE;
01117 
01118   if (len == 0)
01119     return FALSE;
01120 
01121   last_dot = NULL;
01122   iface = _dbus_string_get_const_data (str) + start;
01123   end = iface + len;
01124   s = iface;
01125 
01126   /* check special cases of first char so it doesn't have to be done
01127    * in the loop. Note we know len > 0
01128    */
01129   if (*s == ':')
01130   {
01131     /* unique name */
01132     ++s;
01133     while (s != end)
01134       {
01135         if (*s == '.')
01136           {
01137             if (_DBUS_UNLIKELY ((s + 1) == end))
01138               return FALSE;
01139             if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*(s + 1))))
01140               return FALSE;
01141             ++s; /* we just validated the next char, so skip two */
01142           }
01143         else if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*s)))
01144           {
01145             return FALSE;
01146           }
01147 
01148         ++s;
01149       }
01150 
01151     return TRUE;
01152   }
01153   else if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */
01154     return FALSE;
01155   else if (_DBUS_UNLIKELY (!VALID_INITIAL_BUS_NAME_CHARACTER (*s)))
01156     return FALSE;
01157   else
01158     ++s;
01159 
01160   while (s != end)
01161     {
01162       if (*s == '.')
01163         {
01164           if (_DBUS_UNLIKELY ((s + 1) == end))
01165             return FALSE;
01166           else if (_DBUS_UNLIKELY (!VALID_INITIAL_BUS_NAME_CHARACTER (*(s + 1))))
01167             return FALSE;
01168           last_dot = s;
01169           ++s; /* we just validated the next char, so skip two */
01170         }
01171       else if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*s)))
01172         {
01173           return FALSE;
01174         }
01175 
01176       ++s;
01177     }
01178 
01179   if (_DBUS_UNLIKELY (last_dot == NULL))
01180     return FALSE;
01181 
01182   return TRUE;
01183 }
01184 
01197 dbus_bool_t
01198 _dbus_validate_signature (const DBusString  *str,
01199                           int                start,
01200                           int                len)
01201 {
01202   _dbus_assert (start >= 0);
01203   _dbus_assert (start <= _dbus_string_get_length (str));
01204   _dbus_assert (len >= 0);
01205 
01206   if (len > _dbus_string_get_length (str) - start)
01207     return FALSE;
01208 
01209   return _dbus_validate_signature_with_reason (str, start, len) == DBUS_VALID;
01210 }
01211 
01213 DEFINE_DBUS_NAME_CHECK(path)
01215 DEFINE_DBUS_NAME_CHECK(interface)
01217 DEFINE_DBUS_NAME_CHECK(member)
01219 DEFINE_DBUS_NAME_CHECK(error_name)
01221 DEFINE_DBUS_NAME_CHECK(bus_name)
01223 DEFINE_DBUS_NAME_CHECK(signature)
01225 DEFINE_DBUS_NAME_CHECK(utf8)
01226 
01229 /* tests in dbus-marshal-validate-util.c */