Casting time(2) return value to int and multiplying the result with
such a constant will definitely lead to a signed overflow by this day.
Since signed overflows are undefined behaviour in C, avoid this.
Casting to unsigned is more than enough since the upper bits of a
64 bit time_t value will be removed with the int conversion anyway.
The function _json_c_strerror does not properly format unknown errnos.
The int to ascii loop ignores the leading digit if the number can be
divided by 10 and if an errno has been formatted, shorter errnos would
not properly terminate the newly created string, showing the ending
numbers of the previous output.
A test case has been added to show these effects.
Since this function has been introduced for tests, the effect of this on
real life code is basically non-existing. First an environment variable
has to be set to activate this strerror code and second an unknown errno
would have to be encountered.
The json-c library is used in cryptsetup for LUKS2 header information.
Since cryptsetup can be called very early during boot, the developers
avoid getrandom() calls in their own code base for now. [1]
Introducing a blocking getrandom() call in json-c therefore introduces
this issue for cryptsetup as well. Even though cryptsetup issues do not
have to be json-c issues, here is my proposal:
Let's use a non-blocking call, falling back to other sources if the call
would block. Since getrandom() accesses urandom, it must mean that we
are in an early boot phase -- otherwise the call would not block
according to its manual page.
As stated in manual page of random(4), accessing /dev/urandom won't
block but return weak random numbers, therefore this fallback would work
for json-c.
While at it, fixed the debug message.
[1] https://gitlab.com/cryptsetup/cryptsetup/-/merge_requests/47
which references to https://lwn.net/Articles/800509/
Whilst working on the Reproducible Builds effort [0] I noticed that
json-c could not be built reproducibly.
This is because it used the full, absolute path name as an (sanitised)
input to a filename, resulting in some binary package containing, for
example:
/usr/share/doc/libjson-c-dev/html/md__build_1st_json-c-0_815_issues_closed_for_0_813.html
^^^^^^^^^^^^^^^^^^^^^^
or
/usr/share/doc/libjson-c-dev/html/md__build_2_json-c-0_815_2nd_issues_closed_for_0_813.html
^^^^^^^^^^^^^^^^^^^^^^^^
These differing values are based on the path in which json-c is built. This was
originally filed in Debian as #966657 [1].
[0] https://reproducible-builds.org/
[1] https://bugs.debian.org/966657
Lower overhead than opening & reading from /dev/urandom, and works
in chroots and other situtations where /dev/urandom is not available.
Falls back to existing methods when kernel doesn't support the syscall.
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>
This causes previously failing strings like "123-456" to return a valid json_object with the appropriate value. If you care about the trailing content, call json_tokener_parse_ex() and check the parse end point with json_tokener_get_parse_end().