Rosen Penev [Fri, 18 Dec 2020 03:59:37 +0000 (19:59 -0800)]
fix compilation with clang
Fixes the following warning:
json_pointer.c:230:7: warning: implicit declaration of function
'vasprintf' is invalid in C99 [-Wimplicit-function-declaration]
rc = vasprintf(&path_copy, path_fmt, args);
The array_list_new2 function, which is externally reachable through
json_object_new_array_ext, does not check if specified initial size
actually fits into memory on 32 bit architectures.
It also allows negative values, which could lead to an overflow on these
architectures as well. I have added test cases for these situations.
While at it, also protect array_list_shrink against too large
empty_slots argument. No test added because it takes a huge length
value, therefore a lot of items within the array, to overflow the
calculation. In theory this affects 64 bit sytems as well, but since the
arraylist API is not supposed to be used by external applications
according to its header file, the call is protected due to int
limitation of json_object_array_shrink.
The allocation of printbuf_new might fail. Return NULL to indicate tis
error to the caller. Otherwise later usage of the returned tokener would
lead to null pointer dereference.
Several issues occur if a string is longer than INT_MAX:
- The function json_object_get_string_len returns the length of a string
as int. If the string is longer than INT_MAX, the result would be
negative.
- That in turn would lead to possible out of boundary access when
comparing these strings with memcmp and the returned length as done in
json_object_equal.
- If json_escape_str is called with such strings, out of boundary
accesses can occur due to internal int handling (also fixed).
- The string cannot be printed out due to printbuffer limits at
INT_MAX (which is still true after this commit).
Such huge strings can only be inserted through API calls at this point
because input files are capped at INT_MAX anyway.
Due to huge amount of RAM needed to reproduce these issues I have not
added test cases.
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/
Alan Coopersmith [Thu, 30 Jul 2020 23:13:04 +0000 (16:13 -0700)]
Use getrandom() if available in json_c_get_random_seed
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.
Issue #594 - provide an OVERRIDE_GET_RANDOM_SEED cmake variable to override json_c_get_random_seed() for embedded platforms where time(NULL) doesn't work.
Example:
mkdir build && cd build
cmake -DOVERRIDE_GET_RANDOM_SEED='do { extern uint32_t getMsTicks(void); int ms = getMsTicks() * 433494437; return ms; } while(0)' ..
Don't export json-c symbols starting with an underscore, put deprecated exports into a "JSONC_PRIVATE" version, and note stuff to do during releases.
See also PR #639 and issue #621
Simon McVittie [Mon, 29 Jun 2020 17:16:34 +0000 (18:16 +0100)]
build: Add symbol versions to all exported symbols
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>
Use constants referring to the signed integer types when setting SSIZE_T_MAX.
In practice, the sizes of the signed and unsigned integer types will
almost cetainly be the same, but this is more correct.
Pointed out in issue #638.
In the json_tokener_state_number case, explicitly adjust what "number" characters are allowed based on the exact micro-state that we're in, and check for invalid following characters in a different way, to allow a valid json_type_number object to be returned at the top level.
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().
Fix incremental parsing of invalid numbers with exponents, such as "0e+-" and "12.3E12E12", while still allowing "0e+" in non-strict mode.
Deprecate the json_parse_double() function from json_util.h
Issue #616: Change the parsing of surrogate pairs in unicode escapes so it uses a couple of additional states instead of assuming the low surrogate is already present, to ensure that we correctly handle various cases of incremental parsing.
In test_parse, fix lengths passed during a couple of incremental tests.
Add an optional way to use an incremental chunk size ($TEST_PARSE_CHUNKSIZE)
for all of the single_basic_parse tests, in additional to the regular way.
Rearrange the json_tokener_state_escape_unicode case in json_tokener to simplify the code slightly and make it a bit easier to understand.
While here, drop the utf8_replacement_char that is unnecesarily added if we run out of input in the middle of a unicode escape. No other functional changes (yet).
Add json_object_array_shrink() (and array_list_shrink()) and use it in json_tokener to minimize the amount of memory used. This results in a 39%-50% reduction in memory use (peak RSS, peak heap usage) on the jc-bench benchmark and 9% shorter runtime.
Also add the json_object_new_array_ext, array_list_new2, and array_list_shrink functions.
Micah Snyder [Sun, 14 Jun 2020 16:01:48 +0000 (12:01 -0400)]
Issue #508: `-fPIC` to link libjson-c.a with libs
json-c has symbol collisions with other popular C JSON libraries.
To prevent random crashes in downstream applications that may use a
library which depends on json-c, the solution is to statically link
libjson-c.a into those libraries.
`-fPIC`/`-fPIE` is required when building a `.a` so it can be linked
into a `.so`.
Drop the _delete field from struct json_object and call the type-specific delete functions directly from json_object_put. (Thanks @dota17 for the suggestion in PR #632!)
The split of json_object into type-specific sub-structures is now functionally complete.
Remove all of the temporary defines, structures, old compat fuctions, extra fields, etc... that were needed during the conversion to a split set of json_object_* structures.
Kick json_type_string out of struct json_object.
The default is now that string data is stored inline at the end of json_object, though to allow for json_object_set_string() to set a _longer_ string, we still need to allow for the possibility of a separate char * pointer.
All json types have been split out now, next step it cleanup.
Kick json_type_int and json_type_double out of struct json_object.
Clean up the code in json_object_new_* a bit by dropping unnecesary json_object_base variables.