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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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           _dbus_type_is_valid (*p) &&
00251           !dbus_type_is_basic (*p))
00252         {
00253           result = DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE;
00254           goto out;
00255         }
00256         
00257       last = *p;
00258       ++p;
00259     }
00260 
00261 
00262   if (array_depth > 0)
00263     {
00264       result = DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE;
00265       goto out;
00266     }
00267     
00268   if (struct_depth > 0)
00269     {
00270        result = DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED;
00271        goto out;
00272     }
00273     
00274   if (dict_entry_depth > 0)
00275     {
00276       result =  DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED;
00277       goto out;
00278     }
00279     
00280   _dbus_assert (last != DBUS_TYPE_ARRAY);
00281   _dbus_assert (last != DBUS_STRUCT_BEGIN_CHAR);
00282   _dbus_assert (last != DBUS_DICT_ENTRY_BEGIN_CHAR);
00283 
00284   result = DBUS_VALID;
00285 
00286 out:
00287   _dbus_list_clear (&element_count_stack);
00288   return result;
00289 }
00290 
00291 static DBusValidity
00292 validate_body_helper (DBusTypeReader       *reader,
00293                       int                   byte_order,
00294                       dbus_bool_t           walk_reader_to_end,
00295                       const unsigned char  *p,
00296                       const unsigned char  *end,
00297                       const unsigned char **new_p)
00298 {
00299   int current_type;
00300 
00301   while ((current_type = _dbus_type_reader_get_current_type (reader)) != DBUS_TYPE_INVALID)
00302     {
00303       const unsigned char *a;
00304       int alignment;
00305 
00306 #if 0
00307       _dbus_verbose ("   validating value of type %s type reader %p type_pos %d p %p end %p %d remain\n",
00308                      _dbus_type_to_string (current_type), reader, reader->type_pos, p, end,
00309                      (int) (end - p));
00310 #endif
00311 
00312       /* Guarantee that p has one byte to look at */
00313       if (p == end)
00314         return DBUS_INVALID_NOT_ENOUGH_DATA;
00315 
00316       switch (current_type)
00317         {
00318         case DBUS_TYPE_BYTE:
00319           ++p;
00320           break;
00321           
00322         case DBUS_TYPE_BOOLEAN:
00323         case DBUS_TYPE_INT16:
00324         case DBUS_TYPE_UINT16:
00325         case DBUS_TYPE_INT32:
00326         case DBUS_TYPE_UINT32:
00327         case DBUS_TYPE_INT64:
00328         case DBUS_TYPE_UINT64:
00329         case DBUS_TYPE_DOUBLE:
00330           alignment = _dbus_type_get_alignment (current_type);
00331           a = _DBUS_ALIGN_ADDRESS (p, alignment);
00332           if (a >= end)
00333             return DBUS_INVALID_NOT_ENOUGH_DATA;
00334           while (p != a)
00335             {
00336               if (*p != '\0')
00337                 return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
00338               ++p;
00339             }
00340           
00341           if (current_type == DBUS_TYPE_BOOLEAN)
00342             {
00343               dbus_uint32_t v = _dbus_unpack_uint32 (byte_order,
00344                                                      p);
00345               if (!(v == 0 || v == 1))
00346                 return DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE;
00347             }
00348           
00349           p += alignment;
00350           break;
00351 
00352         case DBUS_TYPE_ARRAY:
00353         case DBUS_TYPE_STRING:
00354         case DBUS_TYPE_OBJECT_PATH:
00355           {
00356             dbus_uint32_t claimed_len;
00357 
00358             a = _DBUS_ALIGN_ADDRESS (p, 4);
00359             if (a + 4 > end)
00360               return DBUS_INVALID_NOT_ENOUGH_DATA;
00361             while (p != a)
00362               {
00363                 if (*p != '\0')
00364                   return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
00365                 ++p;
00366               }
00367 
00368             claimed_len = _dbus_unpack_uint32 (byte_order, p);
00369             p += 4;
00370 
00371             /* p may now be == end */
00372             _dbus_assert (p <= end);
00373 
00374             if (current_type == DBUS_TYPE_ARRAY)
00375               {
00376                 int array_elem_type = _dbus_type_reader_get_element_type (reader);
00377 
00378                 if (!_dbus_type_is_valid (array_elem_type))
00379                   {
00380                     return DBUS_INVALID_UNKNOWN_TYPECODE;
00381                   }
00382 
00383                 alignment = _dbus_type_get_alignment (array_elem_type);
00384 
00385                 a = _DBUS_ALIGN_ADDRESS (p, alignment);
00386 
00387                 /* a may now be == end */
00388                 if (a > end)
00389                   return DBUS_INVALID_NOT_ENOUGH_DATA;
00390 
00391                 while (p != a)
00392                   {
00393                     if (*p != '\0')
00394                       return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
00395                     ++p;
00396                   }
00397               }
00398 
00399             if (claimed_len > (unsigned long) (end - p))
00400               return DBUS_INVALID_LENGTH_OUT_OF_BOUNDS;
00401 
00402             if (current_type == DBUS_TYPE_OBJECT_PATH)
00403               {
00404                 DBusString str;
00405                 _dbus_string_init_const_len (&str, p, claimed_len);
00406                 if (!_dbus_validate_path (&str, 0,
00407                                           _dbus_string_get_length (&str)))
00408                   return DBUS_INVALID_BAD_PATH;
00409 
00410                 p += claimed_len;
00411               }
00412             else if (current_type == DBUS_TYPE_STRING)
00413               {
00414                 DBusString str;
00415                 _dbus_string_init_const_len (&str, p, claimed_len);
00416                 if (!_dbus_string_validate_utf8 (&str, 0,
00417                                                  _dbus_string_get_length (&str)))
00418                   return DBUS_INVALID_BAD_UTF8_IN_STRING;
00419 
00420                 p += claimed_len;
00421               }
00422             else if (current_type == DBUS_TYPE_ARRAY && claimed_len > 0)
00423               {
00424                 DBusTypeReader sub;
00425                 DBusValidity validity;
00426                 const unsigned char *array_end;
00427                 int array_elem_type;
00428 
00429                 if (claimed_len > DBUS_MAXIMUM_ARRAY_LENGTH)
00430                   return DBUS_INVALID_ARRAY_LENGTH_EXCEEDS_MAXIMUM;
00431                 
00432                 /* Remember that the reader is types only, so we can't
00433                  * use it to iterate over elements. It stays the same
00434                  * for all elements.
00435                  */
00436                 _dbus_type_reader_recurse (reader, &sub);
00437 
00438                 array_end = p + claimed_len;
00439 
00440                 array_elem_type = _dbus_type_reader_get_element_type (reader);
00441 
00442                 /* avoid recursive call to validate_body_helper if this is an array
00443                  * of fixed-size elements
00444                  */ 
00445                 if (dbus_type_is_fixed (array_elem_type))
00446                   {
00447                     /* bools need to be handled differently, because they can
00448                      * have an invalid value
00449                      */
00450                     if (array_elem_type == DBUS_TYPE_BOOLEAN)
00451                       {
00452                         dbus_uint32_t v;
00453                         alignment = _dbus_type_get_alignment (array_elem_type);
00454 
00455                         while (p < array_end)
00456                           {
00457                             v = _dbus_unpack_uint32 (byte_order, p);
00458 
00459                             if (!(v == 0 || v == 1))
00460                               return DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE;
00461 
00462                             p += alignment;
00463                           }
00464                       }
00465 
00466                     else
00467                       {
00468                         p = array_end;
00469                       }
00470                   }
00471 
00472                 else
00473                   {
00474                     while (p < array_end)
00475                       {
00476                         validity = validate_body_helper (&sub, byte_order, FALSE, p, end, &p);
00477                         if (validity != DBUS_VALID)
00478                           return validity;
00479                       }
00480                   }
00481 
00482                 if (p != array_end)
00483                   return DBUS_INVALID_ARRAY_LENGTH_INCORRECT;
00484               }
00485 
00486             /* check nul termination */
00487             if (current_type != DBUS_TYPE_ARRAY)
00488               {
00489                 if (p == end)
00490                   return DBUS_INVALID_NOT_ENOUGH_DATA;
00491 
00492                 if (*p != '\0')
00493                   return DBUS_INVALID_STRING_MISSING_NUL;
00494                 ++p;
00495               }
00496           }
00497           break;
00498 
00499         case DBUS_TYPE_SIGNATURE:
00500           {
00501             dbus_uint32_t claimed_len;
00502             DBusString str;
00503             DBusValidity validity;
00504 
00505             claimed_len = *p;
00506             ++p;
00507 
00508             /* 1 is for nul termination */
00509             if (claimed_len + 1 > (unsigned long) (end - p))
00510               return DBUS_INVALID_SIGNATURE_LENGTH_OUT_OF_BOUNDS;
00511 
00512             _dbus_string_init_const_len (&str, p, claimed_len);
00513             validity =
00514               _dbus_validate_signature_with_reason (&str, 0,
00515                                                     _dbus_string_get_length (&str));
00516 
00517             if (validity != DBUS_VALID)
00518               return validity;
00519 
00520             p += claimed_len;
00521 
00522             _dbus_assert (p < end);
00523             if (*p != DBUS_TYPE_INVALID)
00524               return DBUS_INVALID_SIGNATURE_MISSING_NUL;
00525 
00526             ++p;
00527 
00528             _dbus_verbose ("p = %p end = %p claimed_len %u\n", p, end, claimed_len);
00529           }
00530           break;
00531 
00532         case DBUS_TYPE_VARIANT:
00533           {
00534             /* 1 byte sig len, sig typecodes, align to
00535              * contained-type-boundary, values.
00536              */
00537 
00538             /* In addition to normal signature validation, we need to be sure
00539              * the signature contains only a single (possibly container) type.
00540              */
00541             dbus_uint32_t claimed_len;
00542             DBusString sig;
00543             DBusTypeReader sub;
00544             DBusValidity validity;
00545             int contained_alignment;
00546             int contained_type;
00547             DBusValidity reason;
00548 
00549             claimed_len = *p;
00550             ++p;
00551 
00552             /* + 1 for nul */
00553             if (claimed_len + 1 > (unsigned long) (end - p))
00554               return DBUS_INVALID_VARIANT_SIGNATURE_LENGTH_OUT_OF_BOUNDS;
00555 
00556             _dbus_string_init_const_len (&sig, p, claimed_len);
00557             reason = _dbus_validate_signature_with_reason (&sig, 0,
00558                                            _dbus_string_get_length (&sig));
00559             if (!(reason == DBUS_VALID))
00560               {
00561                 if (reason == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
00562                   return reason;
00563                 else 
00564                   return DBUS_INVALID_VARIANT_SIGNATURE_BAD;
00565               }
00566 
00567             p += claimed_len;
00568             
00569             if (*p != DBUS_TYPE_INVALID)
00570               return DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL;
00571             ++p;
00572 
00573             contained_type = _dbus_first_type_in_signature (&sig, 0);
00574             if (contained_type == DBUS_TYPE_INVALID)
00575               return DBUS_INVALID_VARIANT_SIGNATURE_EMPTY;
00576             
00577             contained_alignment = _dbus_type_get_alignment (contained_type);
00578             
00579             a = _DBUS_ALIGN_ADDRESS (p, contained_alignment);
00580             if (a > end)
00581               return DBUS_INVALID_NOT_ENOUGH_DATA;
00582             while (p != a)
00583               {
00584                 if (*p != '\0')
00585                   return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
00586                 ++p;
00587               }
00588 
00589             _dbus_type_reader_init_types_only (&sub, &sig, 0);
00590 
00591             _dbus_assert (_dbus_type_reader_get_current_type (&sub) != DBUS_TYPE_INVALID);
00592 
00593             validity = validate_body_helper (&sub, byte_order, FALSE, p, end, &p);
00594             if (validity != DBUS_VALID)
00595               return validity;
00596 
00597             if (_dbus_type_reader_next (&sub))
00598               return DBUS_INVALID_VARIANT_SIGNATURE_SPECIFIES_MULTIPLE_VALUES;
00599 
00600             _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_INVALID);
00601           }
00602           break;
00603 
00604         case DBUS_TYPE_DICT_ENTRY:
00605         case DBUS_TYPE_STRUCT:
00606           {
00607             DBusTypeReader sub;
00608             DBusValidity validity;
00609 
00610             a = _DBUS_ALIGN_ADDRESS (p, 8);
00611             if (a > end)
00612               return DBUS_INVALID_NOT_ENOUGH_DATA;
00613             while (p != a)
00614               {
00615                 if (*p != '\0')
00616                   return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
00617                 ++p;
00618               }
00619 
00620             _dbus_type_reader_recurse (reader, &sub);
00621 
00622             validity = validate_body_helper (&sub, byte_order, TRUE, p, end, &p);
00623             if (validity != DBUS_VALID)
00624               return validity;
00625           }
00626           break;
00627 
00628         default:
00629           _dbus_assert_not_reached ("invalid typecode in supposedly-validated signature");
00630           break;
00631         }
00632 
00633 #if 0
00634       _dbus_verbose ("   validated value of type %s type reader %p type_pos %d p %p end %p %d remain\n",
00635                      _dbus_type_to_string (current_type), reader, reader->type_pos, p, end,
00636                      (int) (end - p));
00637 #endif
00638 
00639       if (p > end)
00640         {
00641           _dbus_verbose ("not enough data!!! p = %p end = %p end-p = %d\n",
00642                          p, end, (int) (end - p));
00643           return DBUS_INVALID_NOT_ENOUGH_DATA;
00644         }
00645 
00646       if (walk_reader_to_end)
00647         _dbus_type_reader_next (reader);
00648       else
00649         break;
00650     }
00651 
00652   if (new_p)
00653     *new_p = p;
00654 
00655   return DBUS_VALID;
00656 }
00657 
00678 DBusValidity
00679 _dbus_validate_body_with_reason (const DBusString *expected_signature,
00680                                  int               expected_signature_start,
00681                                  int               byte_order,
00682                                  int              *bytes_remaining,
00683                                  const DBusString *value_str,
00684                                  int               value_pos,
00685                                  int               len)
00686 {
00687   DBusTypeReader reader;
00688   const unsigned char *p;
00689   const unsigned char *end;
00690   DBusValidity validity;
00691 
00692   _dbus_assert (len >= 0);
00693   _dbus_assert (value_pos >= 0);
00694   _dbus_assert (value_pos <= _dbus_string_get_length (value_str) - len);
00695 
00696   _dbus_verbose ("validating body from pos %d len %d sig '%s'\n",
00697                  value_pos, len, _dbus_string_get_const_data_len (expected_signature,
00698                                                                   expected_signature_start,
00699                                                                   0));
00700 
00701   _dbus_type_reader_init_types_only (&reader,
00702                                      expected_signature, expected_signature_start);
00703 
00704   p = _dbus_string_get_const_data_len (value_str, value_pos, len);
00705   end = p + len;
00706 
00707   validity = validate_body_helper (&reader, byte_order, TRUE, p, end, &p);
00708   if (validity != DBUS_VALID)
00709     return validity;
00710   
00711   if (bytes_remaining)
00712     {
00713       *bytes_remaining = end - p;
00714       return DBUS_VALID;
00715     }
00716   else if (p < end)
00717     return DBUS_INVALID_TOO_MUCH_DATA;
00718   else
00719     {
00720       _dbus_assert (p == end);
00721       return DBUS_VALID;
00722     }
00723 }
00724 
00729 #define VALID_INITIAL_NAME_CHARACTER(c)         \
00730   ( ((c) >= 'A' && (c) <= 'Z') ||               \
00731     ((c) >= 'a' && (c) <= 'z') ||               \
00732     ((c) == '_') )
00733 
00738 #define VALID_NAME_CHARACTER(c)                 \
00739   ( ((c) >= '0' && (c) <= '9') ||               \
00740     ((c) >= 'A' && (c) <= 'Z') ||               \
00741     ((c) >= 'a' && (c) <= 'z') ||               \
00742     ((c) == '_') )
00743 
00760 dbus_bool_t
00761 _dbus_validate_path (const DBusString  *str,
00762                      int                start,
00763                      int                len)
00764 {
00765   const unsigned char *s;
00766   const unsigned char *end;
00767   const unsigned char *last_slash;
00768 
00769   _dbus_assert (start >= 0);
00770   _dbus_assert (len >= 0);
00771   _dbus_assert (start <= _dbus_string_get_length (str));
00772   
00773   if (len > _dbus_string_get_length (str) - start)
00774     return FALSE;
00775 
00776   if (len == 0)
00777     return FALSE;
00778 
00779   s = _dbus_string_get_const_data (str) + start;
00780   end = s + len;
00781 
00782   if (*s != '/')
00783     return FALSE;
00784   last_slash = s;
00785   ++s;
00786 
00787   while (s != end)
00788     {
00789       if (*s == '/')
00790         {
00791           if ((s - last_slash) < 2)
00792             return FALSE; /* no empty path components allowed */
00793 
00794           last_slash = s;
00795         }
00796       else
00797         {
00798           if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
00799             return FALSE;
00800         }
00801 
00802       ++s;
00803     }
00804 
00805   if ((end - last_slash) < 2 &&
00806       len > 1)
00807     return FALSE; /* trailing slash not allowed unless the string is "/" */
00808 
00809   return TRUE;
00810 }
00811 
00825 dbus_bool_t
00826 _dbus_validate_interface (const DBusString  *str,
00827                           int                start,
00828                           int                len)
00829 {
00830   const unsigned char *s;
00831   const unsigned char *end;
00832   const unsigned char *iface;
00833   const unsigned char *last_dot;
00834 
00835   _dbus_assert (start >= 0);
00836   _dbus_assert (len >= 0);
00837   _dbus_assert (start <= _dbus_string_get_length (str));
00838 
00839   if (len > _dbus_string_get_length (str) - start)
00840     return FALSE;
00841 
00842   if (len > DBUS_MAXIMUM_NAME_LENGTH)
00843     return FALSE;
00844 
00845   if (len == 0)
00846     return FALSE;
00847 
00848   last_dot = NULL;
00849   iface = _dbus_string_get_const_data (str) + start;
00850   end = iface + len;
00851   s = iface;
00852 
00853   /* check special cases of first char so it doesn't have to be done
00854    * in the loop. Note we know len > 0
00855    */
00856   if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */
00857     return FALSE;
00858   else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s)))
00859     return FALSE;
00860   else
00861     ++s;
00862 
00863   while (s != end)
00864     {
00865       if (*s == '.')
00866         {
00867           if (_DBUS_UNLIKELY ((s + 1) == end))
00868             return FALSE;
00869           else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*(s + 1))))
00870             return FALSE;
00871           last_dot = s;
00872           ++s; /* we just validated the next char, so skip two */
00873         }
00874       else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
00875         {
00876           return FALSE;
00877         }
00878 
00879       ++s;
00880     }
00881 
00882   if (_DBUS_UNLIKELY (last_dot == NULL))
00883     return FALSE;
00884 
00885   return TRUE;
00886 }
00887 
00901 dbus_bool_t
00902 _dbus_validate_member (const DBusString  *str,
00903                        int                start,
00904                        int                len)
00905 {
00906   const unsigned char *s;
00907   const unsigned char *end;
00908   const unsigned char *member;
00909 
00910   _dbus_assert (start >= 0);
00911   _dbus_assert (len >= 0);
00912   _dbus_assert (start <= _dbus_string_get_length (str));
00913 
00914   if (len > _dbus_string_get_length (str) - start)
00915     return FALSE;
00916 
00917   if (len > DBUS_MAXIMUM_NAME_LENGTH)
00918     return FALSE;
00919 
00920   if (len == 0)
00921     return FALSE;
00922 
00923   member = _dbus_string_get_const_data (str) + start;
00924   end = member + len;
00925   s = member;
00926 
00927   /* check special cases of first char so it doesn't have to be done
00928    * in the loop. Note we know len > 0
00929    */
00930 
00931   if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s)))
00932     return FALSE;
00933   else
00934     ++s;
00935 
00936   while (s != end)
00937     {
00938       if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
00939         {
00940           return FALSE;
00941         }
00942 
00943       ++s;
00944     }
00945 
00946   return TRUE;
00947 }
00948 
00962 dbus_bool_t
00963 _dbus_validate_error_name (const DBusString  *str,
00964                            int                start,
00965                            int                len)
00966 {
00967   /* Same restrictions as interface name at the moment */
00968   return _dbus_validate_interface (str, start, len);
00969 }
00970 
00975 #define VALID_INITIAL_BUS_NAME_CHARACTER(c)         \
00976   ( ((c) >= 'A' && (c) <= 'Z') ||               \
00977     ((c) >= 'a' && (c) <= 'z') ||               \
00978     ((c) == '_') || ((c) == '-'))
00979 
00984 #define VALID_BUS_NAME_CHARACTER(c)                 \
00985   ( ((c) >= '0' && (c) <= '9') ||               \
00986     ((c) >= 'A' && (c) <= 'Z') ||               \
00987     ((c) >= 'a' && (c) <= 'z') ||               \
00988     ((c) == '_') || ((c) == '-'))
00989 
01003 dbus_bool_t
01004 _dbus_validate_bus_name (const DBusString  *str,
01005                          int                start,
01006                          int                len)
01007 {
01008   const unsigned char *s;
01009   const unsigned char *end;
01010   const unsigned char *iface;
01011   const unsigned char *last_dot;
01012 
01013   _dbus_assert (start >= 0);
01014   _dbus_assert (len >= 0);
01015   _dbus_assert (start <= _dbus_string_get_length (str));
01016 
01017   if (len > _dbus_string_get_length (str) - start)
01018     return FALSE;
01019 
01020   if (len > DBUS_MAXIMUM_NAME_LENGTH)
01021     return FALSE;
01022 
01023   if (len == 0)
01024     return FALSE;
01025 
01026   last_dot = NULL;
01027   iface = _dbus_string_get_const_data (str) + start;
01028   end = iface + len;
01029   s = iface;
01030 
01031   /* check special cases of first char so it doesn't have to be done
01032    * in the loop. Note we know len > 0
01033    */
01034   if (*s == ':')
01035   {
01036     /* unique name */
01037     ++s;
01038     while (s != end)
01039       {
01040         if (*s == '.')
01041           {
01042             if (_DBUS_UNLIKELY ((s + 1) == end))
01043               return FALSE;
01044             if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*(s + 1))))
01045               return FALSE;
01046             ++s; /* we just validated the next char, so skip two */
01047           }
01048         else if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*s)))
01049           {
01050             return FALSE;
01051           }
01052 
01053         ++s;
01054       }
01055 
01056     return TRUE;
01057   }
01058   else if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */
01059     return FALSE;
01060   else if (_DBUS_UNLIKELY (!VALID_INITIAL_BUS_NAME_CHARACTER (*s)))
01061     return FALSE;
01062   else
01063     ++s;
01064 
01065   while (s != end)
01066     {
01067       if (*s == '.')
01068         {
01069           if (_DBUS_UNLIKELY ((s + 1) == end))
01070             return FALSE;
01071           else if (_DBUS_UNLIKELY (!VALID_INITIAL_BUS_NAME_CHARACTER (*(s + 1))))
01072             return FALSE;
01073           last_dot = s;
01074           ++s; /* we just validated the next char, so skip two */
01075         }
01076       else if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*s)))
01077         {
01078           return FALSE;
01079         }
01080 
01081       ++s;
01082     }
01083 
01084   if (_DBUS_UNLIKELY (last_dot == NULL))
01085     return FALSE;
01086 
01087   return TRUE;
01088 }
01089 
01102 dbus_bool_t
01103 _dbus_validate_signature (const DBusString  *str,
01104                           int                start,
01105                           int                len)
01106 {
01107   _dbus_assert (start >= 0);
01108   _dbus_assert (start <= _dbus_string_get_length (str));
01109   _dbus_assert (len >= 0);
01110 
01111   if (len > _dbus_string_get_length (str) - start)
01112     return FALSE;
01113 
01114   return _dbus_validate_signature_with_reason (str, start, len) == DBUS_VALID;
01115 }
01116 
01118 DEFINE_DBUS_NAME_CHECK(path)
01120 DEFINE_DBUS_NAME_CHECK(interface)
01122 DEFINE_DBUS_NAME_CHECK(member)
01124 DEFINE_DBUS_NAME_CHECK(error_name)
01126 DEFINE_DBUS_NAME_CHECK(bus_name)
01128 DEFINE_DBUS_NAME_CHECK(signature)
01129 
01132 /* tests in dbus-marshal-validate-util.c */

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