From c609338b1d7f5c627f93cc57ae2967cfb675c53c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 16 Jan 2024 11:54:20 +0100 Subject: [PATCH] json: export json_variant_is_sensitive_recursive() Let's export this function, so that we can use it elsewhere. Also, while at it, let's cache the result in a flag. This is only safe if the result is positive, since we allow the flag to be enabled at any time down thre tree somewhere, which we need to look at. (We never allow it to be turned off however) --- src/shared/json.c | 49 +++++++++++++++++++++++++++++------------------ src/shared/json.h | 1 + 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/src/shared/json.c b/src/shared/json.c index 0259196e4e..270aef4105 100644 --- a/src/shared/json.c +++ b/src/shared/json.c @@ -89,6 +89,9 @@ struct JsonVariant { /* Erase from memory when freeing */ bool sensitive:1; + /* True if we know that any referenced json object is marked sensitive */ + bool recursive_sensitive:1; + /* If this is an object the fields are strictly ordered by name */ bool sorted:1; @@ -1453,6 +1456,33 @@ bool json_variant_is_sensitive(JsonVariant *v) { return v->sensitive; } +bool json_variant_is_sensitive_recursive(JsonVariant *v) { + if (!v) + return false; + if (json_variant_is_sensitive(v)) + return true; + if (!json_variant_is_regular(v)) + return false; + if (v->recursive_sensitive) /* Already checked this before */ + return true; + if (!IN_SET(v->type, JSON_VARIANT_ARRAY, JSON_VARIANT_OBJECT)) + return false; + if (v->is_reference) { + if (!json_variant_is_sensitive_recursive(v->reference)) + return false; + + return (v->recursive_sensitive = true); + } + + for (size_t i = 0; i < json_variant_elements(v); i++) + if (json_variant_is_sensitive_recursive(json_variant_by_index(v, i))) + return (v->recursive_sensitive = true); + + /* Note: we only cache the result here in case true, since we allow all elements down the tree to + * have their sensitive flag toggled later on (but never off) */ + return false; +} + static void json_variant_propagate_sensitive(JsonVariant *from, JsonVariant *to) { if (json_variant_is_sensitive(from)) json_variant_sensitive(to); @@ -1773,25 +1803,6 @@ static int json_format(FILE *f, JsonVariant *v, JsonFormatFlags flags, const cha return 0; } -static bool json_variant_is_sensitive_recursive(JsonVariant *v) { - if (!v) - return false; - if (json_variant_is_sensitive(v)) - return true; - if (!json_variant_is_regular(v)) - return false; - if (!IN_SET(v->type, JSON_VARIANT_ARRAY, JSON_VARIANT_OBJECT)) - return false; - if (v->is_reference) - return json_variant_is_sensitive_recursive(v->reference); - - for (size_t i = 0; i < json_variant_elements(v); i++) - if (json_variant_is_sensitive_recursive(json_variant_by_index(v, i))) - return true; - - return false; -} - int json_variant_format(JsonVariant *v, JsonFormatFlags flags, char **ret) { _cleanup_(memstream_done) MemStream m = {}; size_t sz; diff --git a/src/shared/json.h b/src/shared/json.h index 3c20f94b58..156f8e731e 100644 --- a/src/shared/json.h +++ b/src/shared/json.h @@ -155,6 +155,7 @@ bool json_variant_equal(JsonVariant *a, JsonVariant *b); void json_variant_sensitive(JsonVariant *v); bool json_variant_is_sensitive(JsonVariant *v); +bool json_variant_is_sensitive_recursive(JsonVariant *v); struct json_variant_foreach_state { JsonVariant *variant;