diff options
Diffstat (limited to 'shared/nm-glib-aux/nm-json-aux.c')
| -rw-r--r-- | shared/nm-glib-aux/nm-json-aux.c | 286 |
1 files changed, 0 insertions, 286 deletions
diff --git a/shared/nm-glib-aux/nm-json-aux.c b/shared/nm-glib-aux/nm-json-aux.c deleted file mode 100644 index 97ee606f..00000000 --- a/shared/nm-glib-aux/nm-json-aux.c +++ /dev/null @@ -1,286 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2017 - 2019 Red Hat, Inc. - */ - -#include "nm-glib-aux/nm-default-glib-i18n-lib.h" - -#include "nm-json-aux.h" - -#include <dlfcn.h> - -/*****************************************************************************/ - -/* If RTLD_DEEPBIND isn't available just ignore it. This can cause problems - * with jansson, json-glib, and cjson symbols clashing (and as such crashing the - * program). But that needs to be fixed by the json libraries, and it is by adding - * symbol versioning in recent versions. */ -#ifndef RTLD_DEEPBIND - #define RTLD_DEEPBIND 0 -#endif - -/*****************************************************************************/ - -static void -_gstr_append_string_len(GString *gstr, const char *str, gsize len) -{ - g_string_append_c(gstr, '\"'); - - while (len > 0) { - gsize n; - const char *end; - gboolean valid; - - nm_assert(len > 0); - - valid = g_utf8_validate(str, len, &end); - - nm_assert(end && end >= str && end <= &str[len]); - - if (end > str) { - const char *s; - - for (s = str; s < end; s++) { - nm_assert(s[0] != '\0'); - - if (s[0] < 0x20) { - const char *text; - - switch (s[0]) { - case '\\': - text = "\\\\"; - break; - case '\"': - text = "\\\""; - break; - case '\b': - text = "\\b"; - break; - case '\f': - text = "\\f"; - break; - case '\n': - text = "\\n"; - break; - case '\r': - text = "\\r"; - break; - case '\t': - text = "\\t"; - break; - default: - g_string_append_printf(gstr, "\\u%04X", (guint) s[0]); - continue; - } - g_string_append(gstr, text); - continue; - } - - if (NM_IN_SET(s[0], '\\', '\"')) - g_string_append_c(gstr, '\\'); - g_string_append_c(gstr, s[0]); - } - } else - nm_assert(!valid); - - if (valid) { - nm_assert(end == &str[len]); - break; - } - - nm_assert(end < &str[len]); - - if (end[0] == '\0') { - /* there is a NUL byte in the string. Technically this is valid UTF-8, so we - * encode it there. However, this will likely result in a truncated string when - * parsing. */ - g_string_append(gstr, "\\u0000"); - } else { - /* the character is not valid UTF-8. There is nothing we can do about it, because - * JSON can only contain UTF-8 and even the escape sequences can only escape Unicode - * codepoints (but not binary). - * - * The argument is not a string (in any known encoding), hence we cannot represent - * it as a JSON string (which are unicode strings). - * - * Print an underscore instead of the invalid char :) */ - g_string_append_c(gstr, '_'); - } - - n = str - end; - nm_assert(n < len); - n++; - str += n; - len -= n; - } - - g_string_append_c(gstr, '\"'); -} - -void -nm_json_gstr_append_string_len(GString *gstr, const char *str, gsize n) -{ - g_return_if_fail(gstr); - - _gstr_append_string_len(gstr, str, n); -} - -void -nm_json_gstr_append_string(GString *gstr, const char *str) -{ - g_return_if_fail(gstr); - - if (!str) - g_string_append(gstr, "null"); - else - _gstr_append_string_len(gstr, str, strlen(str)); -} - -void -nm_json_gstr_append_obj_name(GString *gstr, const char *key, char start_container) -{ - g_return_if_fail(gstr); - g_return_if_fail(key); - - nm_json_gstr_append_string(gstr, key); - - if (start_container != '\0') { - nm_assert(NM_IN_SET(start_container, '[', '{')); - g_string_append_printf(gstr, ": %c ", start_container); - } else - g_string_append(gstr, ": "); -} - -/*****************************************************************************/ - -typedef struct { - NMJsonVt vt; - void * dl_handle; -} NMJsonVtInternal; - -static NMJsonVtInternal * -_nm_json_vt_internal_load(void) -{ - NMJsonVtInternal *v; - const char * soname; - void * handle; - - v = g_new0(NMJsonVtInternal, 1); - -#if WITH_JANSSON && defined(JANSSON_SONAME) - G_STATIC_ASSERT_EXPR(NM_STRLEN(JANSSON_SONAME) > 0); - nm_assert(strlen(JANSSON_SONAME) > 0); - soname = JANSSON_SONAME; -#elif !WITH_JANSSON && !defined(JANSSON_SONAME) - soname = NULL; -#else - #error "WITH_JANSON and JANSSON_SONAME are defined inconsistently." -#endif - - if (!soname) - return v; - - handle = dlopen(soname, - RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE -#if !defined(ASAN_BUILD) - | RTLD_DEEPBIND -#endif - | 0); - if (!handle) - return v; - -#define TRY_BIND_SYMBOL(symbol) \ - G_STMT_START \ - { \ - void *_sym = dlsym(handle, #symbol); \ - \ - if (!_sym) \ - goto fail_symbol; \ - v->vt.nm_##symbol = _sym; \ - } \ - G_STMT_END - - TRY_BIND_SYMBOL(json_array); - TRY_BIND_SYMBOL(json_array_append_new); - TRY_BIND_SYMBOL(json_array_get); - TRY_BIND_SYMBOL(json_array_size); - TRY_BIND_SYMBOL(json_delete); - TRY_BIND_SYMBOL(json_dumps); - TRY_BIND_SYMBOL(json_false); - TRY_BIND_SYMBOL(json_integer); - TRY_BIND_SYMBOL(json_integer_value); - TRY_BIND_SYMBOL(json_loads); - TRY_BIND_SYMBOL(json_object); - TRY_BIND_SYMBOL(json_object_del); - TRY_BIND_SYMBOL(json_object_get); - TRY_BIND_SYMBOL(json_object_iter); - TRY_BIND_SYMBOL(json_object_iter_key); - TRY_BIND_SYMBOL(json_object_iter_next); - TRY_BIND_SYMBOL(json_object_iter_value); - TRY_BIND_SYMBOL(json_object_key_to_iter); - TRY_BIND_SYMBOL(json_object_set_new); - TRY_BIND_SYMBOL(json_object_size); - TRY_BIND_SYMBOL(json_string); - TRY_BIND_SYMBOL(json_string_value); - TRY_BIND_SYMBOL(json_true); - - v->vt.loaded = TRUE; - v->dl_handle = handle; - return v; - -fail_symbol: - dlclose(&handle); - *v = (NMJsonVtInternal){}; - return v; -} - -const NMJsonVt *_nm_json_vt_ptr = NULL; - -const NMJsonVt * -_nm_json_vt_init(void) -{ - NMJsonVtInternal *v; - -again: - v = g_atomic_pointer_get((gpointer *) &_nm_json_vt_ptr); - if (G_UNLIKELY(!v)) { - v = _nm_json_vt_internal_load(); - if (!g_atomic_pointer_compare_and_exchange((gpointer *) &_nm_json_vt_ptr, NULL, v)) { - if (v->dl_handle) - dlclose(v->dl_handle); - g_free(v); - goto again; - } - - /* we transfer ownership. */ - } - - nm_assert(v && v == g_atomic_pointer_get((gpointer *) &_nm_json_vt_ptr)); - return &v->vt; -} - -const NMJsonVt * -nmtst_json_vt_reset(gboolean loaded) -{ - NMJsonVtInternal *v_old; - NMJsonVtInternal *v; - - v_old = g_atomic_pointer_get((gpointer *) &_nm_json_vt_ptr); - - if (!loaded) { - /* load a fake instance for testing. */ - v = g_new0(NMJsonVtInternal, 1); - } else - v = _nm_json_vt_internal_load(); - - if (!g_atomic_pointer_compare_and_exchange((gpointer *) &_nm_json_vt_ptr, v_old, v)) - g_assert_not_reached(); - - if (v_old) { - if (v_old->dl_handle) - dlclose(v_old->dl_handle); - g_free((gpointer *) v_old); - } - - return v->vt.loaded ? &v->vt : NULL; -} |