Skip to content

Commit

Permalink
build: Add a symbol version to all exported symbols for glibc
Browse files Browse the repository at this point in the history
The --default-symver linker option attaches a default version definition
(the SONAME) to every exported symbol. It is supported since at least
GNU binutils 2.22 in 2011 (older versions not tested).

With this version definition, newly-linked binaries that depend on the
jansson 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-c or json-glib if those libraries appear in
dependency search order before jansson, 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 parse_json() calls json_decref(). It does not affect
calls from external code into jansson, unless jansson was statically
linked into the external caller.

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

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

Resolves: akheron/jansson#523
(when combined with an equivalent change to json-c).

Signed-off-by: Simon McVittie <smcv@collabora.com>
  • Loading branch information
JingweiLiuis authored and smcv committed Jun 25, 2022
1 parent 00c7e70 commit 32fc048
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 0 deletions.
7 changes: 7 additions & 0 deletions CMakeLists.txt
Expand Up @@ -107,6 +107,9 @@ if (HAS_NO_FORMAT_TRUNCATION)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-format-truncation")
endif()

include (CheckSymbolExists)
check_symbol_exists("__GLIBC__" "stdlib.h" LIBC_IS_GLIBC)

if (MSVC)
# Turn off Microsofts "security" warnings.
add_definitions( "/W3 /D_CRT_SECURE_NO_WARNINGS /wd4005 /wd4996 /nologo" )
Expand Down Expand Up @@ -366,6 +369,10 @@ if(JANSSON_BUILD_SHARED_LIBS)
${JANSSON_HDR_PUBLIC}
src/jansson.def)

if (LIBC_IS_GLIBC)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--default-symver")
endif()

set_target_properties(jansson PROPERTIES
VERSION ${JANSSON_VERSION}
SOVERSION ${JANSSON_SOVERSION})
Expand Down
4 changes: 4 additions & 0 deletions configure.ac
Expand Up @@ -137,6 +137,10 @@ fi
AS_IF([test "x$with_Bsymbolic" = "xyes"], [JSON_BSYMBOLIC_LDFLAGS=-Wl[,]-Bsymbolic-functions])
AC_SUBST(JSON_BSYMBOLIC_LDFLAGS)

# Enable symbol versioning on GNU libc
JSON_SYMVER_LDFLAGS=
AC_CHECK_DECL([__GLIBC__], [JSON_SYMVER_LDFLAGS=-Wl,--default-symver])
AC_SUBST([JSON_SYMVER_LDFLAGS])

AC_ARG_ENABLE([ossfuzzers],
[AS_HELP_STRING([--enable-ossfuzzers],
Expand Down
1 change: 1 addition & 0 deletions src/Makefile.am
Expand Up @@ -26,4 +26,5 @@ libjansson_la_LDFLAGS = \
-no-undefined \
-export-symbols-regex '^json_|^jansson_' \
-version-info 17:0:13 \
@JSON_SYMVER_LDFLAGS@ \
@JSON_BSYMBOLIC_LDFLAGS@

0 comments on commit 32fc048

Please sign in to comment.