dcavalca / rpms / systemd

Forked from rpms/systemd 3 months ago
Clone
Blob Blame History Raw
From fb195ccc27d1643d4152ee874144c36c0104c56d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Mon, 9 May 2022 15:10:36 +0200
Subject: [PATCH] shared/json: add helper to ref first, unref second

This normally wouldn't happen, but if some of those places were called
with lhs and rhs being the same object, we could unref the last ref first,
and then try to take the ref again. It's easier to be safe, and with the
helper we save some lines too.

(cherry picked from commit ce913e0ec4c97651c7c1509b72fb81ee61d80c6a)
Related: #2087652
---
 src/shared/json.c | 36 ++++++++++--------------------------
 src/shared/json.h |  8 ++++++++
 2 files changed, 18 insertions(+), 26 deletions(-)

diff --git a/src/shared/json.c b/src/shared/json.c
index fe05657dad..bb2363fd98 100644
--- a/src/shared/json.c
+++ b/src/shared/json.c
@@ -1847,9 +1847,7 @@ int json_variant_filter(JsonVariant **v, char **to_remove) {
                 return r;
 
         json_variant_propagate_sensitive(*v, w);
-
-        json_variant_unref(*v);
-        *v = TAKE_PTR(w);
+        JSON_VARIANT_REPLACE(*v, TAKE_PTR(w));
 
         return (int) n;
 }
@@ -1918,9 +1916,7 @@ int json_variant_set_field(JsonVariant **v, const char *field, JsonVariant *valu
                 return r;
 
         json_variant_propagate_sensitive(*v, w);
-
-        json_variant_unref(*v);
-        *v = TAKE_PTR(w);
+        JSON_VARIANT_REPLACE(*v, TAKE_PTR(w));
 
         return 1;
 }
@@ -2001,8 +1997,7 @@ int json_variant_merge(JsonVariant **v, JsonVariant *m) {
                 return 0; /* nothing to do */
 
         if (v_blank) {
-                json_variant_unref(*v);
-                *v = json_variant_ref(m);
+                JSON_VARIANT_REPLACE(*v, json_variant_ref(m));
                 return 1;
         }
 
@@ -2039,9 +2034,7 @@ int json_variant_merge(JsonVariant **v, JsonVariant *m) {
 
         json_variant_propagate_sensitive(*v, w);
         json_variant_propagate_sensitive(m, w);
-
-        json_variant_unref(*v);
-        *v = TAKE_PTR(w);
+        JSON_VARIANT_REPLACE(*v, TAKE_PTR(w));
 
         return 1;
 }
@@ -2081,9 +2074,7 @@ int json_variant_append_array(JsonVariant **v, JsonVariant *element) {
                 return r;
 
         json_variant_propagate_sensitive(*v, nv);
-
-        json_variant_unref(*v);
-        *v = TAKE_PTR(nv);
+        JSON_VARIANT_REPLACE(*v, TAKE_PTR(nv));
 
         return 0;
 }
@@ -2297,8 +2288,7 @@ static int json_variant_set_source(JsonVariant **v, JsonSource *source, unsigned
         w->line = line;
         w->column = column;
 
-        json_variant_unref(*v);
-        *v = w;
+        JSON_VARIANT_REPLACE(*v, w);
 
         return 1;
 }
@@ -4499,14 +4489,10 @@ int json_dispatch_strv(const char *name, JsonVariant *variant, JsonDispatchFlags
 }
 
 int json_dispatch_variant(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
-        JsonVariant **p = userdata;
-
+        JsonVariant **p = ASSERT_PTR(userdata);
         assert(variant);
-        assert(p);
-
-        json_variant_unref(*p);
-        *p = json_variant_ref(variant);
 
+        JSON_VARIANT_REPLACE(*p, json_variant_ref(variant));
         return 0;
 }
 
@@ -4628,8 +4614,7 @@ int json_variant_sort(JsonVariant **v) {
         if (!n->sorted) /* Check if this worked. This will fail if there are multiple identical keys used. */
                 return -ENOTUNIQ;
 
-        json_variant_unref(*v);
-        *v = n;
+        JSON_VARIANT_REPLACE(*v, n);
 
         return 1;
 }
@@ -4684,8 +4669,7 @@ int json_variant_normalize(JsonVariant **v) {
                 goto finish;
         }
 
-        json_variant_unref(*v);
-        *v = n;
+        JSON_VARIANT_REPLACE(*v, n);
 
         r = 1;
 
diff --git a/src/shared/json.h b/src/shared/json.h
index 8760354b66..dd73c1e497 100644
--- a/src/shared/json.h
+++ b/src/shared/json.h
@@ -82,6 +82,14 @@ JsonVariant *json_variant_ref(JsonVariant *v);
 JsonVariant *json_variant_unref(JsonVariant *v);
 void json_variant_unref_many(JsonVariant **array, size_t n);
 
+#define JSON_VARIANT_REPLACE(v, q)        \
+        do {                              \
+                typeof(v)* _v = &(v);     \
+                typeof(q) _q = (q);       \
+                json_variant_unref(*_v);  \
+                *_v = _q;                 \
+        } while(0)
+
 DEFINE_TRIVIAL_CLEANUP_FUNC(JsonVariant *, json_variant_unref);
 
 const char *json_variant_string(JsonVariant *v);