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: https://github.com/akheron/jansson/issues/523
(when combined with an equivalent change to json-c).
Signed-off-by: Simon McVittie <smcv@collabora.com>
The function vsnprintf returns a negative value on error, e.g. on
an invalid format. It's best to return NULL in such a case.
Also avoid a signed integer overflow if vsnprintf returns INT_MAX.
This is undefined behaviour in C and has to be avoided.
A negative value is returned with a call like:
json_sprintf("%111111111111111s", "", "");
INT_MAX is returned with a call like:
json_sprintf("%647s%2147483000s", "", "");
Support merging values nested within objects. For instance, merging:
{
"foo": 1,
"bar": {
"baz": 2
}
}
with
{
"bar": {
"baz": 3
}
}
results in
{
"foo": 1,
"bar": {
"baz": 3
}
}
instead of overwriting the value for the bar key.