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 <jansson.h>. Hence, we cannot drop patching the included jansson.h header yet and still need our wrapper functions.
This commit is contained in:
@@ -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__ */
|
||||
|
@@ -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;
|
||||
|
@@ -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,
|
||||
|
Reference in New Issue
Block a user