chiark / gitweb /
sd-bus: add extra assert check
[elogind.git] / src / libsystemd / sd-bus / bus-message.c
index a4939b47c84b7189c81ecfd9399f80f6045eeec4..ec3a39d051c82629ed3d945c5965204d13d098d3 100644 (file)
@@ -429,10 +429,10 @@ int bus_message_from_header(
                 if (m->creds.pid > 0)
                         m->creds.mask |= SD_BUS_CREDS_PID;
 
-                if (m->creds.uid != (uid_t) -1)
+                if (m->creds.uid != UID_INVALID)
                         m->creds.mask |= SD_BUS_CREDS_UID;
 
-                if (m->creds.gid != (gid_t) -1)
+                if (m->creds.gid != GID_INVALID)
                         m->creds.mask |= SD_BUS_CREDS_GID;
         }
 
@@ -2063,6 +2063,7 @@ static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c)
 
         assert(m);
         assert(c);
+        assert(c->signature);
 
         if (!BUS_MESSAGE_IS_GVARIANT(m))
                 return 0;
@@ -4450,13 +4451,32 @@ _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
 
         assert_return(m, -EINVAL);
         assert_return(m->sealed, -EPERM);
-        assert_return(types, -EINVAL);
 
-        if (isempty(types))
-                return 0;
+        /* If types is NULL, read exactly one element */
+        if (!types) {
+                struct bus_container *c;
+                size_t l;
+
+                if (message_end_of_signature(m))
+                        return -ENXIO;
+
+                if (message_end_of_array(m, m->rindex))
+                        return 0;
+
+                c = message_get_container(m);
+
+                r = signature_element_length(c->signature + c->index, &l);
+                if (r < 0)
+                        return r;
+
+                types = strndupa(c->signature + c->index, l);
+        }
 
         switch (*types) {
 
+        case 0: /* Nothing to drop */
+                return 0;
+
         case SD_BUS_TYPE_BYTE:
         case SD_BUS_TYPE_BOOLEAN:
         case SD_BUS_TYPE_INT16:
@@ -5314,35 +5334,57 @@ _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
         return 1;
 }
 
-const char* bus_message_get_arg(sd_bus_message *m, unsigned i) {
-        int r;
-        const char *t = NULL;
+int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str, char ***strv) {
+        const char *contents;
         unsigned j;
+        char type;
+        int r;
 
         assert(m);
+        assert(str);
+        assert(strv);
 
         r = sd_bus_message_rewind(m, true);
         if (r < 0)
-                return NULL;
+                return r;
 
-        for (j = 0; j <= i; j++) {
-                char type;
+        for (j = 0;; j++) {
+                r = sd_bus_message_peek_type(m, &type, &contents);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        return -ENXIO;
+
+                /* Don't match against arguments after the first one we don't understand */
+                if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
+                    !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
+                        return -ENXIO;
 
-                r = sd_bus_message_peek_type(m, &type, NULL);
+                if (j >= i)
+                        break;
+
+                r = sd_bus_message_skip(m, NULL);
                 if (r < 0)
-                        return NULL;
+                        return r;
+        }
 
-                if (type != SD_BUS_TYPE_STRING &&
-                    type != SD_BUS_TYPE_OBJECT_PATH &&
-                    type != SD_BUS_TYPE_SIGNATURE)
-                        return NULL;
+        if (type == SD_BUS_TYPE_ARRAY) {
 
-                r = sd_bus_message_read_basic(m, type, &t);
+                r = sd_bus_message_read_strv(m, strv);
                 if (r < 0)
-                        return NULL;
+                        return r;
+
+                *str = NULL;
+
+        } else {
+                r = sd_bus_message_read_basic(m, type, str);
+                if (r < 0)
+                        return r;
+
+                *strv = NULL;
         }
 
-        return t;
+        return 0;
 }
 
 bool bus_header_is_complete(struct bus_header *h, size_t size) {