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                 alignment = _dbus_type_get_alignment (array_elem_type);
00378                 p = _DBUS_ALIGN_ADDRESS (p, alignment);
00379               }
00380 
00381             if (claimed_len > (unsigned long) (end - p))
00382               return DBUS_INVALID_LENGTH_OUT_OF_BOUNDS;
00383 
00384             if (current_type == DBUS_TYPE_OBJECT_PATH)
00385               {
00386                 DBusString str;
00387                 _dbus_string_init_const_len (&str, p, claimed_len);
00388                 if (!_dbus_validate_path (&str, 0,
00389                                           _dbus_string_get_length (&str)))
00390                   return DBUS_INVALID_BAD_PATH;
00391 
00392                 p += claimed_len;
00393               }
00394             else if (current_type == DBUS_TYPE_STRING)
00395               {
00396                 DBusString str;
00397                 _dbus_string_init_const_len (&str, p, claimed_len);
00398                 if (!_dbus_string_validate_utf8 (&str, 0,
00399                                                  _dbus_string_get_length (&str)))
00400                   return DBUS_INVALID_BAD_UTF8_IN_STRING;
00401 
00402                 p += claimed_len;
00403               }
00404             else if (current_type == DBUS_TYPE_ARRAY && claimed_len > 0)
00405               {
00406                 DBusTypeReader sub;
00407                 DBusValidity validity;
00408                 const unsigned char *array_end;
00409 
00410                 if (claimed_len > DBUS_MAXIMUM_ARRAY_LENGTH)
00411                   return DBUS_INVALID_ARRAY_LENGTH_EXCEEDS_MAXIMUM;
00412                 
00413                 /* Remember that the reader is types only, so we can't
00414                  * use it to iterate over elements. It stays the same
00415                  * for all elements.
00416                  */
00417                 _dbus_type_reader_recurse (reader, &sub);
00418 
00419                 array_end = p + claimed_len;
00420 
00421                 while (p < array_end)
00422                   {
00423                     /* FIXME we are calling a function per array element! very bad
00424                      * need if (dbus_type_is_fixed(elem_type)) here to just skip
00425                      * big blocks of ints/bytes/etc.
00426                      */                     
00427                     
00428                     validity = validate_body_helper (&sub, byte_order, FALSE, p, end, &p);
00429                     if (validity != DBUS_VALID)
00430                       return validity;
00431                   }
00432 
00433                 if (p != array_end)
00434                   return DBUS_INVALID_ARRAY_LENGTH_INCORRECT;
00435               }
00436 
00437             /* check nul termination */
00438             if (current_type != DBUS_TYPE_ARRAY)
00439               {
00440                 if (p == end)
00441                   return DBUS_INVALID_NOT_ENOUGH_DATA;
00442 
00443                 if (*p != '\0')
00444                   return DBUS_INVALID_STRING_MISSING_NUL;
00445                 ++p;
00446               }
00447           }
00448           break;
00449 
00450         case DBUS_TYPE_SIGNATURE:
00451           {
00452             dbus_uint32_t claimed_len;
00453             DBusString str;
00454             DBusValidity validity;
00455 
00456             claimed_len = *p;
00457             ++p;
00458 
00459             /* 1 is for nul termination */
00460             if (claimed_len + 1 > (unsigned long) (end - p))
00461               return DBUS_INVALID_SIGNATURE_LENGTH_OUT_OF_BOUNDS;
00462 
00463             _dbus_string_init_const_len (&str, p, claimed_len);
00464             validity =
00465               _dbus_validate_signature_with_reason (&str, 0,
00466                                                     _dbus_string_get_length (&str));
00467 
00468             if (validity != DBUS_VALID)
00469               return validity;
00470 
00471             p += claimed_len;
00472 
00473             _dbus_assert (p < end);
00474             if (*p != DBUS_TYPE_INVALID)
00475               return DBUS_INVALID_SIGNATURE_MISSING_NUL;
00476 
00477             ++p;
00478 
00479             _dbus_verbose ("p = %p end = %p claimed_len %u\n", p, end, claimed_len);
00480           }
00481           break;
00482 
00483         case DBUS_TYPE_VARIANT:
00484           {
00485             /* 1 byte sig len, sig typecodes, align to
00486              * contained-type-boundary, values.
00487              */
00488 
00489             /* In addition to normal signature validation, we need to be sure
00490              * the signature contains only a single (possibly container) type.
00491              */
00492             dbus_uint32_t claimed_len;
00493             DBusString sig;
00494             DBusTypeReader sub;
00495             DBusValidity validity;
00496             int contained_alignment;
00497             int contained_type;
00498             DBusValidity reason;
00499 
00500             claimed_len = *p;
00501             ++p;
00502 
00503             /* + 1 for nul */
00504             if (claimed_len + 1 > (unsigned long) (end - p))
00505               return DBUS_INVALID_VARIANT_SIGNATURE_LENGTH_OUT_OF_BOUNDS;
00506 
00507             _dbus_string_init_const_len (&sig, p, claimed_len);
00508             reason = _dbus_validate_signature_with_reason (&sig, 0,
00509                                            _dbus_string_get_length (&sig));
00510             if (!(reason == DBUS_VALID))
00511               {
00512                 if (reason == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
00513                   return reason;
00514                 else 
00515                   return DBUS_INVALID_VARIANT_SIGNATURE_BAD;
00516               }
00517 
00518             p += claimed_len;
00519             
00520             if (*p != DBUS_TYPE_INVALID)
00521               return DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL;
00522             ++p;
00523 
00524             contained_type = _dbus_first_type_in_signature (&sig, 0);
00525             if (contained_type == DBUS_TYPE_INVALID)
00526               return DBUS_INVALID_VARIANT_SIGNATURE_EMPTY;
00527             
00528             contained_alignment = _dbus_type_get_alignment (contained_type);
00529             
00530             a = _DBUS_ALIGN_ADDRESS (p, contained_alignment);
00531             if (a > end)
00532               return DBUS_INVALID_NOT_ENOUGH_DATA;
00533             while (p != a)
00534               {
00535                 if (*p != '\0')
00536                   return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
00537                 ++p;
00538               }
00539 
00540             _dbus_type_reader_init_types_only (&sub, &sig, 0);
00541 
00542             _dbus_assert (_dbus_type_reader_get_current_type (&sub) != DBUS_TYPE_INVALID);
00543 
00544             validity = validate_body_helper (&sub, byte_order, FALSE, p, end, &p);
00545             if (validity != DBUS_VALID)
00546               return validity;
00547 
00548             if (_dbus_type_reader_next (&sub))
00549               return DBUS_INVALID_VARIANT_SIGNATURE_SPECIFIES_MULTIPLE_VALUES;
00550 
00551             _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_INVALID);
00552           }
00553           break;
00554 
00555         case DBUS_TYPE_DICT_ENTRY:
00556         case DBUS_TYPE_STRUCT:
00557           {
00558             DBusTypeReader sub;
00559             DBusValidity validity;
00560 
00561             a = _DBUS_ALIGN_ADDRESS (p, 8);
00562             if (a > end)
00563               return DBUS_INVALID_NOT_ENOUGH_DATA;
00564             while (p != a)
00565               {
00566                 if (*p != '\0')
00567                   return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
00568                 ++p;
00569               }
00570 
00571             _dbus_type_reader_recurse (reader, &sub);
00572 
00573             validity = validate_body_helper (&sub, byte_order, TRUE, p, end, &p);
00574             if (validity != DBUS_VALID)
00575               return validity;
00576           }
00577           break;
00578 
00579         default:
00580           _dbus_assert_not_reached ("invalid typecode in supposedly-validated signature");
00581           break;
00582         }
00583 
00584 #if 0
00585       _dbus_verbose ("   validated value of type %s type reader %p type_pos %d p %p end %p %d remain\n",
00586                      _dbus_type_to_string (current_type), reader, reader->type_pos, p, end,
00587                      (int) (end - p));
00588 #endif
00589 
00590       if (p > end)
00591         {
00592           _dbus_verbose ("not enough data!!! p = %p end = %p end-p = %d\n",
00593                          p, end, (int) (end - p));
00594           return DBUS_INVALID_NOT_ENOUGH_DATA;
00595         }
00596 
00597       if (walk_reader_to_end)
00598         _dbus_type_reader_next (reader);
00599       else
00600         break;
00601     }
00602 
00603   if (new_p)
00604     *new_p = p;
00605 
00606   return DBUS_VALID;
00607 }
00608 
00629 DBusValidity
00630 _dbus_validate_body_with_reason (const DBusString *expected_signature,
00631                                  int               expected_signature_start,
00632                                  int               byte_order,
00633                                  int              *bytes_remaining,
00634                                  const DBusString *value_str,
00635                                  int               value_pos,
00636                                  int               len)
00637 {
00638   DBusTypeReader reader;
00639   const unsigned char *p;
00640   const unsigned char *end;
00641   DBusValidity validity;
00642 
00643   _dbus_assert (len >= 0);
00644   _dbus_assert (value_pos >= 0);
00645   _dbus_assert (value_pos <= _dbus_string_get_length (value_str) - len);
00646 
00647   _dbus_verbose ("validating body from pos %d len %d sig '%s'\n",
00648                  value_pos, len, _dbus_string_get_const_data_len (expected_signature,
00649                                                                   expected_signature_start,
00650                                                                   0));
00651 
00652   _dbus_type_reader_init_types_only (&reader,
00653                                      expected_signature, expected_signature_start);
00654 
00655   p = _dbus_string_get_const_data_len (value_str, value_pos, len);
00656   end = p + len;
00657 
00658   validity = validate_body_helper (&reader, byte_order, TRUE, p, end, &p);
00659   if (validity != DBUS_VALID)
00660     return validity;
00661   
00662   if (bytes_remaining)
00663     {
00664       *bytes_remaining = end - p;
00665       return DBUS_VALID;
00666     }
00667   else if (p < end)
00668     return DBUS_INVALID_TOO_MUCH_DATA;
00669   else
00670     {
00671       _dbus_assert (p == end);
00672       return DBUS_VALID;
00673     }
00674 }
00675 
00680 #define VALID_INITIAL_NAME_CHARACTER(c)         \
00681   ( ((c) >= 'A' && (c) <= 'Z') ||               \
00682     ((c) >= 'a' && (c) <= 'z') ||               \
00683     ((c) == '_') )
00684 
00689 #define VALID_NAME_CHARACTER(c)                 \
00690   ( ((c) >= '0' && (c) <= '9') ||               \
00691     ((c) >= 'A' && (c) <= 'Z') ||               \
00692     ((c) >= 'a' && (c) <= 'z') ||               \
00693     ((c) == '_') )
00694 
00711 dbus_bool_t
00712 _dbus_validate_path (const DBusString  *str,
00713                      int                start,
00714                      int                len)
00715 {
00716   const unsigned char *s;
00717   const unsigned char *end;
00718   const unsigned char *last_slash;
00719 
00720   _dbus_assert (start >= 0);
00721   _dbus_assert (len >= 0);
00722   _dbus_assert (start <= _dbus_string_get_length (str));
00723   
00724   if (len > _dbus_string_get_length (str) - start)
00725     return FALSE;
00726 
00727   if (len == 0)
00728     return FALSE;
00729 
00730   s = _dbus_string_get_const_data (str) + start;
00731   end = s + len;
00732 
00733   if (*s != '/')
00734     return FALSE;
00735   last_slash = s;
00736   ++s;
00737 
00738   while (s != end)
00739     {
00740       if (*s == '/')
00741         {
00742           if ((s - last_slash) < 2)
00743             return FALSE; /* no empty path components allowed */
00744 
00745           last_slash = s;
00746         }
00747       else
00748         {
00749           if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
00750             return FALSE;
00751         }
00752 
00753       ++s;
00754     }
00755 
00756   if ((end - last_slash) < 2 &&
00757       len > 1)
00758     return FALSE; /* trailing slash not allowed unless the string is "/" */
00759 
00760   return TRUE;
00761 }
00762 
00776 dbus_bool_t
00777 _dbus_validate_interface (const DBusString  *str,
00778                           int                start,
00779                           int                len)
00780 {
00781   const unsigned char *s;
00782   const unsigned char *end;
00783   const unsigned char *iface;
00784   const unsigned char *last_dot;
00785 
00786   _dbus_assert (start >= 0);
00787   _dbus_assert (len >= 0);
00788   _dbus_assert (start <= _dbus_string_get_length (str));
00789 
00790   if (len > _dbus_string_get_length (str) - start)
00791     return FALSE;
00792 
00793   if (len > DBUS_MAXIMUM_NAME_LENGTH)
00794     return FALSE;
00795 
00796   if (len == 0)
00797     return FALSE;
00798 
00799   last_dot = NULL;
00800   iface = _dbus_string_get_const_data (str) + start;
00801   end = iface + len;
00802   s = iface;
00803 
00804   /* check special cases of first char so it doesn't have to be done
00805    * in the loop. Note we know len > 0
00806    */
00807   if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */
00808     return FALSE;
00809   else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s)))
00810     return FALSE;
00811   else
00812     ++s;
00813 
00814   while (s != end)
00815     {
00816       if (*s == '.')
00817         {
00818           if (_DBUS_UNLIKELY ((s + 1) == end))
00819             return FALSE;
00820           else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*(s + 1))))
00821             return FALSE;
00822           last_dot = s;
00823           ++s; /* we just validated the next char, so skip two */
00824         }
00825       else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
00826         {
00827           return FALSE;
00828         }
00829 
00830       ++s;
00831     }
00832 
00833   if (_DBUS_UNLIKELY (last_dot == NULL))
00834     return FALSE;
00835 
00836   return TRUE;
00837 }
00838 
00852 dbus_bool_t
00853 _dbus_validate_member (const DBusString  *str,
00854                        int                start,
00855                        int                len)
00856 {
00857   const unsigned char *s;
00858   const unsigned char *end;
00859   const unsigned char *member;
00860 
00861   _dbus_assert (start >= 0);
00862   _dbus_assert (len >= 0);
00863   _dbus_assert (start <= _dbus_string_get_length (str));
00864 
00865   if (len > _dbus_string_get_length (str) - start)
00866     return FALSE;
00867 
00868   if (len > DBUS_MAXIMUM_NAME_LENGTH)
00869     return FALSE;
00870 
00871   if (len == 0)
00872     return FALSE;
00873 
00874   member = _dbus_string_get_const_data (str) + start;
00875   end = member + len;
00876   s = member;
00877 
00878   /* check special cases of first char so it doesn't have to be done
00879    * in the loop. Note we know len > 0
00880    */
00881 
00882   if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s)))
00883     return FALSE;
00884   else
00885     ++s;
00886 
00887   while (s != end)
00888     {
00889       if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
00890         {
00891           return FALSE;
00892         }
00893 
00894       ++s;
00895     }
00896 
00897   return TRUE;
00898 }
00899 
00913 dbus_bool_t
00914 _dbus_validate_error_name (const DBusString  *str,
00915                            int                start,
00916                            int                len)
00917 {
00918   /* Same restrictions as interface name at the moment */
00919   return _dbus_validate_interface (str, start, len);
00920 }
00921 
00926 #define VALID_INITIAL_BUS_NAME_CHARACTER(c)         \
00927   ( ((c) >= 'A' && (c) <= 'Z') ||               \
00928     ((c) >= 'a' && (c) <= 'z') ||               \
00929     ((c) == '_') || ((c) == '-'))
00930 
00935 #define VALID_BUS_NAME_CHARACTER(c)                 \
00936   ( ((c) >= '0' && (c) <= '9') ||               \
00937     ((c) >= 'A' && (c) <= 'Z') ||               \
00938     ((c) >= 'a' && (c) <= 'z') ||               \
00939     ((c) == '_') || ((c) == '-'))
00940 
00954 dbus_bool_t
00955 _dbus_validate_bus_name (const DBusString  *str,
00956                          int                start,
00957                          int                len)
00958 {
00959   const unsigned char *s;
00960   const unsigned char *end;
00961   const unsigned char *iface;
00962   const unsigned char *last_dot;
00963 
00964   _dbus_assert (start >= 0);
00965   _dbus_assert (len >= 0);
00966   _dbus_assert (start <= _dbus_string_get_length (str));
00967 
00968   if (len > _dbus_string_get_length (str) - start)
00969     return FALSE;
00970 
00971   if (len > DBUS_MAXIMUM_NAME_LENGTH)
00972     return FALSE;
00973 
00974   if (len == 0)
00975     return FALSE;
00976 
00977   last_dot = NULL;
00978   iface = _dbus_string_get_const_data (str) + start;
00979   end = iface + len;
00980   s = iface;
00981 
00982   /* check special cases of first char so it doesn't have to be done
00983    * in the loop. Note we know len > 0
00984    */
00985   if (*s == ':')
00986   {
00987     /* unique name */
00988     ++s;
00989     while (s != end)
00990       {
00991         if (*s == '.')
00992           {
00993             if (_DBUS_UNLIKELY ((s + 1) == end))
00994               return FALSE;
00995             if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*(s + 1))))
00996               return FALSE;
00997             ++s; /* we just validated the next char, so skip two */
00998           }
00999         else if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*s)))
01000           {
01001             return FALSE;
01002           }
01003 
01004         ++s;
01005       }
01006 
01007     return TRUE;
01008   }
01009   else if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */
01010     return FALSE;
01011   else if (_DBUS_UNLIKELY (!VALID_INITIAL_BUS_NAME_CHARACTER (*s)))
01012     return FALSE;
01013   else
01014     ++s;
01015 
01016   while (s != end)
01017     {
01018       if (*s == '.')
01019         {
01020           if (_DBUS_UNLIKELY ((s + 1) == end))
01021             return FALSE;
01022           else if (_DBUS_UNLIKELY (!VALID_INITIAL_BUS_NAME_CHARACTER (*(s + 1))))
01023             return FALSE;
01024           last_dot = s;
01025           ++s; /* we just validated the next char, so skip two */
01026         }
01027       else if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*s)))
01028         {
01029           return FALSE;
01030         }
01031 
01032       ++s;
01033     }
01034 
01035   if (_DBUS_UNLIKELY (last_dot == NULL))
01036     return FALSE;
01037 
01038   return TRUE;
01039 }
01040 
01053 dbus_bool_t
01054 _dbus_validate_signature (const DBusString  *str,
01055                           int                start,
01056                           int                len)
01057 {
01058   _dbus_assert (start >= 0);
01059   _dbus_assert (start <= _dbus_string_get_length (str));
01060   _dbus_assert (len >= 0);
01061 
01062   if (len > _dbus_string_get_length (str) - start)
01063     return FALSE;
01064 
01065   return _dbus_validate_signature_with_reason (str, start, len) == DBUS_VALID;
01066 }
01067 
01069 DEFINE_DBUS_NAME_CHECK(path)
01071 DEFINE_DBUS_NAME_CHECK(interface)
01073 DEFINE_DBUS_NAME_CHECK(member)
01075 DEFINE_DBUS_NAME_CHECK(error_name)
01077 DEFINE_DBUS_NAME_CHECK(bus_name)
01079 DEFINE_DBUS_NAME_CHECK(signature)
01080 
01083 /* tests in dbus-marshal-validate-util.c */

Generated on Thu Jan 22 16:37:05 2009 for D-Bus by  doxygen 1.5.1