• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List

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

Generated on Thu Oct 4 2012 08:02:55 for D-Bus by  doxygen 1.7.1