LCOV - code coverage report
Current view: top level - libsystemd/sd-bus - bus-internal.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 143 179 79.9 %
Date: 2019-08-23 13:36:53 Functions: 15 15 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 147 216 68.1 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include "alloc-util.h"
       4                 :            : #include "bus-internal.h"
       5                 :            : #include "bus-message.h"
       6                 :            : #include "hexdecoct.h"
       7                 :            : #include "string-util.h"
       8                 :            : 
       9                 :       1443 : bool object_path_is_valid(const char *p) {
      10                 :            :         const char *q;
      11                 :            :         bool slash;
      12                 :            : 
      13         [ -  + ]:       1443 :         if (!p)
      14                 :          0 :                 return false;
      15                 :            : 
      16         [ +  + ]:       1443 :         if (p[0] != '/')
      17                 :         12 :                 return false;
      18                 :            : 
      19         [ +  + ]:       1431 :         if (p[1] == 0)
      20                 :        192 :                 return true;
      21                 :            : 
      22         [ +  + ]:      16167 :         for (slash = true, q = p+1; *q; q++)
      23         [ +  + ]:      14944 :                 if (*q == '/') {
      24         [ +  + ]:       1730 :                         if (slash)
      25                 :         12 :                                 return false;
      26                 :            : 
      27                 :       1718 :                         slash = true;
      28                 :            :                 } else {
      29                 :            :                         bool good;
      30                 :            : 
      31                 :      13214 :                         good =
      32         [ -  + ]:      12360 :                                 (*q >= 'a' && *q <= 'z') ||
      33   [ +  +  +  + ]:        854 :                                 (*q >= 'A' && *q <= 'Z') ||
      34   [ +  +  +  +  :      26500 :                                 (*q >= '0' && *q <= '9') ||
                   +  + ]
      35         [ +  + ]:         72 :                                 *q == '_';
      36                 :            : 
      37         [ +  + ]:      13214 :                         if (!good)
      38                 :          4 :                                 return false;
      39                 :            : 
      40                 :      13210 :                         slash = false;
      41                 :            :                 }
      42                 :            : 
      43         [ +  + ]:       1223 :         if (slash)
      44                 :          8 :                 return false;
      45                 :            : 
      46                 :       1215 :         return (q - p) <= BUS_PATH_SIZE_MAX;
      47                 :            : }
      48                 :            : 
      49                 :        156 : char* object_path_startswith(const char *a, const char *b) {
      50                 :            :         const char *p;
      51                 :            : 
      52         [ +  - ]:        156 :         if (!object_path_is_valid(a) ||
      53         [ +  + ]:        156 :             !object_path_is_valid(b))
      54                 :          4 :                 return NULL;
      55                 :            : 
      56         [ +  + ]:        152 :         if (streq(b, "/"))
      57                 :         24 :                 return (char*) a + 1;
      58                 :            : 
      59                 :        128 :         p = startswith(a, b);
      60         [ +  + ]:        128 :         if (!p)
      61                 :         16 :                 return NULL;
      62                 :            : 
      63         [ +  + ]:        112 :         if (*p == 0)
      64                 :         16 :                 return (char*) p;
      65                 :            : 
      66         [ +  - ]:         96 :         if (*p == '/')
      67                 :         96 :                 return (char*) p + 1;
      68                 :            : 
      69                 :          0 :         return NULL;
      70                 :            : }
      71                 :            : 
      72                 :        911 : bool interface_name_is_valid(const char *p) {
      73                 :            :         const char *q;
      74                 :        911 :         bool dot, found_dot = false;
      75                 :            : 
      76         [ -  + ]:        911 :         if (isempty(p))
      77                 :          0 :                 return false;
      78                 :            : 
      79         [ +  + ]:      24323 :         for (dot = true, q = p; *q; q++)
      80         [ +  + ]:      23412 :                 if (*q == '.') {
      81         [ -  + ]:       2330 :                         if (dot)
      82                 :          0 :                                 return false;
      83                 :            : 
      84                 :       2330 :                         found_dot = dot = true;
      85                 :            :                 } else {
      86                 :            :                         bool good;
      87                 :            : 
      88                 :      21082 :                         good =
      89         [ -  + ]:      19444 :                                 (*q >= 'a' && *q <= 'z') ||
      90   [ +  +  -  + ]:       1638 :                                 (*q >= 'A' && *q <= 'Z') ||
      91   [ +  +  +  -  :      42164 :                                 (!dot && *q >= '0' && *q <= '9') ||
             +  -  -  + ]
      92         [ #  # ]:          0 :                                 *q == '_';
      93                 :            : 
      94         [ -  + ]:      21082 :                         if (!good)
      95                 :          0 :                                 return false;
      96                 :            : 
      97                 :      21082 :                         dot = false;
      98                 :            :                 }
      99                 :            : 
     100         [ -  + ]:        911 :         if (q - p > SD_BUS_MAXIMUM_NAME_LENGTH)
     101                 :          0 :                 return false;
     102                 :            : 
     103         [ -  + ]:        911 :         if (dot)
     104                 :          0 :                 return false;
     105                 :            : 
     106         [ -  + ]:        911 :         if (!found_dot)
     107                 :          0 :                 return false;
     108                 :            : 
     109                 :        911 :         return true;
     110                 :            : }
     111                 :            : 
     112                 :       1152 : bool service_name_is_valid(const char *p) {
     113                 :            :         const char *q;
     114                 :       1152 :         bool dot, found_dot = false, unique;
     115                 :            : 
     116         [ -  + ]:       1152 :         if (isempty(p))
     117                 :          0 :                 return false;
     118                 :            : 
     119                 :       1152 :         unique = p[0] == ':';
     120                 :            : 
     121   [ +  +  +  + ]:      22016 :         for (dot = true, q = unique ? p+1 : p; *q; q++)
     122         [ +  + ]:      20864 :                 if (*q == '.') {
     123         [ -  + ]:       2294 :                         if (dot)
     124                 :          0 :                                 return false;
     125                 :            : 
     126                 :       2294 :                         found_dot = dot = true;
     127                 :            :                 } else {
     128                 :            :                         bool good;
     129                 :            : 
     130                 :      18570 :                         good =
     131         [ -  + ]:      15692 :                                 (*q >= 'a' && *q <= 'z') ||
     132   [ +  +  -  + ]:       2878 :                                 (*q >= 'A' && *q <= 'Z') ||
     133   [ +  +  +  +  :      37148 :                                 ((!dot || unique) && *q >= '0' && *q <= '9') ||
          +  -  +  +  -  
                      + ]
     134   [ +  -  +  - ]:          8 :                                 IN_SET(*q, '_', '-');
     135                 :            : 
     136         [ -  + ]:      18570 :                         if (!good)
     137                 :          0 :                                 return false;
     138                 :            : 
     139                 :      18570 :                         dot = false;
     140                 :            :                 }
     141                 :            : 
     142         [ -  + ]:       1152 :         if (q - p > SD_BUS_MAXIMUM_NAME_LENGTH)
     143                 :          0 :                 return false;
     144                 :            : 
     145         [ -  + ]:       1152 :         if (dot)
     146                 :          0 :                 return false;
     147                 :            : 
     148         [ -  + ]:       1152 :         if (!found_dot)
     149                 :          0 :                 return false;
     150                 :            : 
     151                 :       1152 :         return true;
     152                 :            : }
     153                 :            : 
     154                 :       1407 : bool member_name_is_valid(const char *p) {
     155                 :            :         const char *q;
     156                 :            : 
     157         [ -  + ]:       1407 :         if (isempty(p))
     158                 :          0 :                 return false;
     159                 :            : 
     160         [ +  + ]:      15063 :         for (q = p; *q; q++) {
     161                 :            :                 bool good;
     162                 :            : 
     163                 :      13656 :                 good =
     164         [ -  + ]:      11398 :                         (*q >= 'a' && *q <= 'z') ||
     165   [ +  +  +  + ]:       2258 :                         (*q >= 'A' && *q <= 'Z') ||
     166   [ +  +  +  -  :      27344 :                         (*q >= '0' && *q <= '9') ||
                   +  + ]
     167         [ +  - ]:         32 :                         *q == '_';
     168                 :            : 
     169         [ -  + ]:      13656 :                 if (!good)
     170                 :          0 :                         return false;
     171                 :            :         }
     172                 :            : 
     173         [ -  + ]:       1407 :         if (q - p > SD_BUS_MAXIMUM_NAME_LENGTH)
     174                 :          0 :                 return false;
     175                 :            : 
     176                 :       1407 :         return true;
     177                 :            : }
     178                 :            : 
     179                 :            : /*
     180                 :            :  * Complex pattern match
     181                 :            :  * This checks whether @a is a 'complex-prefix' of @b, or @b is a
     182                 :            :  * 'complex-prefix' of @a, based on strings that consist of labels with @c as
     183                 :            :  * separator. This function returns true if:
     184                 :            :  *   - both strings are equal
     185                 :            :  *   - either is a prefix of the other and ends with @c
     186                 :            :  * The second rule makes sure that either string needs to be fully included in
     187                 :            :  * the other, and the string which is considered the prefix needs to end with a
     188                 :            :  * separator.
     189                 :            :  */
     190                 :         88 : static bool complex_pattern_check(char c, const char *a, const char *b) {
     191                 :         88 :         bool separator = false;
     192                 :            : 
     193   [ -  +  #  # ]:         88 :         if (!a && !b)
     194                 :          0 :                 return true;
     195                 :            : 
     196   [ +  -  -  + ]:         88 :         if (!a || !b)
     197                 :          0 :                 return false;
     198                 :            : 
     199                 :            :         for (;;) {
     200         [ +  + ]:        480 :                 if (*a != *b)
     201   [ +  +  +  +  :         64 :                         return (separator && (*a == 0 || *b == 0));
                   +  - ]
     202                 :            : 
     203         [ +  + ]:        416 :                 if (*a == 0)
     204                 :         24 :                         return true;
     205                 :            : 
     206                 :        392 :                 separator = *a == c;
     207                 :            : 
     208                 :        392 :                 a++, b++;
     209                 :            :         }
     210                 :            : }
     211                 :            : 
     212                 :         40 : bool namespace_complex_pattern(const char *pattern, const char *value) {
     213                 :         40 :         return complex_pattern_check('.', pattern, value);
     214                 :            : }
     215                 :            : 
     216                 :         48 : bool path_complex_pattern(const char *pattern, const char *value) {
     217                 :         48 :         return complex_pattern_check('/', pattern, value);
     218                 :            : }
     219                 :            : 
     220                 :            : /*
     221                 :            :  * Simple pattern match
     222                 :            :  * This checks whether @a is a 'simple-prefix' of @b, based on strings that
     223                 :            :  * consist of labels with @c as separator. This function returns true, if:
     224                 :            :  *   - if @a and @b are equal
     225                 :            :  *   - if @a is a prefix of @b, and the first following character in @b (or the
     226                 :            :  *     last character in @a) is @c
     227                 :            :  * The second rule basically makes sure that if @a is a prefix of @b, then @b
     228                 :            :  * must follow with a new label separated by @c. It cannot extend the label.
     229                 :            :  */
     230                 :         64 : static bool simple_pattern_check(char c, const char *a, const char *b) {
     231                 :         64 :         bool separator = false;
     232                 :            : 
     233   [ -  +  #  # ]:         64 :         if (!a && !b)
     234                 :          0 :                 return true;
     235                 :            : 
     236   [ +  -  -  + ]:         64 :         if (!a || !b)
     237                 :          0 :                 return false;
     238                 :            : 
     239                 :            :         for (;;) {
     240         [ +  + ]:        340 :                 if (*a != *b)
     241   [ +  +  +  +  :         52 :                         return *a == 0 && (*b == c || separator);
                   +  + ]
     242                 :            : 
     243         [ +  + ]:        288 :                 if (*a == 0)
     244                 :         12 :                         return true;
     245                 :            : 
     246                 :        276 :                 separator = *a == c;
     247                 :            : 
     248                 :        276 :                 a++, b++;
     249                 :            :         }
     250                 :            : }
     251                 :            : 
     252                 :         44 : bool namespace_simple_pattern(const char *pattern, const char *value) {
     253                 :         44 :         return simple_pattern_check('.', pattern, value);
     254                 :            : }
     255                 :            : 
     256                 :         20 : bool path_simple_pattern(const char *pattern, const char *value) {
     257                 :         20 :         return simple_pattern_check('/', pattern, value);
     258                 :            : }
     259                 :            : 
     260                 :        136 : int bus_message_type_from_string(const char *s, uint8_t *u) {
     261         [ +  + ]:        136 :         if (streq(s, "signal"))
     262                 :        132 :                 *u = SD_BUS_MESSAGE_SIGNAL;
     263         [ +  - ]:          4 :         else if (streq(s, "method_call"))
     264                 :          4 :                 *u = SD_BUS_MESSAGE_METHOD_CALL;
     265         [ #  # ]:          0 :         else if (streq(s, "error"))
     266                 :          0 :                 *u = SD_BUS_MESSAGE_METHOD_ERROR;
     267         [ #  # ]:          0 :         else if (streq(s, "method_return"))
     268                 :          0 :                 *u = SD_BUS_MESSAGE_METHOD_RETURN;
     269                 :            :         else
     270                 :          0 :                 return -EINVAL;
     271                 :            : 
     272                 :        136 :         return 0;
     273                 :            : }
     274                 :            : 
     275                 :        156 : const char *bus_message_type_to_string(uint8_t u) {
     276         [ +  + ]:        156 :         if (u == SD_BUS_MESSAGE_SIGNAL)
     277                 :         24 :                 return "signal";
     278         [ +  + ]:        132 :         else if (u == SD_BUS_MESSAGE_METHOD_CALL)
     279                 :         80 :                 return "method_call";
     280         [ -  + ]:         52 :         else if (u == SD_BUS_MESSAGE_METHOD_ERROR)
     281                 :          0 :                 return "error";
     282         [ +  - ]:         52 :         else if (u == SD_BUS_MESSAGE_METHOD_RETURN)
     283                 :         52 :                  return "method_return";
     284                 :            :         else
     285                 :          0 :                 return NULL;
     286                 :            : }
     287                 :            : 
     288                 :         28 : char *bus_address_escape(const char *v) {
     289                 :            :         const char *a;
     290                 :            :         char *r, *b;
     291                 :            : 
     292                 :         28 :         r = new(char, strlen(v)*3+1);
     293         [ -  + ]:         28 :         if (!r)
     294                 :          0 :                 return NULL;
     295                 :            : 
     296         [ +  + ]:        204 :         for (a = v, b = r; *a; a++) {
     297                 :            : 
     298   [ +  -  +  + ]:        176 :                 if ((*a >= '0' && *a <= '9') ||
     299   [ +  +  -  + ]:        160 :                     (*a >= 'a' && *a <= 'z') ||
     300   [ -  +  #  # ]:         48 :                     (*a >= 'A' && *a <= 'Z') ||
     301         [ -  + ]:         48 :                     strchr("_-/.", *a))
     302                 :        128 :                         *(b++) = *a;
     303                 :            :                 else {
     304                 :         48 :                         *(b++) = '%';
     305                 :         48 :                         *(b++) = hexchar(*a >> 4);
     306                 :         48 :                         *(b++) = hexchar(*a & 0xF);
     307                 :            :                 }
     308                 :            :         }
     309                 :            : 
     310                 :         28 :         *b = 0;
     311                 :         28 :         return r;
     312                 :            : }
     313                 :            : 
     314                 :        175 : int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) {
     315         [ -  + ]:        175 :         assert(m);
     316                 :            : 
     317         [ -  + ]:        175 :         if (r < 0) {
     318         [ #  # ]:          0 :                 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
     319                 :          0 :                         sd_bus_reply_method_errno(m, r, error);
     320                 :            : 
     321         [ -  + ]:        175 :         } else if (sd_bus_error_is_set(error)) {
     322         [ #  # ]:          0 :                 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
     323                 :          0 :                         sd_bus_reply_method_error(m, error);
     324                 :            :         } else
     325                 :        175 :                 return r;
     326                 :            : 
     327         [ #  # ]:          0 :         log_debug("Failed to process message type=%s sender=%s destination=%s path=%s interface=%s member=%s cookie=%" PRIu64 " reply_cookie=%" PRIu64 " signature=%s error-name=%s error-message=%s: %s",
     328                 :            :                   bus_message_type_to_string(m->header->type),
     329                 :            :                   strna(sd_bus_message_get_sender(m)),
     330                 :            :                   strna(sd_bus_message_get_destination(m)),
     331                 :            :                   strna(sd_bus_message_get_path(m)),
     332                 :            :                   strna(sd_bus_message_get_interface(m)),
     333                 :            :                   strna(sd_bus_message_get_member(m)),
     334                 :            :                   BUS_MESSAGE_COOKIE(m),
     335                 :            :                   m->reply_cookie,
     336                 :            :                   strna(m->root_container.signature),
     337                 :            :                   strna(m->error.name),
     338                 :            :                   strna(m->error.message),
     339                 :            :                   bus_error_message(error, r));
     340                 :            : 
     341                 :          0 :         return 1;
     342                 :            : }

Generated by: LCOV version 1.14