8d419f
From fb195ccc27d1643d4152ee874144c36c0104c56d Mon Sep 17 00:00:00 2001
8d419f
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
8d419f
Date: Mon, 9 May 2022 15:10:36 +0200
8d419f
Subject: [PATCH] shared/json: add helper to ref first, unref second
8d419f
8d419f
This normally wouldn't happen, but if some of those places were called
8d419f
with lhs and rhs being the same object, we could unref the last ref first,
8d419f
and then try to take the ref again. It's easier to be safe, and with the
8d419f
helper we save some lines too.
8d419f
8d419f
(cherry picked from commit ce913e0ec4c97651c7c1509b72fb81ee61d80c6a)
8d419f
Related: #2087652
8d419f
---
8d419f
 src/shared/json.c | 36 ++++++++++--------------------------
8d419f
 src/shared/json.h |  8 ++++++++
8d419f
 2 files changed, 18 insertions(+), 26 deletions(-)
8d419f
8d419f
diff --git a/src/shared/json.c b/src/shared/json.c
8d419f
index fe05657dad..bb2363fd98 100644
8d419f
--- a/src/shared/json.c
8d419f
+++ b/src/shared/json.c
8d419f
@@ -1847,9 +1847,7 @@ int json_variant_filter(JsonVariant **v, char **to_remove) {
8d419f
                 return r;
8d419f
 
8d419f
         json_variant_propagate_sensitive(*v, w);
8d419f
-
8d419f
-        json_variant_unref(*v);
8d419f
-        *v = TAKE_PTR(w);
8d419f
+        JSON_VARIANT_REPLACE(*v, TAKE_PTR(w));
8d419f
 
8d419f
         return (int) n;
8d419f
 }
8d419f
@@ -1918,9 +1916,7 @@ int json_variant_set_field(JsonVariant **v, const char *field, JsonVariant *valu
8d419f
                 return r;
8d419f
 
8d419f
         json_variant_propagate_sensitive(*v, w);
8d419f
-
8d419f
-        json_variant_unref(*v);
8d419f
-        *v = TAKE_PTR(w);
8d419f
+        JSON_VARIANT_REPLACE(*v, TAKE_PTR(w));
8d419f
 
8d419f
         return 1;
8d419f
 }
8d419f
@@ -2001,8 +1997,7 @@ int json_variant_merge(JsonVariant **v, JsonVariant *m) {
8d419f
                 return 0; /* nothing to do */
8d419f
 
8d419f
         if (v_blank) {
8d419f
-                json_variant_unref(*v);
8d419f
-                *v = json_variant_ref(m);
8d419f
+                JSON_VARIANT_REPLACE(*v, json_variant_ref(m));
8d419f
                 return 1;
8d419f
         }
8d419f
 
8d419f
@@ -2039,9 +2034,7 @@ int json_variant_merge(JsonVariant **v, JsonVariant *m) {
8d419f
 
8d419f
         json_variant_propagate_sensitive(*v, w);
8d419f
         json_variant_propagate_sensitive(m, w);
8d419f
-
8d419f
-        json_variant_unref(*v);
8d419f
-        *v = TAKE_PTR(w);
8d419f
+        JSON_VARIANT_REPLACE(*v, TAKE_PTR(w));
8d419f
 
8d419f
         return 1;
8d419f
 }
8d419f
@@ -2081,9 +2074,7 @@ int json_variant_append_array(JsonVariant **v, JsonVariant *element) {
8d419f
                 return r;
8d419f
 
8d419f
         json_variant_propagate_sensitive(*v, nv);
8d419f
-
8d419f
-        json_variant_unref(*v);
8d419f
-        *v = TAKE_PTR(nv);
8d419f
+        JSON_VARIANT_REPLACE(*v, TAKE_PTR(nv));
8d419f
 
8d419f
         return 0;
8d419f
 }
8d419f
@@ -2297,8 +2288,7 @@ static int json_variant_set_source(JsonVariant **v, JsonSource *source, unsigned
8d419f
         w->line = line;
8d419f
         w->column = column;
8d419f
 
8d419f
-        json_variant_unref(*v);
8d419f
-        *v = w;
8d419f
+        JSON_VARIANT_REPLACE(*v, w);
8d419f
 
8d419f
         return 1;
8d419f
 }
8d419f
@@ -4499,14 +4489,10 @@ int json_dispatch_strv(const char *name, JsonVariant *variant, JsonDispatchFlags
8d419f
 }
8d419f
 
8d419f
 int json_dispatch_variant(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
8d419f
-        JsonVariant **p = userdata;
8d419f
-
8d419f
+        JsonVariant **p = ASSERT_PTR(userdata);
8d419f
         assert(variant);
8d419f
-        assert(p);
8d419f
-
8d419f
-        json_variant_unref(*p);
8d419f
-        *p = json_variant_ref(variant);
8d419f
 
8d419f
+        JSON_VARIANT_REPLACE(*p, json_variant_ref(variant));
8d419f
         return 0;
8d419f
 }
8d419f
 
8d419f
@@ -4628,8 +4614,7 @@ int json_variant_sort(JsonVariant **v) {
8d419f
         if (!n->sorted) /* Check if this worked. This will fail if there are multiple identical keys used. */
8d419f
                 return -ENOTUNIQ;
8d419f
 
8d419f
-        json_variant_unref(*v);
8d419f
-        *v = n;
8d419f
+        JSON_VARIANT_REPLACE(*v, n);
8d419f
 
8d419f
         return 1;
8d419f
 }
8d419f
@@ -4684,8 +4669,7 @@ int json_variant_normalize(JsonVariant **v) {
8d419f
                 goto finish;
8d419f
         }
8d419f
 
8d419f
-        json_variant_unref(*v);
8d419f
-        *v = n;
8d419f
+        JSON_VARIANT_REPLACE(*v, n);
8d419f
 
8d419f
         r = 1;
8d419f
 
8d419f
diff --git a/src/shared/json.h b/src/shared/json.h
8d419f
index 8760354b66..dd73c1e497 100644
8d419f
--- a/src/shared/json.h
8d419f
+++ b/src/shared/json.h
8d419f
@@ -82,6 +82,14 @@ JsonVariant *json_variant_ref(JsonVariant *v);
8d419f
 JsonVariant *json_variant_unref(JsonVariant *v);
8d419f
 void json_variant_unref_many(JsonVariant **array, size_t n);
8d419f
 
8d419f
+#define JSON_VARIANT_REPLACE(v, q)        \
8d419f
+        do {                              \
8d419f
+                typeof(v)* _v = &(v);     \
8d419f
+                typeof(q) _q = (q);       \
8d419f
+                json_variant_unref(*_v);  \
8d419f
+                *_v = _q;                 \
8d419f
+        } while(0)
8d419f
+
8d419f
 DEFINE_TRIVIAL_CLEANUP_FUNC(JsonVariant *, json_variant_unref);
8d419f
 
8d419f
 const char *json_variant_string(JsonVariant *v);