]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-bus: switch to a manual overflow check in sd_bus_track_add_name()
authorLennart Poettering <lennart@poettering.net>
Wed, 20 Apr 2022 20:30:22 +0000 (22:30 +0200)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 20 Apr 2022 23:58:35 +0000 (08:58 +0900)
This is generally used in a directly client controllable way, hence we
should handle ref count overflow gracefully, instead of hitting an
assert().

As discussed:

https://github.com/systemd/systemd/pull/23099#discussion_r854341850

src/libsystemd/sd-bus/bus-track.c

index 4c44162108c4dc635c06cb5bee9fe9c0db64f5aa..e403555f8f83ce3959a3a3a531f3aa9ba1555d14 100644 (file)
@@ -48,7 +48,7 @@ static struct track_item* track_item_free(struct track_item *i) {
         return mfree(i);
 }
 
-DEFINE_PRIVATE_TRIVIAL_REF_UNREF_FUNC(struct track_item, track_item, track_item_free);
+DEFINE_PRIVATE_TRIVIAL_UNREF_FUNC(struct track_item, track_item, track_item_free);
 DEFINE_TRIVIAL_CLEANUP_FUNC(struct track_item*, track_item_unref);
 DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(track_item_hash_ops, char, string_hash_func, string_compare_func,
                                               struct track_item, track_item_free);
@@ -190,8 +190,18 @@ _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) {
 
         i = hashmap_get(track->names, name);
         if (i) {
-                if (track->recursive)
-                        track_item_ref(i);
+                if (track->recursive) {
+                        assert(i->n_ref > 0);
+
+                        /* Manual oveflow check (instead of a DEFINE_TRIVIAL_REF_FUNC() helper or so), so
+                         * that we can return a proper error, given this is almost always called in a
+                         * directly client controllable way, and thus better should never hit an assertion
+                         * here. */
+                        if (i->n_ref >= UINT_MAX)
+                                return -EOVERFLOW;
+
+                        i->n_ref++;
+                }
 
                 bus_track_remove_from_queue(track);
                 return 0;