]> granicus.if.org Git - json-c/commitdiff
build: Add symbol versions to all exported symbols
authorSimon McVittie <smcv@collabora.com>
Mon, 29 Jun 2020 17:16:34 +0000 (18:16 +0100)
committerSimon McVittie <smcv@collabora.com>
Wed, 1 Jul 2020 17:24:26 +0000 (18:24 +0100)
With this version script, newly-linked binaries that depend on the
json-c shared library will refer to its symbols in a versioned form,
preventing their references from being resolved to a symbol of the same
name exported by json-glib or libjansson if those libraries appear in
dependency search order before json-c, which will usually result in
a crash. This is necessary because ELF symbol resolution normally uses
a single flat namespace, not a tree like Windows symbol resolution.
At least one symbol (json_object_iter_next()) is exported by all three
JSON libraries.

Linking with -Bsymbolic is not enough to have this effect in all cases,
because -Bsymbolic only affects symbol lookup within a shared object,
for example when json_object_set_serializer() calls
json_object_set_userdata(). It does not affect calls from external
code into json-c, unless json-c was statically linked into the
external caller.

This change will also not prevent code that depends on json-glib or
libjansson from finding json-c's symbols and crashing; to prevent
that, a corresponding change in json-glib or libjansson would be needed.

Adding a symbol-version is a backwards-compatible change, but once
added, removing or changing the symbol-version on a symbol would be an
incompatible change that requires a SONAME bump.

Resolves: https://github.com/json-c/json-c/issues/621
(when combined with an equivalent change to libjansson).

Signed-off-by: Simon McVittie <smcv@collabora.com>
CMakeLists.txt
json-c.sym [new file with mode: 0644]

index 21e395ed3c75a79d0bc412ec7a4cdbf49f6c26c0..da0af963edb07c67b155b2246e3dc22d704a1675 100644 (file)
@@ -325,6 +325,22 @@ if (NOT ("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC"))
                # XXX need cmake>=3.13 for this:
                #add_link_options("-Wl,-Bsymbolic-functions")
        endif()
+
+       file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/check-version-script.sym" "TEST { global: *; };")
+       list(APPEND CMAKE_REQUIRED_LIBRARIES "-Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/check-version-script.sym")
+       check_c_source_compiles(
+       "
+       int main (void)
+       {
+         return 0;
+       }
+       "
+       VERSION_SCRIPT_WORKS
+       )
+       list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES "-Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/check-version-script.sym")
+       if (VERSION_SCRIPT_WORKS)
+               set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--version-script,${CMAKE_CURRENT_SOURCE_DIR}/json-c.sym")
+       endif()
 endif()
 
 if ($ENV{VALGRIND})
diff --git a/json-c.sym b/json-c.sym
new file mode 100644 (file)
index 0000000..bf78792
--- /dev/null
@@ -0,0 +1,153 @@
+JSONC_0.14 {
+  global:
+    _json_c_set_last_err;
+    _json_c_strerror;
+    _json_c_strerror_enable;
+    array_list_add;
+    array_list_bsearch;
+    array_list_del_idx;
+    array_list_free;
+    array_list_get_idx;
+    array_list_length;
+    array_list_new;
+    array_list_put_idx;
+    array_list_sort;
+    json_c_get_random_seed;
+    json_c_object_sizeof;
+    json_c_set_serialization_double_format;
+    json_c_shallow_copy_default;
+    json_c_version;
+    json_c_version_num;
+    json_c_visit;
+    json_global_set_string_hash;
+    json_hex_chars;
+    json_number_chars;
+    json_object_array_add;
+    json_object_array_bsearch;
+    json_object_array_del_idx;
+    json_object_array_get_idx;
+    json_object_array_length;
+    json_object_array_put_idx;
+    json_object_array_sort;
+    json_object_deep_copy;
+    json_object_double_to_json_string;
+    json_object_equal;
+    json_object_free_userdata;
+    json_object_from_fd;
+    json_object_from_fd_ex;
+    json_object_from_file;
+    json_object_get;
+    json_object_get_array;
+    json_object_get_boolean;
+    json_object_get_double;
+    json_object_get_int64;
+    json_object_get_int;
+    json_object_get_object;
+    json_object_get_string;
+    json_object_get_string_len;
+    json_object_get_type;
+    json_object_get_uint64;
+    json_object_get_userdata;
+    json_object_int_inc;
+    json_object_is_type;
+    json_object_iter_begin;
+    json_object_iter_end;
+    json_object_iter_equal;
+    json_object_iter_init_default;
+    json_object_iter_next;
+    json_object_iter_peek_name;
+    json_object_iter_peek_value;
+    json_object_new_array;
+    json_object_new_boolean;
+    json_object_new_double;
+    json_object_new_double_s;
+    json_object_new_int64;
+    json_object_new_int;
+    json_object_new_null;
+    json_object_new_object;
+    json_object_new_string;
+    json_object_new_string_len;
+    json_object_new_uint64;
+    json_object_object_add;
+    json_object_object_add_ex;
+    json_object_object_del;
+    json_object_object_get;
+    json_object_object_get_ex;
+    json_object_object_length;
+    json_object_put;
+    json_object_set_boolean;
+    json_object_set_double;
+    json_object_set_int64;
+    json_object_set_int;
+    json_object_set_serializer;
+    json_object_set_string;
+    json_object_set_string_len;
+    json_object_set_uint64;
+    json_object_set_userdata;
+    json_object_to_fd;
+    json_object_to_file;
+    json_object_to_file_ext;
+    json_object_to_json_string;
+    json_object_to_json_string_ext;
+    json_object_to_json_string_length;
+    json_object_userdata_to_json_string;
+    json_parse_double;
+    json_parse_int64;
+    json_parse_uint64;
+    json_pointer_get;
+    json_pointer_getf;
+    json_pointer_set;
+    json_pointer_setf;
+    json_tokener_error_desc;
+    json_tokener_free;
+    json_tokener_get_error;
+    json_tokener_get_parse_end;
+    json_tokener_new;
+    json_tokener_new_ex;
+    json_tokener_parse;
+    json_tokener_parse_ex;
+    json_tokener_parse_verbose;
+    json_tokener_reset;
+    json_tokener_set_flags;
+    json_type_to_name;
+    json_util_get_last_err;
+    lh_char_equal;
+    lh_kchar_table_new;
+    lh_kptr_table_new;
+    lh_ptr_equal;
+    lh_table_delete;
+    lh_table_delete_entry;
+    lh_table_free;
+    lh_table_insert;
+    lh_table_insert_w_hash;
+    lh_table_length;
+    lh_table_lookup;
+    lh_table_lookup_entry;
+    lh_table_lookup_entry_w_hash;
+    lh_table_lookup_ex;
+    lh_table_new;
+    lh_table_resize;
+    mc_debug;
+    mc_error;
+    mc_get_debug;
+    mc_info;
+    mc_set_debug;
+    mc_set_syslog;
+    printbuf_free;
+    printbuf_memappend;
+    printbuf_memset;
+    printbuf_new;
+    printbuf_reset;
+    sprintbuf;
+
+  local:
+    *;
+};
+
+JSONC_0.15 {
+  global:
+    array_list_new2;
+    array_list_shrink;
+    json_object_array_shrink;
+    json_object_new_array_ext;
+} JSONC_0.14;