sd-bus: handle non-string keys in dictionaries in JSON dump
JSON only supports string keys in objects, but D-Bus specification is a bit more lenient and allows dict entries to have any basic type as key. Let's stringify allowed non-string keys so that we can represent them as JSON objects. Relevant snippet from the D-Bus specification: A DICT_ENTRY works exactly like a struct, but rather than parentheses it uses curly braces, and it has more restrictions. The restrictions are: it occurs only as an array element type; it has exactly two single complete types inside the curly braces; the first single complete type (the "key") must be a basic type rather than a container type. Implementations must not accept dict entries outside of arrays, must not accept dict entries with zero, one, or more than two fields, and must not accept dict entries with non-basic-typed keys. A dict entry is always a key-value pair. Resolves: #32904
This commit is contained in:
committed by
Yu Watanabe
parent
304899fa57
commit
7cecff8c99
@@ -72,6 +72,7 @@ static int json_transform_dict_array(sd_bus_message *m, sd_json_variant **ret) {
|
||||
CLEANUP_ARRAY(elements, n_elements, sd_json_variant_unref_many);
|
||||
|
||||
for (;;) {
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *key = NULL;
|
||||
const char *contents;
|
||||
char type;
|
||||
|
||||
@@ -94,11 +95,35 @@ static int json_transform_dict_array(sd_bus_message *m, sd_json_variant **ret) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = json_transform_one(m, elements + n_elements);
|
||||
r = json_transform_one(m, &key);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
n_elements++;
|
||||
/* JSON only supports string keys in objects, but D-Bus specification is a bit more lenient
|
||||
* and allows dict entries to have any basic type as key. Let's stringify allowed non-string
|
||||
* keys so that we can represent them as JSON objects. */
|
||||
if (!sd_json_variant_is_string(key)) {
|
||||
_cleanup_free_ char *s = NULL;
|
||||
|
||||
if (!IN_SET(sd_json_variant_type(key),
|
||||
SD_JSON_VARIANT_BOOLEAN,
|
||||
SD_JSON_VARIANT_INTEGER,
|
||||
SD_JSON_VARIANT_REAL,
|
||||
SD_JSON_VARIANT_UNSIGNED))
|
||||
return -EINVAL;
|
||||
|
||||
r = sd_json_variant_format(key, /* flags= */ 0, &s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
key = sd_json_variant_unref(key);
|
||||
|
||||
r = sd_json_variant_new_string(&key, s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
elements[n_elements++] = TAKE_PTR(key);
|
||||
|
||||
r = json_transform_one(m, elements + n_elements);
|
||||
if (r < 0)
|
||||
|
||||
@@ -43,6 +43,12 @@ busctl call --json=short \
|
||||
busctl call -j \
|
||||
org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.DBus.Properties \
|
||||
GetAll s "org.freedesktop.systemd1.Manager" | jq -c
|
||||
# Do the same with D-Bus' org.freedesktop.DBus.Debug.Stats interface which also provides some
|
||||
# complex signatures that caused issues during the JSON conversion in the past
|
||||
# See: https://github.com/systemd/systemd/issues/32904
|
||||
busctl call --json=pretty \
|
||||
org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.Debug.Stats \
|
||||
GetStats | jq -c
|
||||
busctl call --verbose --timeout=60 --expect-reply=yes \
|
||||
org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager \
|
||||
ListUnitsByPatterns asas 1 "active" 2 "systemd-*.socket" "*.mount"
|
||||
|
||||
Reference in New Issue
Block a user