LCOV - code coverage report
Current view: top level - libsystemd/sd-bus - bus-signature.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 65 71 91.5 %
Date: 2019-08-22 15:41:25 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <util.h>
       4             : 
       5             : #include "sd-bus.h"
       6             : 
       7             : #include "bus-signature.h"
       8             : #include "bus-type.h"
       9             : 
      10        5434 : static int signature_element_length_internal(
      11             :                 const char *s,
      12             :                 bool allow_dict_entry,
      13             :                 unsigned array_depth,
      14             :                 unsigned struct_depth,
      15             :                 size_t *l) {
      16             : 
      17             :         int r;
      18             : 
      19        5434 :         if (!s)
      20           0 :                 return -EINVAL;
      21             : 
      22        5434 :         assert(l);
      23             : 
      24        5434 :         if (bus_type_is_basic(*s) || *s == SD_BUS_TYPE_VARIANT) {
      25        4177 :                 *l = 1;
      26        4177 :                 return 0;
      27             :         }
      28             : 
      29        1257 :         if (*s == SD_BUS_TYPE_ARRAY) {
      30             :                 size_t t;
      31             : 
      32         321 :                 if (array_depth >= 32)
      33           1 :                         return -EINVAL;
      34             : 
      35         320 :                 r = signature_element_length_internal(s + 1, true, array_depth+1, struct_depth, &t);
      36         320 :                 if (r < 0)
      37          34 :                         return r;
      38             : 
      39         286 :                 *l = t + 1;
      40         286 :                 return 0;
      41             :         }
      42             : 
      43         936 :         if (*s == SD_BUS_TYPE_STRUCT_BEGIN) {
      44         565 :                 const char *p = s + 1;
      45             : 
      46         565 :                 if (struct_depth >= 32)
      47           1 :                         return -EINVAL;
      48             : 
      49        1688 :                 while (*p != SD_BUS_TYPE_STRUCT_END) {
      50             :                         size_t t;
      51             : 
      52        1163 :                         r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t);
      53        1163 :                         if (r < 0)
      54          39 :                                 return r;
      55             : 
      56        1124 :                         p += t;
      57             :                 }
      58             : 
      59         525 :                 if (p - s < 2)
      60             :                         /* D-Bus spec: Empty structures are not allowed; there
      61             :                          * must be at least one type code between the parentheses.
      62             :                          */
      63          10 :                         return -EINVAL;
      64             : 
      65         515 :                 *l = p - s + 1;
      66         515 :                 return 0;
      67             :         }
      68             : 
      69         371 :         if (*s == SD_BUS_TYPE_DICT_ENTRY_BEGIN && allow_dict_entry) {
      70         363 :                 const char *p = s + 1;
      71         363 :                 unsigned n = 0;
      72             : 
      73         363 :                 if (struct_depth >= 32)
      74           0 :                         return -EINVAL;
      75             : 
      76        1085 :                 while (*p != SD_BUS_TYPE_DICT_ENTRY_END) {
      77             :                         size_t t;
      78             : 
      79         723 :                         if (n == 0 && !bus_type_is_basic(*p))
      80           1 :                                 return -EINVAL;
      81             : 
      82         722 :                         r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t);
      83         722 :                         if (r < 0)
      84           0 :                                 return r;
      85             : 
      86         722 :                         p += t;
      87         722 :                         n++;
      88             :                 }
      89             : 
      90         362 :                 if (n != 2)
      91           3 :                         return -EINVAL;
      92             : 
      93         359 :                 *l = p - s + 1;
      94         359 :                 return 0;
      95             :         }
      96             : 
      97           8 :         return -EINVAL;
      98             : }
      99             : 
     100        1635 : int signature_element_length(const char *s, size_t *l) {
     101        1635 :         return signature_element_length_internal(s, true, 0, 0, l);
     102             : }
     103             : 
     104         466 : bool signature_is_single(const char *s, bool allow_dict_entry) {
     105             :         int r;
     106             :         size_t t;
     107             : 
     108         466 :         if (!s)
     109           0 :                 return false;
     110             : 
     111         466 :         r = signature_element_length_internal(s, allow_dict_entry, 0, 0, &t);
     112         466 :         if (r < 0)
     113          15 :                 return false;
     114             : 
     115         451 :         return s[t] == 0;
     116             : }
     117             : 
     118         133 : bool signature_is_pair(const char *s) {
     119             : 
     120         133 :         if (!s)
     121           0 :                 return false;
     122             : 
     123         133 :         if (!bus_type_is_basic(*s))
     124           3 :                 return false;
     125             : 
     126         130 :         return signature_is_single(s + 1, false);
     127             : }
     128             : 
     129         947 : bool signature_is_valid(const char *s, bool allow_dict_entry) {
     130             :         const char *p;
     131             :         int r;
     132             : 
     133         947 :         if (!s)
     134           0 :                 return false;
     135             : 
     136         947 :         p = s;
     137        2071 :         while (*p) {
     138             :                 size_t t;
     139             : 
     140        1128 :                 r = signature_element_length_internal(p, allow_dict_entry, 0, 0, &t);
     141        1128 :                 if (r < 0)
     142           4 :                         return false;
     143             : 
     144        1124 :                 p += t;
     145             :         }
     146             : 
     147         943 :         return p - s <= SD_BUS_MAXIMUM_SIGNATURE_LENGTH;
     148             : }

Generated by: LCOV version 1.14