From 125d362177eeabf49d04216bb62ae4c31c55e94c Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 9 Jan 2018 09:15:04 +0100 Subject: [PATCH] libnm: don't use any symbols from jansson.h directly Some symbols in jansson.h are macros, some are regular functions, and some are inline functions. Regular functions must not be used directly, only via dlsym(). Macros must be used directly, but it is non-obvious which symbols are macros. Hence, for each json_* macro add an nm_json_* alias. Inline functions are a bit odd. If they are inlined and don't use any non-inlined symbols from libjansson, they could be used directly. However, it's non obvious whether both of the conditions are met. Hence, we reimplement them in nm-json.h. The only function of this kind is json_decref(). The point is to not use any json_* symbols directly -- except structs and typedefs. Seemingly, with this change we don't use any jansson symbols directly. However, that is not true, as macros like nm_json_object_foreach() still are implemented based on what is included from . Hence, we cannot drop patching the included jansson.h header yet and still need our wrapper functions. --- libnm-core/nm-json.h | 32 ++++++++++++++++++++++++++++++++ libnm-core/nm-team-utils.c | 28 ++++++++++++++-------------- libnm-core/nm-utils.c | 7 ++++--- 3 files changed, 50 insertions(+), 17 deletions(-) diff --git a/libnm-core/nm-json.h b/libnm-core/nm-json.h index 2d0f10773d..3f99609e37 100644 --- a/libnm-core/nm-json.h +++ b/libnm-core/nm-json.h @@ -97,4 +97,36 @@ nm_json_vt_assert (void) const NMJsonVt *nmtst_json_vt_reset (gboolean loaded); +#define nm_json_boolean(vt, val) \ + ((val) ? (vt)->nm_json_true () : (vt)->nm_json_false ()) + +static inline void +nm_json_decref (const NMJsonVt *vt, json_t *json) +{ + /* Our ref-counting is not threadsafe, unlike libjansson's. But we never + * share one json_t instance between threads, and if we would, we would very likely + * wrap a mutex around it. */ + if ( json + && json->refcount != (size_t) -1 + && --json->refcount == 0) + vt->nm_json_delete (json); +} + +/*****************************************************************************/ + +/* the following are implemented as pure macros in jansson.h. + * They can be used directly, however, add a nm_json* variant, + * to make it explict we don't accidentally use jansson ABI. */ + +#define nm_json_is_boolean(json) json_is_boolean (json) +#define nm_json_is_integer(json) json_is_integer (json) +#define nm_json_is_string(json) json_is_string (json) +#define nm_json_is_object(json) json_is_object (json) +#define nm_json_is_array(json) json_is_array (json) +#define nm_json_is_true(json) json_is_true (json) +#define nm_json_boolean_value(json) json_boolean_value (json) +#define nm_json_array_foreach(a, b, c) json_array_foreach (a, b, c) +#define nm_json_object_foreach(a, b, c) json_object_foreach (a, b, c) +#define nm_json_object_foreach_safe(a, b, c, d) json_object_foreach_safe (a, b, c, d) + #endif /* __NM_JSON_H__ */ diff --git a/libnm-core/nm-team-utils.c b/libnm-core/nm-team-utils.c index af96b995d7..f08d50d26a 100644 --- a/libnm-core/nm-team-utils.c +++ b/libnm-core/nm-team-utils.c @@ -1127,10 +1127,10 @@ _link_watcher_from_json (const json_t *root_js_obj, const char *v_name; NMTeamLinkWatcher *result = NULL; - if (!json_is_object (root_js_obj)) + if (!nm_json_is_object (root_js_obj)) goto fail; - json_object_foreach ((json_t *) root_js_obj, j_key, j_val) { + nm_json_object_foreach ((json_t *) root_js_obj, j_key, j_val) { const LinkWatcherAttrData *attr_data = NULL; NMValueTypUnioMaybe *parse_result; @@ -1713,18 +1713,18 @@ _js_parse_locate_keys (NMTeamSetting *self, (_found_keys)[_attr_data->team_attr] = (_cur_val); \ _handled = TRUE; \ } else if ( !_attr_data \ - || !json_is_object ((_cur_val))) { \ + || !nm_json_is_object ((_cur_val))) { \ *(_out_unrecognized_content) = TRUE; \ _handled = TRUE; \ } \ _handled; \ }) - json_object_foreach (root_js_obj, cur_key1, cur_val1) { + nm_json_object_foreach (root_js_obj, cur_key1, cur_val1) { if (!_handle (self, cur_key1, cur_val1, keys, 1, found_keys, out_unrecognized_content)) { - json_object_foreach (cur_val1, cur_key2, cur_val2) { + nm_json_object_foreach (cur_val1, cur_key2, cur_val2) { if (!_handle (self, cur_key2, cur_val2, keys, 2, found_keys, out_unrecognized_content)) { - json_object_foreach (cur_val2, cur_key3, cur_val3) { + nm_json_object_foreach (cur_val2, cur_key3, cur_val3) { if (!_handle (self, cur_key3, cur_val3, keys, 3, found_keys, out_unrecognized_content)) *out_unrecognized_content = TRUE; } @@ -1770,13 +1770,13 @@ _js_parse_unpack (gboolean is_port, NMTeamLinkWatcher *link_watcher; nm_assert (out_ptr_array_link_watchers_free && !*out_ptr_array_link_watchers_free); - if (json_is_array (arg_js_obj)) { + if (nm_json_is_array (arg_js_obj)) { gsize i, len; - len = json_array_size (arg_js_obj); + len = nm_json_array_size (arg_js_obj); link_watchers = g_ptr_array_new_full (len, (GDestroyNotify) nm_team_link_watcher_unref); for (i = 0; i < len; i++) { - link_watcher = _link_watcher_from_json (json_array_get (arg_js_obj, i), + link_watcher = _link_watcher_from_json (nm_json_array_get (arg_js_obj, i), out_unrecognized_content); if (link_watcher) g_ptr_array_add (link_watchers, link_watcher); @@ -1799,16 +1799,16 @@ _js_parse_unpack (gboolean is_port, GPtrArray *strv = NULL; nm_assert (out_ptr_array_master_runner_tx_hash_free && !*out_ptr_array_master_runner_tx_hash_free); - if (json_is_array (arg_js_obj)) { + if (nm_json_is_array (arg_js_obj)) { gsize i, len; - len = json_array_size (arg_js_obj); + len = nm_json_array_size (arg_js_obj); if (len > 0) { strv = g_ptr_array_sized_new (len); for (i = 0; i < len; i++) { const char *v_string; - if ( nm_jansson_json_as_string (json_array_get (arg_js_obj, i), + if ( nm_jansson_json_as_string (nm_json_array_get (arg_js_obj, i), &v_string) <= 0 || !v_string || v_string[0] == '\0') { @@ -1871,10 +1871,10 @@ nm_team_setting_config_set (NMTeamSetting *self, const char *js_str) nm_auto_decref_json json_t *root_js_obj = NULL; if (nm_json_vt ()) - root_js_obj = json_loads (js_str, 0, NULL); + root_js_obj = nm_json_loads (js_str, 0, NULL); if ( !root_js_obj - || !json_is_object (root_js_obj)) + || !nm_json_is_object (root_js_obj)) new_js_str_invalid = TRUE; else { gboolean unrecognized_content = FALSE; diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c index b7b54948b4..8b6b121332 100644 --- a/libnm-core/nm-utils.c +++ b/libnm-core/nm-utils.c @@ -5495,6 +5495,7 @@ nm_utils_is_json_object (const char *str, GError **error) { #if WITH_JSON_VALIDATION nm_auto_decref_json json_t *json = NULL; + const NMJsonVt *vt; json_error_t jerror; g_return_val_if_fail (!error || !*error, FALSE); @@ -5507,10 +5508,10 @@ nm_utils_is_json_object (const char *str, GError **error) return FALSE; } - if (!nm_json_vt ()) + if (!(vt = nm_json_vt ())) return _nm_utils_is_json_object_no_validation (str, error); - json = json_loads (str, JSON_REJECT_DUPLICATES, &jerror); + json = vt->nm_json_loads (str, JSON_REJECT_DUPLICATES, &jerror); if (!json) { g_set_error (error, NM_CONNECTION_ERROR, @@ -5523,7 +5524,7 @@ nm_utils_is_json_object (const char *str, GError **error) /* valid JSON (depending on the definition) can also be a literal. * Here we only allow objects. */ - if (!json_is_object (json)) { + if (!nm_json_is_object (json)) { g_set_error_literal (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY,