117 Commits

Author SHA1 Message Date
Eric Hawicz
52ddfb35f1 Fix memory leak in test_safe_json_pointer_set, the caller must free the passed value when json_pointer_set failed. Also, reformat. 2026-02-19 19:05:10 -05:00
Eric Hawicz
8c987e0b73 Issue #919: Fix build on non-x86 windows. Patch thanks to @dotanbrk 2026-02-19 18:48:05 -05:00
Eric Hawicz
d7f14cb330 Merge pull request #917 from thely314/fix/oom-too-large-index
Fix: OOM vulnerability cause by is_valid_index
2026-02-14 17:23:49 -05:00
lone
c293d9b61c general callback, safer API & related tests
- Changed json_pointer_set_with_array_cb to json_pointer_set_with_cb, related cb updated
- Added tests(test_safe_json_pointer_set.*) for new-exported funcs, also updated cmake & meson

Signed-off-by: lone <lonechan314@qq.com>
2026-02-09 14:01:38 +08:00
Eric Hawicz
8c01a7c32f Merge pull request #903 from neheb/1
Some checks failed
meson / Linux-GCC (13) (push) Has been cancelled
meson / Linux-GCC (9) (push) Has been cancelled
meson / Linux-Clang (22) (push) Has been cancelled
meson / Linux-Clang (9) (push) Has been cancelled
meson / VisualStudio (x64) (push) Has been cancelled
meson / VisualStudio (x86) (push) Has been cancelled
meson / VisualStudio-clang-cl (push) Has been cancelled
meson / MSYS2 (CLANG64) (push) Has been cancelled
meson / MSYS2 (UCRT64) (push) Has been cancelled
meson / Cygwin (push) Has been cancelled
meson / MacOS (push) Has been cancelled
meson / DragonflyBSD (push) Has been cancelled
meson / FreeBSD (push) Has been cancelled
meson / NetBSD (push) Has been cancelled
meson / OmniOS (push) Has been cancelled
meson / OpenBSD (push) Has been cancelled
meson / Alpine (aarch64) (push) Has been cancelled
meson / Alpine (armhf) (push) Has been cancelled
meson / Alpine (armv7) (push) Has been cancelled
meson / Alpine (ppc64le) (push) Has been cancelled
meson / Alpine (riscv64) (push) Has been cancelled
meson / Alpine (s390x) (push) Has been cancelled
meson / Alpine (x86) (push) Has been cancelled
meson / Alpine (x86_64) (push) Has been cancelled
meson: use override_dependency
2026-02-08 17:08:04 -05:00
Rosen Penev
d61b41c8bb github CI: add
Signed-off-by: Rosen Penev <rosenp@gmail.com>
2026-02-05 13:46:00 -08:00
Rosen Penev
1d4885ad09 fix compilation with clang-cl
Something in the configure stage goes wrong where it believe strncasecmp
is present but the header defining it is not. Work around this.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2026-02-05 13:46:00 -08:00
Rosen Penev
92a4911e88 meson: use static library for tests
Needed as tests use private APIs that are not exported.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2026-02-05 13:46:00 -08:00
Rosen Penev
798d8f7235 meson: add license information
Signed-off-by: Rosen Penev <rosenp@gmail.com>
2026-02-05 13:21:54 -08:00
Rosen Penev
a0c6bb32dd meson: simplify __thread check and fix MinGW
> was missing.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2026-02-05 13:21:54 -08:00
Rosen Penev
af2671a212 meson: use override_dependency
Allows wraps to use the dependency_names syntax instead of the possibly
changing variable syntax.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2026-02-05 13:21:54 -08:00
Eric Hawicz
46defb4349 Merge pull request #915 from jaisonZheng/fix-macos-locale-memory-leak
Fix memory leak on macOS by auto-enabling NEWLOCALE_NEEDS_FREELOCALE
2026-01-31 13:22:57 -05:00
lone
bda8299eb1 fix: adapt to the early C std
Signed-off-by: lone <lonechan314@qq.com>
2026-01-27 14:43:56 +08:00
lone
1c3b98ddb5 amend: removed marco related logic
Signed-off-by: lone <lonechan314@qq.com>
2026-01-26 17:54:53 +08:00
lone
22e470ac5c Fix: try to make json_pointer_set_with_array_cb a public api
make json_pointer_set_with_array_cb a public api, along with a function with wrapped callback

Signed-off-by: lone <lonechan314@qq.com>
2026-01-26 17:33:00 +08:00
lone
3d86402028 Fix: OOM vulnerability cause by is_valid_index
An OOM vulnerability exists in the json_pointer_set function (and related functions).
See issue #916 for more details.

To fix that, added a sanity check in the is_valid_index function to limit the maximum value of a parsed array index.
Provided a configurable macro for modification.

Signed-off-by: lone <lonechan314@qq.com>
2026-01-25 23:54:27 +08:00
JaisonZheng
653a12c7c2 Fix memory leak on macOS by auto-enabling NEWLOCALE_NEEDS_FREELOCALE
macOS's newlocale() does not follow POSIX specification - it doesn't
reuse the passed locale_t, causing ~1,472 bytes leak per json_tokener_parse() call.

This is the same issue as #668 (FreeBSD). The existing workaround works,
but macOS was not auto-detected.

Tested with AddressSanitizer: leak drops from 1,472,000 bytes to ~120 bytes
(system init only).
2026-01-21 17:28:20 +08:00
Eric Hawicz
d05ea4851f Update ChangeLog, abi-check.sh, AUTHORS and issues_closed list for an upcoming 0.19 release. 2026-01-19 17:46:57 -05:00
Eric Hawicz
8948568031 Merge pull request #913 from mlocati-forks/dll-versioninfo
Add VERSIONINFO to libjson-c.dll
2026-01-18 15:25:29 -05:00
Michele Locati
b01b5b701b Add VERSIONINFO to libjson-c.dll 2026-01-18 20:23:50 +01:00
Eric Hawicz
26fcd8d569 Merge pull request #910 from bhaible/support-msvc-with-autoconf
Support MSVC in packages that use GNU Autoconf.
2026-01-09 23:18:40 -05:00
Bruno Haible
9774826e79 Support MSVC in packages that use GNU Autoconf.
Fixes https://github.com/json-c/json-c/issues/909

When ssize_t is defined as a macro, typically through a package's config.h file,
the installed json*.h files must not attempt to define ssize_t via typedef.
2026-01-09 23:51:43 +01:00
Eric Hawicz
14c8e2e5ee Merge pull request #907 from travier/master-cmake4
tests/CMakeLists: Allow build with CMake 4
2025-12-29 23:42:24 -05:00
Timothée Ravier
e4b9dfba49 tests/CMakeLists: Allow build with CMake 4
See: https://github.com/json-c/json-c/issues/889
2025-12-23 11:52:43 +01:00
Eric Hawicz
a1249bfda0 Merge pull request #905 from glance-/fix-typo
Fix typo
2025-12-01 06:37:11 -05:00
Anton Lundin
dc44b05961 Fix typo
That include line wasn't valid code, so that resulted in:
Checking for size of "size_t" : -1

And later on:
json-c/json_patch.c:28:2: error: #error Unable to determine size of size_t
2025-12-01 11:37:59 +01:00
Eric Hawicz
20974e5f88 Merge pull request #904 from Lakshmi-Surekha/aix-getopt-dont-include
Include getopt.h header file if the platform is not AIX.
2025-11-29 11:40:00 -05:00
Lakshmi-Surekha
a7b34a299b apps: use CMake check for getopt.h
Add CMake detection for getopt.h and update json_parse.c to include it
only when HAVE_GETOPT_H is defined. Fixes AIX build failure.
2025-11-29 01:32:10 -06:00
Eric Hawicz
243ed1a51c Merge pull request #900 from neheb/1
meson cleanups
2025-11-04 18:32:47 -05:00
Rosen Penev
f565798e2c meson: remove useless if
get_supported_arguments already handles this.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2025-11-04 10:45:20 -08:00
Rosen Penev
8c012da8a6 meson: add header to size_t check
Might be needed under MSVC.
2025-11-04 10:45:20 -08:00
Rosen Penev
bd7355470e meson: replace target_machine with host_machine
The latter is the canonical way to express this.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2025-11-04 10:45:20 -08:00
Rosen Penev
40fe4d2b04 meson: use loops for checks
All of these are effectively the same. No point in duplicating it
everywhere.

Remove prefix from has_function. Apparently having the prefix in there
changes behavior.

Also fix an error on MinGW where SSIZE_T_MAX is undefined.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2025-11-04 10:44:42 -08:00
Eric Hawicz
2c412d4593 Merge pull request #899 from Seagate/meson_support
Meson support
2025-10-27 16:00:37 -04:00
Tyler Erickson
0883c24130 Merge branch 'json-c:master' into meson_support 2025-10-27 12:13:23 -06:00
Eric Hawicz
fbdd4bed24 Merge pull request #898 from Seagate/fix_cmake_clangcl
bug: Fixing Cmake build when using clang-cl
2025-10-25 09:46:22 -04:00
Eric Hawicz
33f4cb9353 Merge pull request #895 from nim65s/patch-1
CMake: sync minimum version
2025-10-25 09:45:50 -04:00
Tyler Erickson
a5bc36de26 Removing werror option as meson has a built-in option for this
Signed-off-by: Tyler Erickson <tyler.erickson@seagate.com>
2025-10-24 09:48:56 -06:00
Tyler Erickson
3723b182db bug: Fixing runtime issue with test_util_file.c in Windows
Windows was failing tests due to how the Windows API works with some of the calls used.
When opening and reading a file O_BINARY is needed otherwise it fails for size checks. This is due to how Windows handles newlines and counts between text and binary mode file reads.

Also fixed is the test for /dev/null.
In Windows, this fails, but crashes due to a missing return statement when it cannot open this file.
I also tried telling windows to open the special file NUL, however that leads to a CRT crash later in the test that cannot be stopped and will always fail. Rather than fail a test that Windows will always fail, it has been disabled in that specific case.

Signed-off-by: Tyler Erickson <tyler.erickson@seagate.com>
2025-10-20 12:10:57 -06:00
Tyler Erickson
e3a33ae8ae make: Adding support for building json-c with meson
Adding meson build files for json-c that work similarly to the cmake build files.
Where it made sense, I reused existing cmake .h.in files or generated entirely from meson.
All tests were done with GCC and Clang in ubuntu 24.04, Windows using MSVC 2022 and Clang-cl from llvm's repo using version 21.1.3

Signed-off-by: Tyler Erickson <tyler.erickson@seagate.com>
2025-10-20 12:08:01 -06:00
Tyler Erickson
461d9f90c4 bug: Fixing Cmake build when using clang-cl
Clang-cl will fail to build and produce warnings about redefining existing symbols, mostly for float.h and math.h compatibility.

To resolve this, this moves the clang-cl detection earlier in the CMakeLists.txt so that CLANG_CL can be checked properly where there is an existing MSVC workaround for these symbols.
This resolves the build using the latest clang-cl from the LLVM clang repo as well as clang-cl that can be installed with MSVC 2022.

Signed-off-by: Tyler Erickson <tyler.erickson@seagate.com>
2025-10-20 11:39:04 -06:00
Eric Hawicz
2372e9518e Merge pull request #893 from sffc/supplemental-code-point-bug
Fix bug involving supplemental code points that look like high surrogates
2025-08-07 09:46:47 -04:00
Guilhem Saurel
8af05ab785 CMake: sync minimum version 2025-08-06 22:10:41 +02:00
Shane F. Carr
7974657c56 Fix code and update tests 2025-07-30 17:40:56 -07:00
Shane F. Carr
dbefb48948 Add tests with current behavior 2025-07-30 17:39:47 -07:00
Eric Hawicz
bf92456789 Make json_parse a bit more useful by adding -u (validate UTF8) and -P (specify arbitrary tokener parse flags), and read from stdin if no filename is provided. 2025-07-08 21:04:00 -04:00
Eric Hawicz
7cee5237dc Issue #867 - also disallow control characters in keys 2025-04-03 21:16:29 -04:00
Eric Hawicz
7bca694b47 Merge pull request #884 from careles/mingw_win64-WIN32_LEAN_AND_MEAN-redefined
fix macro WIN32_LEAN_AND_MEAN redefined
2025-01-09 00:12:09 -05:00
Careles
51bcdd0000 fix macro WIN32_LEAN_AND_MEAN redefined
json-c as add_subdirectory and project cmakelists.txt has add_definitions(-DWIN32_LEAN_AND_MEAN)
2025-01-06 10:56:53 +08:00
Eric Hawicz
a304464807 Merge pull request #872 from GitMensch/patch-2
fix linkhash breaking -std=c89
2024-12-29 13:34:38 -05:00
Eric Hawicz
7b73916815 Merge pull request #847 from sacredbanana/amiga
Add support for Commodore Amiga
2024-12-29 13:26:11 -05:00
Eric Hawicz
ee83daa409 Merge pull request #882 from simonresch/handle-nan-to-int-conversion
Explicitly handle NaN values when converting to integer
2024-12-26 19:07:07 -05:00
Cameron Armstrong (Nightfox)
ca1a6b0cc9 Add support for MorphOS 2024-12-24 10:09:50 +08:00
Cameron Armstrong (Nightfox)
daff6eb746 Remove linking to libamiga and libc 2024-12-24 10:09:50 +08:00
Cameron Armstrong (Nightfox)
254b5abef8 Do not use duplocale if building for libnix because it isnt supported yet 2024-12-24 10:09:50 +08:00
Cameron Armstrong (Nightfox)
d31d635af1 Clean up CMakeLists.txt and remove Amiga specific locale.h guard 2024-12-24 10:09:50 +08:00
Cameron Armstrong (Nightfox)
743ebf53e5 Fix Readme 2024-12-24 10:09:50 +08:00
Cameron Armstrong
f928e7c0fa Get working ror libnix and clib2 2024-12-24 10:09:50 +08:00
Cameron Armstrong
4feebc1cd6 Add support for Commodore Amiga 2024-12-24 10:09:50 +08:00
Eric Hawicz
961c31f8ed Merge pull request #879 from janotomko/null
Handle NULL gracefully in json_tokener_free
2024-12-07 13:33:05 -05:00
Simon Resch
0c3588330a Set error codes for truncating int conversions
json_object_get_int/int64/uint64() now sets errno to ERANGE when the source value
can't be represented in the target type.
2024-11-27 07:17:20 +01:00
Simon Resch
8c13801f2c Explicitly handle NaN values when converting to int
Json objects of type double with the value NaN could cause undefined
behavior when casting double to int in `json_object_get_int`.
2024-11-27 07:17:20 +01:00
Eric Hawicz
c63d4a4194 Merge pull request #878 from 0xfadead/readme-fix-underline
Fix underline bug in README
2024-11-23 19:39:50 -05:00
Eric Hawicz
77bb5c54fc Merge pull request #883 from simonresch/add-oss-fuzz-tests
Add fuzz tests for json_object/point/array apis
2024-11-23 19:39:13 -05:00
Simon Resch
839fbe0d63 Add fuzz tests for json_object/point/array apis
Extends the coverage of fuzz tests executed in OSS-Fuzz.
2024-11-22 07:43:32 +01:00
Eric Hawicz
ff8ed0f094 Issue #881: don't allow json_tokener_new_ex() with a depth < 1 2024-11-17 22:11:24 -05:00
Eric Hawicz
565f181f65 Fix issue #875: cast to unsigned char so bytes above 0x7f aren't interpreted as negative, which was causing the strict-mode control characters check to incorrectly trigger. 2024-11-08 22:20:40 -05:00
Ján Tomko
828c12b226 Handle NULL gracefully in json_tokener_free
Similarly to glibc's free, make json_tokener_free(NULL)
a no-op, to simplify cleanup paths.

Signed-off-by: Ján Tomko <jtomko@redhat.com>
2024-11-06 15:23:00 +01:00
Eric Hawicz
474ee12435 Fix the apps/json_parse "-s" (strict) option so it actually does something, and default to non-strict. 2024-11-03 19:44:21 -05:00
Awildidiot
d6b973e047 Fix underline bug in README 2024-11-03 20:03:49 +01:00
Eric Hawicz
07148f33a1 Merge pull request #873 from esiaero/master
Correct year in changelog for 0.18 release
2024-10-10 20:55:18 -04:00
Evan Si
2ec0b87b58 Correct year in changelog for 0.18 release 2024-10-10 23:47:55 +00:00
Simon Sobisch
6aab3da807 fix linkhash breaking -std=c89
making the definition of _LH_INLINE depending on __STDC_VERSION__, not on a specific compiler
2024-10-07 08:16:42 +00:00
Eric Hawicz
c793374f16 Update openssl command to work for newer versions of openssl. 2024-09-15 13:16:48 -04:00
Eric Hawicz
e9bd26d568 Update the master branch to version 0.18.99 2024-09-15 13:06:06 -04:00
Eric Haszlakiewicz
7ebdc4ddf8 Update abi-check.sh to compare 0.16 and 0.18 2024-09-15 16:10:57 +00:00
Eric Hawicz
87900c0a2e Fix the expected output for test_parse 2024-09-15 11:59:05 -04:00
Eric Hawicz
e5ca4d3b3d Update ChangeLog, AUTHORS and issues_closed_for_0.18.md for an upcoming 0.18 release. 2024-09-15 11:54:50 -04:00
Eric Hawicz
e3db88d114 Merge pull request #871 from json-c/disallow-control-chars
Issue #867: disallow control characters in strict mode.
2024-09-15 11:22:58 -04:00
Eric Hawicz
6bfab90c87 Issue #867: disallow control characters in strict mode. 2024-09-15 10:37:45 -04:00
Eric Hawicz
ecb7a4c9a3 Merge pull request #864 from pavelzw/patch-1
Build pkg-config for msvc as well
2024-08-29 21:08:52 -04:00
Pavel Zwerschke
906d1581de Update CMakeLists.txt 2024-08-29 10:55:02 +02:00
Pavel Zwerschke
9b8d170d1f Build pkg-config for msvc as well 2024-06-18 00:11:13 +02:00
Eric Hawicz
6e481aa061 Merge pull request #861 from bhaible/handle-another-oom-condition
Handle yet another out-of-memory condition.
2024-05-05 09:49:26 -04:00
Eric Haszlakiewicz
781675758f Although CMAKE_C_COMPILER_FRONTEND_VARIANT is defined, it's not always set to some value. Fix builds for cases when it's blank. 2024-04-28 17:15:42 +00:00
Bruno Haible
833233faa8 Handle yet another out-of-memory condition.
duplocale() can return NULL, with errno set to ENOMEM.
In this case, bail out and set the current error code to
json_tokener_error_memory.
2024-04-22 01:54:10 +02:00
Eric Hawicz
31a22fb2da Issue #857: fix a few places where json_tokener should have been returning json_tokener_error_memory but wasn't. 2024-04-21 10:37:16 -04:00
Eric Hawicz
0051f2dbe0 Merge pull request #858 from alurm/master
json_tokener.h: json_tokener_parse_verbose: fix typo
2024-04-16 11:23:09 -04:00
Alan Urmancheev
0741ce3918 json_tokener.h: json_tokener_parse_verbose: fix typo 2024-04-16 14:56:00 +00:00
Eric Hawicz
e3464a2ab4 Issue #829: attempt to detect clang-cl.exe and pass MSVC-compatile command line arguments. 2024-03-29 22:40:45 -04:00
Eric Hawicz
61016412fb Issue #850: fill in & adjust the "@returns" docs for several functions. 2024-03-29 18:46:05 -04:00
Eric Hawicz
f2eac07129 doxygen can't handle html on heading, split that to separate lines
https://github.com/doxygen/doxygen/issues/10466
2024-03-29 18:45:22 -04:00
Eric Hawicz
e93ae70417 Fix issue #854: Set error=json_tokener_error_memory in json_tokener_parser_verbose() when allocating the tokener fails. 2024-03-29 18:09:12 -04:00
Eric Hawicz
0bc2dd5e60 Merge pull request #852 from fedefrancescon/docs/micro-typo-fix
docs: micro typo in json_object_put doc
2024-03-02 17:31:24 -05:00
Federico Francescon
9c44c7ed52 docs: micro typo in json_object_get doc 2024-03-02 22:41:10 +01:00
Eric Hawicz
401249cbdf Merge pull request #831 from neheb/1
rename WIN32 to _WIN32
2024-02-08 08:11:57 -05:00
Rosen Penev
66f7869219 rename WIN32 to _WIN32
The latter is the proper macro defined by Windows headers.

Fixes compilation under at least clang-cl which mandates function
declarations.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2024-02-07 18:06:55 -08:00
Eric Hawicz
dabed80523 Merge pull request #849 from rouault/random_seed_toctou
random_seed.c: add a Coverity Scan suppression
2024-01-08 12:45:39 -05:00
Even Rouault
f6c8eba84e random_seed.c: add a Coverity Scan suppression
Coverity Scan warns about the use of open() after stat() being a
potential TOCTOU (Time of check time of use) issue. But here there is no
such issue.
2024-01-07 20:55:38 +01:00
Eric Hawicz
76f819e51d Merge pull request #846 from evo-i/CMP0153
Use execute_process instead of exec_program
2023-12-17 07:23:07 -05:00
evo
eef983b1df Update CMakeLists.txt
Replace with `execute_process` available on v3.0+
2023-12-17 11:19:20 +03:00
evo
c0cf4bc23b Update CMakeLists.txt
Now saved to variable.
2023-12-17 00:32:21 +03:00
evo
e85c8ada54 Fix ECHO_OUTPUT_VARIABLE 2023-12-17 00:23:51 +03:00
evo
2c84476c77 [CMP0153](https://cmake.org/cmake/help/latest/policy/CMP0153.html) 2023-12-12 16:28:41 +03:00
Eric Haszlakiewicz
407ddb4350 Issue #842 - fix one particular sign conversion warning.
There are many others that show up if we were to add -Wsign-conversions,
but this is the only one using a literal constant.
2023-11-30 13:59:13 +00:00
Eric Hawicz
33337523f5 Merge pull request #839 from ffontaine/master
json_pointer.c: initialize idx
2023-11-08 18:11:13 -05:00
Fabrice Fontaine
7ff7eab603 json_pointer.c: initialize idx
Fix the following build failure with gcc 5:

/home/thomas/autobuild/instance-2/output-1/build/json-c-0.17/json_pointer.c: In function 'json_pointer_result_get_recursive':
/home/thomas/autobuild/instance-2/output-1/build/json-c-0.17/json_pointer.c:193:25: error: 'idx' may be used uninitialized in this function [-Werror=maybe-uninitialized]
    res->index_in_parent = idx;
                         ^

Fixes:
 - http://autobuild.buildroot.org/results/523b35a979d59121fe4e18c38171792b06233940/

Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
2023-11-08 22:42:48 +01:00
Eric Hawicz
88bce2b38e Merge pull request #837 from HansolChoe/fix-tokener-parse-ex-fuzzer
Add type checking for parsed objects in tokener_parse_ex_fuzzer
2023-10-19 07:49:32 -04:00
HansolChoe
a907f7dd1b tokener_parse_ex_fuzzer: add type checking for parsed object 2023-10-19 16:55:15 +09:00
Eric Hawicz
ad8b8afa7d Take 2 fixing the placement of json_tokener_error_memory in the enum. (json_tokener_error_size is an actual error, *not* a measure of the size of the enum!) 2023-09-22 22:26:21 -04:00
Eric Hawicz
4186537557 Merge pull request #827 from robert-pang/master
Resolve build issue in tokener_parse_ex_fuzzer.c
2023-09-11 00:13:45 +02:00
Eric Hawicz
9ff6b68baf Merge pull request #826 from emlix/cmake-policies
CMake: remove needless policy setting
2023-09-11 00:10:55 +02:00
Robert Pang
1a7defaa69 Fix variable and API names in tokener_parse_ex_fuzzer.cc to resolve build issue. 2023-09-05 13:58:51 -07:00
Rolf Eike Beer
c4a615a052 CMake: request all policies up to CMake 3.12 being set to NEW 2023-09-05 14:31:24 +02:00
Rolf Eike Beer
159822dd8a CMake: request consistent minimum version 2023-09-05 14:31:14 +02:00
Rolf Eike Beer
990acb4e19 CMake: remove needless policy setting
These policies were all introduced before CMake 3.9, so they will automatically
be initialized to the new behavior when requesting a minimum version of 3.9.
2023-09-05 12:14:46 +02:00
Eric Haszlakiewicz
502522a93d Update the master branch to version 0.17.99 2023-08-12 19:08:59 +00:00
54 changed files with 2221 additions and 193 deletions

228
.github/workflows/meson.yml vendored Normal file
View File

@@ -0,0 +1,228 @@
name: meson
on: [push, pull_request]
concurrency:
group: ${{github.workflow}}-${{github.head_ref}}
cancel-in-progress: true
jobs:
Linux-GCC:
runs-on: ubuntu-22.04
strategy:
matrix:
cc: ['9', '13']
steps:
- uses: actions/checkout@v4
- uses: egor-tensin/setup-gcc@v1
with:
version: ${{matrix.cc}}
- name: Install packages
run: |
python3 -m pip install meson ninja
- name: Compile and Test
run: |
meson setup "${{github.workspace}}/build" -Dwarning_level=3 -Dbuildtype=debug
meson compile -C "${{github.workspace}}/build" --verbose
meson test -C "${{github.workspace}}/build" --verbose
Linux-Clang:
runs-on: ubuntu-22.04
strategy:
matrix:
cc: ['9', '22']
steps:
- uses: actions/checkout@v4
- uses: egor-tensin/setup-clang@v1
- name: Install packages
run: |
python3 -m pip install meson ninja
- name: Compile and Test
run: |
meson setup "${{github.workspace}}/build" -Dwarning_level=3 -Dbuildtype=debug
meson compile -C "${{github.workspace}}/build" --verbose
meson test -C "${{github.workspace}}/build" --verbose
VisualStudio:
runs-on: windows-latest
strategy:
matrix:
platform: ['x64', 'x86']
steps:
- uses: actions/checkout@v4
- name: Install packages
run: |
python -m pip install meson ninja
- uses: ilammy/msvc-dev-cmd@v1
with:
arch: ${{matrix.platform}}
- name: Compile and Test
env:
CFLAGS: '/analyze'
run: |
meson setup "${{github.workspace}}/build" --wrap-mode=forcefallback -Dwarning_level=3 -Dbuildtype=debug
meson compile -C "${{github.workspace}}/build" --verbose
meson test -C "${{github.workspace}}/build" --verbose
VisualStudio-clang-cl:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Install packages
run: |
python -m pip install meson ninja
- uses: ilammy/msvc-dev-cmd@v1
- name: Compile and Test
env:
CC: clang-cl
run: |
meson setup "${{github.workspace}}/build" -Dwarning_level=3 -Dbuildtype=debug
meson compile -C "${{github.workspace}}/build" --verbose
meson test -C "${{github.workspace}}/build" --verbose
MSYS2:
runs-on: windows-latest
strategy:
matrix:
platform: ['UCRT64', 'CLANG64']
defaults:
run:
shell: msys2 {0}
steps:
- uses: actions/checkout@v4
- uses: msys2/setup-msys2@v2
with:
msystem: ${{matrix.platform}}
pacboy: >-
cc:p
cmake:p
meson:p
ninja:p
pkgconf:p
- name: Compile and Test
run: |
meson setup "${{github.workspace}}/build" -Dwarning_level=3 -Dbuildtype=debug
meson compile -C "${{github.workspace}}/build" --verbose
meson test -C "${{github.workspace}}/build" --verbose
Cygwin:
runs-on: windows-latest
defaults:
run:
shell: msys2 {0}
steps:
- uses: actions/checkout@v4
- uses: msys2/setup-msys2@v2
with:
msystem: 'MSYS'
install: >-
gcc
meson
ninja
- name: Compile and Test
run: |
meson setup build -Dwarning_level=3 -Dcpp_std=gnu++20 -Dbuildtype=debug
meson compile -C build --verbose
meson test -C build --verbose
MacOS:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Install packages
run: |
brew install meson
- name: Compile and Test
run: |
meson setup "${{github.workspace}}/build" -Dwarning_level=3 -Dbuildtype=debug
meson compile -C "${{github.workspace}}/build" --verbose
meson test -C "${{github.workspace}}/build" --verbose
DragonflyBSD:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: vmactions/dragonflybsd-vm@v1
with:
prepare: |
pkg install -y ninja meson pkgconf
run: |
meson setup "${{github.workspace}}/build" -Dwarning_level=3 -Dbuildtype=debug
meson compile -C "${{github.workspace}}/build" --verbose
meson test -C "${{github.workspace}}/build" --verbose
FreeBSD:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: vmactions/freebsd-vm@v1
with:
prepare: |
pkg install -y ninja meson pkgconf
run: |
meson setup "${{github.workspace}}/build" -Dwarning_level=3 -Dbuildtype=debug
meson compile -C "${{github.workspace}}/build" --verbose
meson test -C "${{github.workspace}}/build" --verbose
NetBSD:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: vmactions/netbsd-vm@v1
with:
prepare: |
/usr/sbin/pkg_add meson pkgconf
run: |
meson setup "${{github.workspace}}/build" -Dwarning_level=3 -Dbuildtype=debug
meson compile -C "${{github.workspace}}/build" --verbose
meson test -C "${{github.workspace}}/build" --verbose
OmniOS:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: vmactions/omnios-vm@v1
with:
prepare: |
pkg install gcc14 meson-313 ninja pkg-config python-313
run: |
/usr/lib/python3.13/bin/meson setup "${{github.workspace}}/build" -Dwarning_level=3 -Dbuildtype=debug
/usr/lib/python3.13/bin/meson compile -C "${{github.workspace}}/build" --verbose
/usr/lib/python3.13/bin/meson test -C "${{github.workspace}}/build" --verbose
OpenBSD:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: vmactions/openbsd-vm@v1
with:
prepare: |
pkg_add ninja meson pkgconf
run: |
meson setup "${{github.workspace}}/build" -Dwarning_level=3 -Dbuildtype=debug
meson compile -C "${{github.workspace}}/build" --verbose
meson test -C "${{github.workspace}}/build" --verbose
Alpine:
runs-on: ubuntu-latest
strategy:
matrix:
platform: ['x86_64', 'x86', 'armhf', 'armv7', 'aarch64', 'ppc64le', 'riscv64', 's390x']
defaults:
run:
shell: alpine.sh {0}
steps:
- uses: actions/checkout@v4
- uses: jirutka/setup-alpine@v1
with:
branch: edge
arch: ${{matrix.platform}}
packages: >
build-base pkgconf meson samurai
- name: Compile and Test
run: |
meson setup "${{github.workspace}}/build" -Dwarning_level=3 -Dbuildtype=debug
meson compile -C "${{github.workspace}}/build" --verbose
meson test -C "${{github.workspace}}/build" --verbose

1
.gitignore vendored
View File

@@ -10,6 +10,7 @@
*.save *.save
*.autosav *.autosav
*.autosave *.autosave
.DS_Store
# Tests # Tests
/tests/Makefile /tests/Makefile

23
AUTHORS
View File

@@ -1,11 +1,17 @@
Alan Coopersmith <alan.coopersmith@oracle.com> Alan Coopersmith <alan.coopersmith@oracle.com>
Alan Urmancheev <108410815+alurm@users.noreply.github.com>
Alexander Dahl <post@lespocky.de> Alexander Dahl <post@lespocky.de>
Alexandru Ardelean <ardeleanalex@gmail.com> Alexandru Ardelean <ardeleanalex@gmail.com>
An7ar35 <eadavison@protonmail.com> An7ar35 <eadavison@protonmail.com>
andy5995 <andy400-dev@yahoo.com> andy5995 <andy400-dev@yahoo.com>
Anton Lundin <glance@ac2.se>
Aram Poghosyan <Aram.Poghosyan@teamviewer.com> Aram Poghosyan <Aram.Poghosyan@teamviewer.com>
Awildidiot <69577313+0xfadead@users.noreply.github.com>
Björn Esser <besser82@fedoraproject.org> Björn Esser <besser82@fedoraproject.org>
BonsaY <bonsay@posteo.de> BonsaY <bonsay@posteo.de>
Bruno Haible <bruno@clisp.org>
Cameron Armstrong <cameronscottarmstrong@gmail.com>
Careles <zhancheng1996@gmail.com>
changyong guo <guo1487@163.com> changyong guo <guo1487@163.com>
chenguoping <chenguopingdota@163.com> chenguoping <chenguopingdota@163.com>
Chris Lamb <lamby@debian.org> Chris Lamb <lamby@debian.org>
@@ -20,10 +26,15 @@ Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com>
dota17 <chenguopingdota@163.com> dota17 <chenguopingdota@163.com>
Eric Haszlakiewicz <erh+git@nimenees.com> Eric Haszlakiewicz <erh+git@nimenees.com>
Eric Hawicz <erh+git@nimenees.com> Eric Hawicz <erh+git@nimenees.com>
Evan Si <evsi@amazon.com>
Even Rouault <even.rouault@spatialys.com> Even Rouault <even.rouault@spatialys.com>
evo <149657734+evo-i@users.noreply.github.com>
Fabrice Fontaine <fontaine.fabrice@gmail.com>
Federico Francescon <federico.francescon@higeco.com> Federico Francescon <federico.francescon@higeco.com>
Gianluigi Tiesi <sherpya@netfarm.it> Gianluigi Tiesi <sherpya@netfarm.it>
grdowns <grdowns@microsoft.com> grdowns <grdowns@microsoft.com>
Guilhem Saurel <guilhem.saurel@laas.fr>
HansolChoe <hansol614@gmail.com>
Hex052 <elijahiff@gmail.com> Hex052 <elijahiff@gmail.com>
hofnarr <hofnarr@hofnarr.fi> hofnarr <hofnarr@hofnarr.fi>
ihsinme <61293369+ihsinme@users.noreply.github.com> ihsinme <61293369+ihsinme@users.noreply.github.com>
@@ -31,6 +42,7 @@ Ivan Romanov <drizt@land.ru>
Jaap Keuter <jaap.keuter@xs4all.nl> Jaap Keuter <jaap.keuter@xs4all.nl>
Jakov Smolic <jakov.smolic@sartura.hr> Jakov Smolic <jakov.smolic@sartura.hr>
janczer <menshikov.ivn@gmail.com> janczer <menshikov.ivn@gmail.com>
Ján Tomko <jtomko@redhat.com>
JC (Jonathan Chen) <jc@dijonkitchen.org> JC (Jonathan Chen) <jc@dijonkitchen.org>
Jehan <jehan@girinstud.io> Jehan <jehan@girinstud.io>
Jehiah Czebotar <jehiah@gmail.com> Jehiah Czebotar <jehiah@gmail.com>
@@ -41,6 +53,7 @@ Juuso Alasuutari <juuso.alasuutari@gmail.com>
Keith Holman <keith.holman@windriver.com> Keith Holman <keith.holman@windriver.com>
Khem Raj <raj.khem@gmail.com> Khem Raj <raj.khem@gmail.com>
Kizuna-Meraki <z9@kizunameraki.de> Kizuna-Meraki <z9@kizunameraki.de>
Lakshmi-Surekha <Lakshmi.Kovvuri@ibm.com>
Leon Gross <leon.gross@rub.de> Leon Gross <leon.gross@rub.de>
Liang, Gao <liang.gao@intel.com> Liang, Gao <liang.gao@intel.com>
Luca Mannella <luca.mannella@studenti.polito.it> Luca Mannella <luca.mannella@studenti.polito.it>
@@ -49,8 +62,10 @@ Matthias Gatto <matthias.gatto@protonmail.com>
max <mpano91@gmail.com> max <mpano91@gmail.com>
Micah Snyder <micasnyd@cisco.com> Micah Snyder <micasnyd@cisco.com>
Michael Clark <michael@metaparadigm.com> Michael Clark <michael@metaparadigm.com>
Michele Locati <michele@locati.it>
myd7349 <myd7349@gmail.com> myd7349 <myd7349@gmail.com>
Pascal Cuoq <cuoq@trust-in-soft.com> Pascal Cuoq <cuoq@trust-in-soft.com>
Pavel Zwerschke <pavelzw@gmail.com>
Pawday <pawday@mail.ru> Pawday <pawday@mail.ru>
Philosoph228 <philosoph228@gmail.com> Philosoph228 <philosoph228@gmail.com>
Pierce Lopez <pierce.lopez@gmail.com> Pierce Lopez <pierce.lopez@gmail.com>
@@ -58,14 +73,22 @@ Po-Chuan Hsieh <sunpoet@sunpoet.net>
Ramiro Polla <ramiro.polla@gmail.com> Ramiro Polla <ramiro.polla@gmail.com>
Rikard Falkeborn <rikard.falkeborn@gmail.com> Rikard Falkeborn <rikard.falkeborn@gmail.com>
Robert Bielik <robert.bielik@dirac.com> Robert Bielik <robert.bielik@dirac.com>
Robert Pang <robertpang@google.com>
Robert <roby_p97@yahoo.com> Robert <roby_p97@yahoo.com>
Rolf Eike Beer <eb@emlix.com>
Rosen Penev <rosenp@gmail.com> Rosen Penev <rosenp@gmail.com>
Rubasri Kalidas <rubasri.kalidas@intel.com> Rubasri Kalidas <rubasri.kalidas@intel.com>
Sergey Sharshunov <s.sharshunov@gmail.com> Sergey Sharshunov <s.sharshunov@gmail.com>
Shane F. Carr <shane@unicode.org>
Simon McVittie <smcv@collabora.com> Simon McVittie <smcv@collabora.com>
Simon Resch <simon.resch@code-intelligence.de>
Simon Sobisch <simonsobisch@web.de>
ssrlive <30760636+ssrlive@users.noreply.github.com> ssrlive <30760636+ssrlive@users.noreply.github.com>
Timothée Ravier <tim@siosm.fr>
Tobias Nießen <tniessen@users.noreply.github.com> Tobias Nießen <tniessen@users.noreply.github.com>
Tobias Stoeckmann <tobias@stoeckmann.org> Tobias Stoeckmann <tobias@stoeckmann.org>
Tudor Brindus <me@tbrindus.ca> Tudor Brindus <me@tbrindus.ca>
Tyler Erickson <tyler.erickson@seagate.com>
Tyler Erickson <vonericsen@gmail.com>
Unmanned Player <36690541+unmanned-player@users.noreply.github.com> Unmanned Player <36690541+unmanned-player@users.noreply.github.com>
Yurii Rashkovskii <yrashk@gmail.com> Yurii Rashkovskii <yrashk@gmail.com>

View File

@@ -3,24 +3,11 @@
# and many OpenWRT packages require, much newer CMake packages. # and many OpenWRT packages require, much newer CMake packages.
# We're stopping before 3.10 because that version starts requiring # We're stopping before 3.10 because that version starts requiring
# c++11, which isn't available on e.g HPUX. # c++11, which isn't available on e.g HPUX.
cmake_minimum_required(VERSION 3.9) cmake_minimum_required(VERSION 3.9...3.12)
# The project() command manages VERSION variables.
cmake_policy(SET CMP0048 NEW)
# JSON-C library is C only project. # JSON-C library is C only project.
# PROJECT_VERSION{,_MAJOR,_MINOR,_PATCH} set by project(): # PROJECT_VERSION{,_MAJOR,_MINOR,_PATCH} set by project():
project(json-c LANGUAGES C VERSION 0.16.99) project(json-c LANGUAGES C VERSION 0.18.99)
# Targets may not link directly to themselves.
cmake_policy(SET CMP0038 NEW)
# MACOSX_RPATH is enabled by default.
# We set it explicitly to avoid the warning
cmake_policy(SET CMP0042 NEW)
# Only interpret if() arguments as variables or keywords when unquoted.
cmake_policy(SET CMP0054 NEW)
# set default build type if not specified by user # set default build type if not specified by user
if(NOT CMAKE_BUILD_TYPE) if(NOT CMAKE_BUILD_TYPE)
@@ -29,13 +16,6 @@ endif()
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O2") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O2")
# Include file check macros honor CMAKE_REQUIRED_LIBRARIES
# i.e. the check_include_file() calls will include -lm when checking.
# New in version 3.12.
if(POLICY CMP0075)
cmake_policy(SET CMP0075 NEW)
endif()
include(CTest) include(CTest)
# Set some packaging variables. # Set some packaging variables.
@@ -65,10 +45,6 @@ include(CMakePackageConfigHelpers)
option(BUILD_SHARED_LIBS "Default to building shared libraries" ON) option(BUILD_SHARED_LIBS "Default to building shared libraries" ON)
option(BUILD_STATIC_LIBS "Default to building static libraries" ON) option(BUILD_STATIC_LIBS "Default to building static libraries" ON)
if (BUILD_SHARED_LIBS)
add_definitions(-D JSON_C_DLL)
endif()
# Generate a release merge and test it to verify the correctness of republishing the package. # Generate a release merge and test it to verify the correctness of republishing the package.
ADD_CUSTOM_TARGET(distcheck ADD_CUSTOM_TARGET(distcheck
COMMAND make package_source COMMAND make package_source
@@ -90,15 +66,68 @@ option(OVERRIDE_GET_RANDOM_SEED "Override json_c_get_random_seed() with cu
option(DISABLE_EXTRA_LIBS "Avoid linking against extra libraries, such as libbsd." OFF) option(DISABLE_EXTRA_LIBS "Avoid linking against extra libraries, such as libbsd." OFF)
option(DISABLE_JSON_POINTER "Disable JSON pointer (RFC6901) and JSON patch support." OFF) option(DISABLE_JSON_POINTER "Disable JSON pointer (RFC6901) and JSON patch support." OFF)
option(DISABLE_JSON_PATCH "Disable JSON patch (RFC6902) support." OFF) option(DISABLE_JSON_PATCH "Disable JSON patch (RFC6902) support." OFF)
option(NEWLOCALE_NEEDS_FREELOCALE "Work around newlocale bugs in old FreeBSD by calling freelocale" OFF) option(NEWLOCALE_NEEDS_FREELOCALE "Work around newlocale bugs in old FreeBSD and macOS by calling freelocale" OFF)
option(BUILD_APPS "Default to building apps" ON) option(BUILD_APPS "Default to building apps" ON)
# macOS (Darwin) has the same newlocale() bug as older FreeBSD versions:
# newlocale() does not free the locale object passed to it, causing memory leaks.
# See: https://github.com/json-c/json-c/issues/668
if(APPLE AND NOT NEWLOCALE_NEEDS_FREELOCALE)
message(STATUS "macOS detected: enabling NEWLOCALE_NEEDS_FREELOCALE to prevent memory leaks")
set(NEWLOCALE_NEEDS_FREELOCALE ON CACHE BOOL "macOS needs freelocale workaround" FORCE)
endif()
if (UNIX OR MINGW OR CYGWIN) if (AMIGA)
set(DISABLE_THREAD_LOCAL_STORAGE ON)
set(ENABLE_THREADING OFF)
set(BUILD_SHARED_LIBS OFF)
set(BUILD_APPS OFF)
set(DISABLE_STATIC_FPIC ON)
if ($ENV{CROSS_PFX} STREQUAL "m68k-amigaos")
set(AMIGA_M68K ON)
set(BUILD_TESTING OFF)
if (${M68K_CRT} STREQUAL "newlib")
set(NEWLIB ON)
elseif(${M68K_CRT} STREQUAL "clib2")
set(CLIB2 ON)
elseif(${M68K_CRT} STREQUAL "ixemul")
set(IXEMUL ON)
elseif(${M68K_CRT} STREQUAL "nix20")
set(NIX20 ON)
elseif(${M68K_CRT} STREQUAL "nix13")
set(NIX13 ON)
else()
set(NEWLIB ON)
endif()
message(STATUS "Building for Motorola 68k AmigaOS using CRT: ${M68K_CRT}")
elseif ($ENV{CROSS_PFX} STREQUAL "ppc-amigaos")
set(AMIGA_PPC ON)
message(STATUS "Building for PowerPC AmigaOS")
elseif($ENV{CROSS_PFX} STREQUAL "ppc-morphos")
set(MORPHOS ON)
if (NOIXEMUL)
message(STATUS "Building for PowerPC MorphOS without ixemul")
set(DISABLE_WERROR ON)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -noixemul")
else()
message(STATUS "Building for PowerPC MorphOS with ixemul")
endif()
else()
message(FATAL_ERROR "Unsupported AmigaOS target")
endif()
else()
message(STATUS "Building for ${CMAKE_SYSTEM_NAME}")
endif()
if (UNIX OR MINGW OR CYGWIN OR AMIGA)
list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE) list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
endif() endif()
if (UNIX) if (BUILD_SHARED_LIBS)
add_definitions(-D JSON_C_DLL)
endif()
if (UNIX OR AMIGA)
list(APPEND CMAKE_REQUIRED_LIBRARIES m) list(APPEND CMAKE_REQUIRED_LIBRARIES m)
endif() endif()
@@ -156,7 +185,17 @@ endif()
check_symbol_exists(_isnan "float.h" HAVE_DECL__ISNAN) check_symbol_exists(_isnan "float.h" HAVE_DECL__ISNAN)
check_symbol_exists(_finite "float.h" HAVE_DECL__FINITE) check_symbol_exists(_finite "float.h" HAVE_DECL__FINITE)
if ((MSVC AND NOT (MSVC_VERSION LESS 1800)) OR MINGW OR CYGWIN OR UNIX) if ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
# Detect clang-cl.exe, it is Clang but with MSVC compatible command line arguments
execute_process (COMMAND ${CMAKE_C_COMPILER} -? ERROR_QUIET OUTPUT_QUIET RESULT_VARIABLE _clang_result)
if (_clang_result EQUAL 0)
set(CLANG_CL TRUE)
else()
set(CLANG_CL FALSE)
endif()
endif()
if ((MSVC AND NOT (MSVC_VERSION LESS 1800)) OR MINGW OR CYGWIN OR UNIX OR AMIGA OR CLANG_CL)
check_symbol_exists(INFINITY "math.h" HAVE_DECL_INFINITY) check_symbol_exists(INFINITY "math.h" HAVE_DECL_INFINITY)
check_symbol_exists(isinf "math.h" HAVE_DECL_ISINF) check_symbol_exists(isinf "math.h" HAVE_DECL_ISINF)
check_symbol_exists(isnan "math.h" HAVE_DECL_ISNAN) check_symbol_exists(isnan "math.h" HAVE_DECL_ISNAN)
@@ -164,22 +203,23 @@ if ((MSVC AND NOT (MSVC_VERSION LESS 1800)) OR MINGW OR CYGWIN OR UNIX)
endif() endif()
check_symbol_exists(_doprnt "stdio.h" HAVE_DOPRNT) check_symbol_exists(_doprnt "stdio.h" HAVE_DOPRNT)
if (UNIX OR MINGW OR CYGWIN) if (UNIX OR MINGW OR CYGWIN OR AMIGA)
check_symbol_exists(snprintf "stdio.h" HAVE_SNPRINTF) check_symbol_exists(snprintf "stdio.h" HAVE_SNPRINTF)
endif() endif()
check_symbol_exists(vasprintf "stdio.h" HAVE_VASPRINTF) check_symbol_exists(vasprintf "stdio.h" HAVE_VASPRINTF)
check_symbol_exists(vsnprintf "stdio.h" HAVE_VSNPRINTF) check_symbol_exists(vsnprintf "stdio.h" HAVE_VSNPRINTF)
check_symbol_exists(vprintf "stdio.h" HAVE_VPRINTF) check_symbol_exists(vprintf "stdio.h" HAVE_VPRINTF)
if (NOT AMIGA_M68K)
check_symbol_exists(arc4random "stdlib.h" HAVE_ARC4RANDOM) check_symbol_exists(arc4random "stdlib.h" HAVE_ARC4RANDOM)
endif()
if (NOT HAVE_ARC4RANDOM AND DISABLE_EXTRA_LIBS STREQUAL "OFF") if (NOT HAVE_ARC4RANDOM AND DISABLE_EXTRA_LIBS STREQUAL "OFF")
check_include_file(bsd/stdlib.h HAVE_BSD_STDLIB_H) check_include_file(bsd/stdlib.h HAVE_BSD_STDLIB_H)
if (HAVE_BSD_STDLIB_H) if (HAVE_BSD_STDLIB_H)
list(APPEND CMAKE_REQUIRED_LIBRARIES "bsd") list(APPEND CMAKE_REQUIRED_LIBRARIES "bsd")
unset(HAVE_ARC4RANDOM CACHE) unset(HAVE_ARC4RANDOM CACHE)
check_symbol_exists(arc4random "bsd/stdlib.h" HAVE_ARC4RANDOM) check_symbol_exists(arc4random "bsd/stdlib.h" HAVE_ARC4RANDOM)
if (NOT HAVE_ARC4RANDOM) if (NOT HAVE_ARC4RANDOM)
list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES "bsd") list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES "bsd")
endif() endif()
endif() endif()
endif() endif()
@@ -193,13 +233,18 @@ endif()
if (HAVE_LOCALE_H) if (HAVE_LOCALE_H)
check_symbol_exists(setlocale "locale.h" HAVE_SETLOCALE) check_symbol_exists(setlocale "locale.h" HAVE_SETLOCALE)
check_symbol_exists(uselocale "locale.h" HAVE_USELOCALE) check_symbol_exists(uselocale "locale.h" HAVE_USELOCALE)
if (NOT NIX20 AND NOT NIX13)
# libnix does not fully support this yet
check_symbol_exists(duplocale "locale.h" HAVE_DUPLOCALE)
endif()
endif() endif()
# uClibc *intentionally* crashes in duplocale(), at least as of: # uClibc *intentionally* crashes in duplocale(), at least as of:
# https://github.com/ffainelli/uClibc/blob/266bdc1/libc/misc/locale/locale.c#L1322 # https://github.com/ffainelli/uClibc/blob/266bdc1/libc/misc/locale/locale.c#L1322
# So, if it looks like we're compiling for a system like that just disable # So, if it looks like we're compiling for a system like that just disable
# locale handling entirely. # locale handling entirely.
exec_program(${CMAKE_C_COMPILER} ARGS -dumpmachine OUTPUT_VARIABLE CMAKE_GNU_C_MACHINE) execute_process (COMMAND ${CMAKE_C_COMPILER} -dumpmachine ERROR_QUIET OUTPUT_VARIABLE CMAKE_GNU_C_MACHINE)
if (CMAKE_GNU_C_MACHINE MATCHES "uclibc") if (CMAKE_GNU_C_MACHINE MATCHES "uclibc")
message(STATUS "Detected uClibc compiler, disabling locale handling") message(STATUS "Detected uClibc compiler, disabling locale handling")
set(HAVE_SETLOCALE 0) set(HAVE_SETLOCALE 0)
@@ -295,11 +340,29 @@ message(STATUS "Wrote ${PROJECT_BINARY_DIR}/config.h")
configure_file(${PROJECT_SOURCE_DIR}/cmake/json_config.h.in ${PROJECT_BINARY_DIR}/json_config.h) configure_file(${PROJECT_SOURCE_DIR}/cmake/json_config.h.in ${PROJECT_BINARY_DIR}/json_config.h)
message(STATUS "Wrote ${PROJECT_BINARY_DIR}/json_config.h") message(STATUS "Wrote ${PROJECT_BINARY_DIR}/json_config.h")
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") if (NOT DEFINED CMAKE_C_COMPILER_FRONTEND_VARIANT OR "${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "") # only available in cmake 3.14+
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
set(CMAKE_C_COMPILER_FRONTEND_VARIANT "MSVC")
elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
set(CMAKE_C_COMPILER_FRONTEND_VARIANT "GNU")
elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
if (CLANG_CL)
set(CMAKE_C_COMPILER_FRONTEND_VARIANT "MSVC")
else()
set(CMAKE_C_COMPILER_FRONTEND_VARIANT "GNU")
message(STATUS, "clang result is NOT 0")
endif()
endif()
endif()
if ("${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "Clang")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections")
if ("${DISABLE_WERROR}" STREQUAL "OFF") if ("${DISABLE_WERROR}" STREQUAL "OFF")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
endif() endif()
if (AMIGA_M68K)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fbaserel")
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wcast-qual") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wcast-qual")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error=deprecated-declarations") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error=deprecated-declarations")
@@ -312,11 +375,11 @@ if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL
add_definitions(-D_GNU_SOURCE) add_definitions(-D_GNU_SOURCE)
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") if ("${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "Clang")
# Remove this for 1.0 when we can bump the ABI and actually fix these warnings. # Remove this for 1.0 when we can bump the ABI and actually fix these warnings.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-shorten-64-to-32") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-shorten-64-to-32")
endif() endif()
elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC") elseif ("${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "MSVC")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /DEBUG") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /DEBUG")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4100") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4100")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4996") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4996")
@@ -327,7 +390,7 @@ elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4701") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4701")
endif() endif()
if (NOT ("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")) if (NOT ("${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "MSVC"))
check_c_source_compiles( check_c_source_compiles(
" "
/* uClibc toolchains without threading barf when _REENTRANT is defined */ /* uClibc toolchains without threading barf when _REENTRANT is defined */
@@ -431,6 +494,13 @@ set(JSON_C_SOURCES
${PROJECT_SOURCE_DIR}/strerror_override.c ${PROJECT_SOURCE_DIR}/strerror_override.c
) )
set(JSON_C_RESOURCES)
if (BUILD_SHARED_LIBS AND WIN32)
enable_language(RC)
set(JSON_C_RESOURCES ${JSON_C_RESOURCES} ${PROJECT_SOURCE_DIR}/libjson.rc)
endif()
if (NOT DISABLE_JSON_POINTER) if (NOT DISABLE_JSON_POINTER)
set(JSON_C_PUBLIC_HEADERS ${JSON_C_PUBLIC_HEADERS} ${PROJECT_SOURCE_DIR}/json_pointer.h) set(JSON_C_PUBLIC_HEADERS ${JSON_C_PUBLIC_HEADERS} ${PROJECT_SOURCE_DIR}/json_pointer.h)
set(JSON_C_SOURCES ${JSON_C_SOURCES} ${PROJECT_SOURCE_DIR}/json_pointer.c) set(JSON_C_SOURCES ${JSON_C_SOURCES} ${PROJECT_SOURCE_DIR}/json_pointer.c)
@@ -470,9 +540,10 @@ endif()
add_library(${PROJECT_NAME} add_library(${PROJECT_NAME}
${JSON_C_SOURCES} ${JSON_C_SOURCES}
${JSON_C_HEADERS} ${JSON_C_HEADERS}
${JSON_C_RESOURCES}
) )
set_target_properties(${PROJECT_NAME} PROPERTIES set_target_properties(${PROJECT_NAME} PROPERTIES
VERSION 5.2.0 VERSION 5.4.0
SOVERSION 5) SOVERSION 5)
list(APPEND CMAKE_TARGETS ${PROJECT_NAME}) list(APPEND CMAKE_TARGETS ${PROJECT_NAME})
# If json-c is used as subroject it set to target correct interface -I flags and allow # If json-c is used as subroject it set to target correct interface -I flags and allow
@@ -545,7 +616,6 @@ install(
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
) )
if (UNIX OR MINGW OR CYGWIN)
SET(prefix ${CMAKE_INSTALL_PREFIX}) SET(prefix ${CMAKE_INSTALL_PREFIX})
# exec_prefix is prefix by default and CMake does not have the # exec_prefix is prefix by default and CMake does not have the
# concept. # concept.
@@ -573,7 +643,6 @@ if (UNIX OR MINGW OR CYGWIN)
configure_file(json-c.pc.in json-c.pc @ONLY) configure_file(json-c.pc.in json-c.pc @ONLY)
set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_LIBDIR}/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files") set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_LIBDIR}/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files")
install(FILES ${PROJECT_BINARY_DIR}/json-c.pc DESTINATION "${INSTALL_PKGCONFIG_DIR}") install(FILES ${PROJECT_BINARY_DIR}/json-c.pc DESTINATION "${INSTALL_PKGCONFIG_DIR}")
endif ()
install(FILES ${JSON_C_PUBLIC_HEADERS} DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR}/json-c) install(FILES ${JSON_C_PUBLIC_HEADERS} DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR}/json-c)
@@ -589,4 +658,3 @@ if (NOT MSVC) # cmd line apps don't built on Windows currently.
add_subdirectory(apps) add_subdirectory(apps)
endif() endif()
endif() endif()

View File

@@ -1,7 +1,77 @@
0.19 (up to commit 8948568, 2026-01-18)
========================================
Deprecated and removed features:
--------------------------------
* none
New features
------------
* Add support for Commodore Amiga and MorphOS
* Allow builds with CMake 4 - sync minimum version across all CMakeLists.txt files
* Update openssl command to work for newer versions of openssl.
* Add support for building json-c with meson
* Support MSVC in packages that use GNU Autoconf.
* Add VERSIONINFO to libjson-c.dll
* Make json_tokener_free(NULL) a no-op, to simplify cleanup paths.
* Explicitly handle NaN values when converting to int
* Set errno=RANGE in json_object_get_int/int64/uint64() when the source value can't be represented in the target type.
* Make json_parse a bit more useful by adding -u (validate UTF8) and -P (specify arbitrary tokener parse flags), and read from stdin if no filename is provided.
* Fix the apps/json_parse "-s" (strict) option so it actually does something, and default to non-strict.
Significant changes and bug fixes
---------------------------------
* Issue #867 - also disallow control characters in keys in JSON_TOKENER_STRICT mode
* Issue #875: cast to unsigned char so bytes above 0x7f aren't interpreted as negative, which was causing the strict-mode control characters check to incorrectly trigger.
* Issue #881: don't allow json_tokener_new_ex() with a depth < 1
* Fix linkhash breaking -std=c89
* Fixing Cmake build when using clang-cl, avoids errors about redefining existing symbols
* Fix AIX build failure - Add CMake detection for getopt.h
* Fix bug involving supplemental code points that look like high surrogates
* Fix runtime issue with test_util_file.c in Windows (add O_BINARY)
* Fix macro WIN32_LEAN_AND_MEAN redefined
0.18 (up to commit 6bfab90, 2024-09-15)
========================================
Deprecated and removed features:
--------------------------------
* Clean up pre-3.9 CMake support in CMakeLists.txt
New features
------------
* Build pkg-config for msvc as well
Significant changes and bug fixes
---------------------------------
* Critical fix for binary compatibility with 0.16: Move the
json_tokener_error_memory entry to the end of enum json_tokener_error.
* Issue #829: attempt to detect clang-cl.exe and pass MSVC-compatile command
line arguments.
* PR #831 - rename WIN32 to _WIN32
* PR #839 - Fix gcc 5 "may be used uninitialized" failure in json_pointer.c
* PR #849 - random_seed.c: add a Coverity Scan suppression
* Issue #854: Set error=json_tokener_error_memory in
json_tokener_parser_verbose() when allocating the tokener fails.
* Issue #857: fix a few places where json_tokener should have been returning
json_tokener_error_memory but wasn't.
* Handle yet another out-of-memory condition in json_tokener, duplocate can
return NULL.
* Various fixes in the fuzzers
* A few minor doc fixes
***
0.17 (up to commit 077661f, 2023-08-08) 0.17 (up to commit 077661f, 2023-08-08)
======================================== ========================================
Known Bugs
----------
* DO NOT USE THE 0.17 RELEASE: json_tokener_error_memory in misplaced in the
json_tokener_error enum, leading to binary compatibility issues.
Deprecated and removed features: Deprecated and removed features:
-------------------------------- --------------------------------
* None * None

View File

@@ -1,6 +1,6 @@
\mainpage \mainpage
`json-c` json-c
======== ========
1. [Overview and Build Status](#overview) 1. [Overview and Build Status](#overview)
@@ -12,10 +12,12 @@
5. [Testing](#testing) 5. [Testing](#testing)
6. [Building with `vcpkg`](#buildvcpkg) 6. [Building with `vcpkg`](#buildvcpkg)
7. [Building for Android](#android) 7. [Building for Android](#android)
7. [Linking to libjson-c](#linking) 8. [Building for Commodore Amiga or MorphOS](#amiga)
8. [Using json-c](#using) 9. [Linking to libjson-c](#linking)
10. [Using json-c](#using)
JSON-C - A JSON implementation in C <a name="overview"></a> <a name="overview"></a>
JSON-C - A JSON implementation in C
----------------------------------- -----------------------------------
JSON-C implements a reference counting object model that allows you to easily JSON-C implements a reference counting object model that allows you to easily
@@ -29,7 +31,8 @@ if you already have json-c installed and ready to use.
Home page for json-c: https://github.com/json-c/json-c/wiki Home page for json-c: https://github.com/json-c/json-c/wiki
Getting Help <a name="gettinghelp"></a> <a name="gettinghelp"></a>
Getting Help
------------ ------------
If you have questions about using json-c, please start a thread on If you have questions about using json-c, please start a thread on
@@ -47,7 +50,8 @@ features or large changes of any kind, please first start a discussion
on the [forums](https://groups.google.com/forum/#!forum/json-c). on the [forums](https://groups.google.com/forum/#!forum/json-c).
Building on Unix with `git`, `gcc` and `cmake` <a name="buildunix"></a> <a name="buildunix"></a>
Building on Unix with `git`, `gcc` and `cmake`
-------------------------------------------------- --------------------------------------------------
If you already have json-c installed, see [Linking to `libjson-c`](#linking) If you already have json-c installed, see [Linking to `libjson-c`](#linking)
@@ -60,7 +64,8 @@ Build Status
Test Status Test Status
* [Coveralls](https://coveralls.io/github/json-c/json-c?branch=master) [![Coverage Status](https://coveralls.io/repos/github/json-c/json-c/badge.svg?branch=master)](https://coveralls.io/github/json-c/json-c?branch=master) * [Coveralls](https://coveralls.io/github/json-c/json-c?branch=master) [![Coverage Status](https://coveralls.io/repos/github/json-c/json-c/badge.svg?branch=master)](https://coveralls.io/github/json-c/json-c?branch=master)
### Prerequisites: <a name="installprereq"></a> <a name="installprereq"></a>
### Prerequisites:
- `gcc`, `clang`, or another C compiler - `gcc`, `clang`, or another C compiler
@@ -80,7 +85,8 @@ sudo apt install doxygen # optional
sudo apt install valgrind # optional sudo apt install valgrind # optional
``` ```
### Build instructions: <a name="buildcmds"></a> <a name="buildcmds"></a>
### Build instructions:
`json-c` GitHub repo: https://github.com/json-c/json-c `json-c` GitHub repo: https://github.com/json-c/json-c
@@ -116,7 +122,8 @@ google-chrome doc/html/index.html
``` ```
CMake Options <a name="CMake"></a> <a name="CMake"></a>
CMake Options
-------------------- --------------------
The json-c library is built with [CMake](https://cmake.org/cmake-tutorial/), The json-c library is built with [CMake](https://cmake.org/cmake-tutorial/),
@@ -188,7 +195,8 @@ cmake-configure can take a few options.
| disable-werror | Avoid treating compiler warnings as fatal errors | | disable-werror | Avoid treating compiler warnings as fatal errors |
Testing: <a name="testing"></a> <a name="testing"></a>
Testing:
---------- ----------
By default, if valgrind is available running tests uses it. By default, if valgrind is available running tests uses it.
@@ -224,7 +232,8 @@ JSONC_TEST_TRACE=1 make test
and check the log files again. and check the log files again.
Building on Unix and Windows with `vcpkg` <a name="buildvcpkg"></a> <a name="buildvcpkg"></a>
Building on Unix and Windows with `vcpkg`
-------------------------------------------------- --------------------------------------------------
You can download and install JSON-C using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager: You can download and install JSON-C using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager:
@@ -237,7 +246,8 @@ You can download and install JSON-C using the [vcpkg](https://github.com/Microso
The JSON-C port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. The JSON-C port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
Building for Android <a name="android"> <a name="android"></a>
Building for Android
---------------------- ----------------------
Building on Android is now particularly well supported, but there Building on Android is now particularly well supported, but there
@@ -261,7 +271,65 @@ cmake \
make install make install
``` ```
Linking to `libjson-c` <a name="linking"> <a name="amiga"></a>
Building for Commodore Amiga or MorphOS
----------------------
Building for Commodore Amiga is supported for both Motorola 68k (AmigaOS 3) and PowerPC (AmigaOS 4) architectures. MorphOS on compatible PowerPC hardware is also supported. You can set up a cross compiler locally, however it is much easier to use the already preconfigured Amiga development environment wtthin a Docker container.
Install Docker on your machine if you don't already have it. You can download Docker Desktop for Windows/macOS/Linux [here](https://www.docker.com/products/docker-desktop/).
### To build for Motorola 68k Amiga:
```
mkdir build
docker run --rm \
-v ${PWD}:/work \
-e USER=$( id -u ) -e GROUP=$( id -g ) \
-it sacredbanana/amiga-compiler:m68k-amigaos bash
cd build
cmake -DM68K_CRT=newlib ..
make
```
libjson-c.a will get created in the build directory.
You can change newlib to nix20, nix13, ixemul or clib2 if you would like to build the library suited for libnix or clib2 instead. Newlib is default.
### To build for PowerPC Amiga:
```
mkdir build
docker run --rm \
-v ${PWD}:/work \
-e USER=$( id -u ) -e GROUP=$( id -g ) \
-it sacredbanana/amiga-compiler:ppc-amigaos bash
cd build
cmake ..
make
```
libjson-c.a will get created in the build directory.
### To build for PowerPC MorphOS:
```
mkdir build
docker run --rm \
-v ${PWD}:/work \
-e USER=$( id -u ) -e GROUP=$( id -g ) \
-it sacredbanana/amiga-compiler:ppc-morphos bash
cd build
cmake -DNOIXEMUL=1 ..
make
```
If you are making an application that absolutely requires ixemul, then remove the `-DNOIXEMUL=1`.
libjson-c.a will get created in the build directory.
<a name="linking"></a>
Linking to `libjson-c`
---------------------- ----------------------
If your system has `pkgconfig`, If your system has `pkgconfig`,
@@ -298,7 +366,8 @@ cd build
cmake -DCMAKE_PREFIX_PATH=/path/to/json_c/install/lib64/cmake .. cmake -DCMAKE_PREFIX_PATH=/path/to/json_c/install/lib64/cmake ..
``` ```
Using json-c <a name="using"> <a name="using"></a>
Using json-c
------------ ------------
To use json-c you can either include json.h, or preferably, one of the To use json-c you can either include json.h, or preferably, one of the

View File

@@ -141,12 +141,10 @@ Use ${release}.99 to indicate a version "newer" than anything on the branch:
Update the version in json_c_version.h Update the version in json_c_version.h
Update the version in CMakeLists.txt Update the version in CMakeLists.txt
Update RELEASE_CHECKLIST.txt, set release=${release}+1 Update the set_target_properties() line in CmakeLists.txt to match the release branch.
Add a new empty section to the json-c.sym file, for ${release}+1 Add a new empty section to the json-c.sym file, for ${release}+1
Update the set_target_properties() line in CmakeLists.txt to match the release branch.
git commit -a -m "Update the master branch to version ${release}.99" git commit -a -m "Update the master branch to version ${release}.99"
git push git push
@@ -179,7 +177,7 @@ Update the gh-pages branch with new docs:
Update checksums on wiki page. Update checksums on wiki page.
cd .. cd ..
openssl sha -sha256 json-c*gz openssl sha1 -sha256 json-c*gz
openssl md5 json-c*gz openssl md5 json-c*gz
Copy and paste this output into the wiki page at: Copy and paste this output into the wiki page at:

20
abi-check.sh Normal file → Executable file
View File

@@ -1,14 +1,19 @@
#!/bin/sh #!/bin/sh
prev=0.16 set -e
release=0.17
# The 0.17 release is broken
prev=0.18
release=0.19
# ... clone json-c, abi-compliance-checker, abi-dumper # ... clone json-c, abi-compliance-checker, abi-dumper
mkdir build if [ "$1" != "--skip-build" ] ; then
cd build mkdir build
CFLAGS=-Og cmake -DCMAKE_INSTALL_PREFIX=~/json-c-installs/json-c-${release} .. cd build
make && make test && make install CFLAGS=-Og cmake -DCMAKE_INSTALL_PREFIX=~/json-c-installs/json-c-${release} ..
make && make test && make install
fi
# Assume the old version has already been built # Assume the old version has already been built
@@ -16,6 +21,9 @@ cd ~/abi-compliance-checker
mkxml() mkxml()
{ {
ver="$1" ver="$1"
if [ ! -e ../json-c-installs/json-c-${ver}/lib64 ] ; then
ln -s lib ../json-c-installs/json-c-${ver}/lib64
fi
cat <<EOF > json-c-${ver}.xml cat <<EOF > json-c-${ver}.xml
<foo> <foo>
<version> <version>

View File

@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 2.8) # see ../CMakeLists.txt for why 2.8 cmake_minimum_required(VERSION 3.9...3.12) # see ../CMakeLists.txt for why
if(POLICY CMP0075) if(POLICY CMP0075)
cmake_policy(SET CMP0075 NEW) cmake_policy(SET CMP0075 NEW)
@@ -94,6 +94,9 @@ endif() # end "standalone mode" block
# --------------------------------- # ---------------------------------
# Check whether getopt.h exists
check_include_file(getopt.h HAVE_GETOPT_H)
check_include_file(sys/resource.h HAVE_SYS_RESOURCE_H) # for getrusage check_include_file(sys/resource.h HAVE_SYS_RESOURCE_H) # for getrusage
if (HAVE_SYS_RESOURCE_H) if (HAVE_SYS_RESOURCE_H)
check_symbol_exists(getrusage "sys/resource.h" HAVE_GETRUSAGE) check_symbol_exists(getrusage "sys/resource.h" HAVE_GETRUSAGE)

View File

@@ -1,7 +1,9 @@
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#ifdef HAVE_GETOPT_H
#include <getopt.h> #include <getopt.h>
#endif
#include <stddef.h> #include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@@ -38,6 +40,8 @@
static int formatted_output = JSON_C_TO_STRING_SPACED; static int formatted_output = JSON_C_TO_STRING_SPACED;
static int show_output = 1; static int show_output = 1;
static int strict_mode = 0; static int strict_mode = 0;
static int validate_utf8 = 0;
static int tokener_flags = 0;
static int color = 0; static int color = 0;
static const char *fname = NULL; static const char *fname = NULL;
@@ -74,11 +78,21 @@ static int parseit(int fd, int (*callback)(struct json_object *))
fprintf(stderr, "unable to allocate json_tokener: %s\n", strerror(errno)); fprintf(stderr, "unable to allocate json_tokener: %s\n", strerror(errno));
return 1; return 1;
} }
json_tokener_set_flags(tok, JSON_TOKENER_STRICT if (strict_mode)
{
tokener_flags |= JSON_TOKENER_STRICT;
#ifdef JSON_TOKENER_ALLOW_TRAILING_CHARS #ifdef JSON_TOKENER_ALLOW_TRAILING_CHARS
| JSON_TOKENER_ALLOW_TRAILING_CHARS tokener_flags |= JSON_TOKENER_ALLOW_TRAILING_CHARS;
#endif #endif
); }
if (validate_utf8)
{
tokener_flags |= JSON_TOKENER_VALIDATE_UTF8;
}
if (tokener_flags)
{
json_tokener_set_flags(tok, tokener_flags);
}
// XXX push this into some kind of json_tokener_parse_fd API? // XXX push this into some kind of json_tokener_parse_fd API?
// json_object_from_fd isn't flexible enough, and mirroring // json_object_from_fd isn't flexible enough, and mirroring
@@ -157,13 +171,15 @@ static void usage(const char *argv0, int exitval, const char *errmsg)
fp = stderr; fp = stderr;
if (errmsg != NULL) if (errmsg != NULL)
fprintf(fp, "ERROR: %s\n\n", errmsg); fprintf(fp, "ERROR: %s\n\n", errmsg);
fprintf(fp, "Usage: %s [-f|-F <arg>] [-n] [-s]\n", argv0); fprintf(fp, "Usage: %s [-f|-F <arg>] [-n] [-s] [-u] [filename]\n", argv0);
fprintf(fp, " -f - Format the output to stdout with JSON_C_TO_STRING_PRETTY (default is JSON_C_TO_STRING_SPACED)\n"); fprintf(fp, " -f - Format the output to stdout with JSON_C_TO_STRING_PRETTY (default is JSON_C_TO_STRING_SPACED)\n");
fprintf(fp, " -F - Format the output to stdout with <arg>, e.g. 0 for JSON_C_TO_STRING_PLAIN\n"); fprintf(fp, " -F - Format the output to stdout with <arg>, e.g. 0 for JSON_C_TO_STRING_PLAIN\n");
fprintf(fp, " -n - No output\n"); fprintf(fp, " -n - No output\n");
fprintf(fp, " -c - color\n"); fprintf(fp, " -c - Set JSON_C_TO_STRING_COLOR to colorize the output\n");
fprintf(fp, " -s - Parse in strict mode, flags:\n"); fprintf(fp, " -P - Initialize tokener flags to the given value\n");
fprintf(fp, " -s - Parse in strict mode, add flags:\n");
fprintf(fp, " JSON_TOKENER_STRICT|JSON_TOKENER_ALLOW_TRAILING_CHARS\n"); fprintf(fp, " JSON_TOKENER_STRICT|JSON_TOKENER_ALLOW_TRAILING_CHARS\n");
fprintf(fp, " -u - Add the JSON_TOKENER_VALIDATE_UTF8 flag when parsing\n");
fprintf(fp, " Diagnostic information will be emitted to stderr\n"); fprintf(fp, " Diagnostic information will be emitted to stderr\n");
fprintf(fp, "\nWARNING WARNING WARNING\n"); fprintf(fp, "\nWARNING WARNING WARNING\n");
@@ -175,26 +191,28 @@ int main(int argc, char **argv)
{ {
int opt; int opt;
while ((opt = getopt(argc, argv, "fF:hnsc")) != -1) while ((opt = getopt(argc, argv, "cfF:hnP:su")) != -1)
{ {
switch (opt) switch (opt)
{ {
case 'c': color = JSON_C_TO_STRING_COLOR; break;
case 'f': formatted_output = JSON_C_TO_STRING_PRETTY; break; case 'f': formatted_output = JSON_C_TO_STRING_PRETTY; break;
case 'F': formatted_output = atoi(optarg); break; case 'F': formatted_output = atoi(optarg); break;
case 'n': show_output = 0; break; case 'n': show_output = 0; break;
case 'P': tokener_flags = atoi(optarg); break;
case 's': strict_mode = 1; break; case 's': strict_mode = 1; break;
case 'c': color = JSON_C_TO_STRING_COLOR; break; case 'u': validate_utf8 = 1; break;
case 'h': usage(argv[0], 0, NULL); case 'h': usage(argv[0], 0, NULL);
default: /* '?' */ usage(argv[0], EXIT_FAILURE, "Unknown arguments"); default: /* '?' */ usage(argv[0], EXIT_FAILURE, "Unknown arguments");
} }
} }
if (optind >= argc) int fd = STDIN_FILENO;
fname = "stdin";
if (argc > optind && strcmp(argv[optind], "-") != 0)
{ {
usage(argv[0], EXIT_FAILURE, "Expected argument after options"); fname = argv[optind];
fd = open(fname, O_RDONLY, 0);
} }
fname = argv[optind];
int fd = open(argv[optind], O_RDONLY, 0);
showmem(); showmem();
if (parseit(fd, showobj) != 0) if (parseit(fd, showobj) != 0)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);

27
apps/meson.build Normal file
View File

@@ -0,0 +1,27 @@
appconf_data = configuration_data()
# Check for json_tokener_get_parse_end symbol
appconf_data.set('HAVE_JSON_TOKENER_GET_PARSE_END',
cc.has_function('json_tokener_get_parse_end', prefix: '#include <json_tokener.h>') ? 1 : 0
)
# Check for getrusage if sys/resource.h is available
appconf_data.set('HAVE_SYS_RESOURCE_H', cc.has_header('sys/resource.h') ? 1 : 0, description: 'Define to 1 if you have the <sys/resource.h> header file.')
if appconf_data.get('HAVE_SYS_RESOURCE_H') == 1
appconf_data.set('HAVE_GETRUSAGE',
cc.has_function('getrusage', prefix: '#include <sys/resource.h>') ? 1 : 0, description: 'Define if you have the `getrusage` function. ')
else
appconf_data.set('HAVE_GETRUSAGE', 0, description: 'Define if you have the `getrusage` function. ')
endif
# Generate apps_config.h
configure_file(
output: 'apps_config.h',
configuration: appconf_data
)
# Build json_parse executable
executable('json_parse', 'json_parse.c',
dependencies: [jsonc_dep],
install: false
)

View File

@@ -137,6 +137,9 @@
/* Define to 1 if you have the `uselocale' function. */ /* Define to 1 if you have the `uselocale' function. */
#cmakedefine HAVE_USELOCALE #cmakedefine HAVE_USELOCALE
/* Define to 1 if you have the `duplocale' function. */
#cmakedefine HAVE_DUPLOCALE
/* Define to 1 if newlocale() needs freelocale() called on it's `base` argument */ /* Define to 1 if newlocale() needs freelocale() called on it's `base` argument */
#cmakedefine NEWLOCALE_NEEDS_FREELOCALE #cmakedefine NEWLOCALE_NEEDS_FREELOCALE

27
fuzz/json_array_fuzzer.cc Normal file
View File

@@ -0,0 +1,27 @@
#include <fuzzer/FuzzedDataProvider.h>
#include "json.h"
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
FuzzedDataProvider fdp(data, size);
json_object *my_array = json_object_new_array();
for (int i = 0; i < 3; ++i) {
json_object *jso = json_tokener_parse(fdp.ConsumeRandomLengthString(10).c_str());
if (jso == NULL) {
continue;
}
json_object_array_add(my_array, jso);
}
json_object_array_insert_idx(my_array, fdp.ConsumeIntegralInRange<size_t>(0, 10),
json_object_new_int(fdp.ConsumeIntegral<int>()));
json_object_array_get_idx(my_array, fdp.ConsumeIntegralInRange<size_t>(0, 10));
json_object_array_put_idx(my_array, fdp.ConsumeIntegralInRange<size_t>(0, 10),
json_object_new_int(fdp.ConsumeIntegral<int>()));
json_object_array_del_idx(my_array, fdp.ConsumeIntegralInRange<size_t>(0, 10),
fdp.ConsumeIntegralInRange<size_t>(0, 10));
json_object_array_shrink(my_array, fdp.ConsumeIntegralInRange<size_t>(0, 10));
json_object_array_sort(my_array, [](const void *a, const void *b) { return 0; });
json_object_array_length(my_array);
json_object_put(my_array);
return 0;
}

View File

@@ -0,0 +1,21 @@
"{"
"}"
","
"["
"]"
","
":"
"e"
"e+"
"e-"
"E"
"E+"
"E-"
"\""
"null"
"1"
"1.234"
"3e4"
"NaN"
"Infinity"
"-Infinity"

View File

@@ -0,0 +1,44 @@
#include <fuzzer/FuzzedDataProvider.h>
#include "json.h"
#include "json_visit.h"
// Function to test json_c_visit
static int emit_object(json_object *jso, int flags, json_object *parent_jso, const char *jso_key,
size_t *jso_index, void *userarg) {
return JSON_C_VISIT_RETURN_CONTINUE;
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
FuzzedDataProvider fdp(data, size);
json_object *jso = json_tokener_parse(fdp.ConsumeRandomLengthString(20).c_str());
json_object_get_boolean(jso);
json_object_get_double(jso);
json_object_get_int(jso);
json_object_get_int64(jso);
json_object_get_uint64(jso);
json_object_get_string(jso);
json_object_get_string_len(jso);
json_object_get_object(jso);
json_object_get_array(jso);
json_object_get_type(jso);
json_c_visit(jso, 0, emit_object, NULL);
json_object_set_int(jso, fdp.ConsumeIntegral<int>());
json_object_set_int64(jso, fdp.ConsumeIntegral<int64_t>());
json_object_set_uint64(jso, fdp.ConsumeIntegral<uint64_t>());
json_object_set_double(jso, fdp.ConsumeFloatingPoint<double>());
json_object_set_string(jso, fdp.ConsumeRandomLengthString(10).c_str());
json_object_set_boolean(jso, fdp.ConsumeBool());
std::string str = fdp.ConsumeRandomLengthString(10);
json_object_set_string_len(jso, str.c_str(), str.size());
json_object *dst = NULL;
json_object_deep_copy(jso, &dst, json_c_shallow_copy_default);
json_object_put(dst);
json_object_put(jso);
return 0;
}

View File

@@ -0,0 +1,21 @@
"{"
"}"
","
"["
"]"
","
":"
"e"
"e+"
"e-"
"E"
"E+"
"E-"
"\""
"null"
"1"
"1.234"
"3e4"
"NaN"
"Infinity"
"-Infinity"

View File

@@ -0,0 +1,53 @@
#include <fuzzer/FuzzedDataProvider.h>
#include "json.h"
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
FuzzedDataProvider fdp(data, size);
struct json_tokener *tokener =
json_tokener_new_ex(fdp.ConsumeIntegralInRange<int>(1, JSON_TOKENER_DEFAULT_DEPTH));
int flags = 0;
if (fdp.ConsumeBool()) {
flags |= JSON_TOKENER_VALIDATE_UTF8;
}
if (fdp.ConsumeBool()) {
flags |= JSON_TOKENER_ALLOW_TRAILING_CHARS;
}
if (fdp.ConsumeBool()) {
flags |= JSON_TOKENER_STRICT;
}
json_tokener_set_flags(tokener, flags);
std::string path = fdp.ConsumeRandomLengthString(5);
std::string sub_json_str = fdp.ConsumeRandomLengthString(10);
bool use_format_string = fdp.ConsumeBool();
std::string json_str = fdp.ConsumeRemainingBytesAsString();
struct json_object *jo1 = json_tokener_parse_ex(tokener, json_str.c_str(), json_str.size());
struct json_object *sub_json = json_tokener_parse(sub_json_str.c_str());
if (sub_json == NULL) {
sub_json = json_object_new_object();
}
struct json_object *jo2 = NULL;
if (use_format_string) {
json_pointer_getf(jo1, &jo2, "%s", path.c_str());
if (json_pointer_setf(&jo1, sub_json, "%s", path.c_str()))
{
json_object_put(sub_json);
}
} else {
json_pointer_get(jo1, path.c_str(), &jo2);
if (json_pointer_set(&jo1, path.c_str(), sub_json))
{
json_object_put(sub_json);
}
}
// Clean up the main JSON object
json_object_put(jo1);
json_tokener_free(tokener);
return 0;
}

View File

@@ -0,0 +1,21 @@
"{"
"}"
","
"["
"]"
","
":"
"e"
"e+"
"e-"
"E"
"E+"
"E-"
"\""
"null"
"1"
"1.234"
"3e4"
"NaN"
"Infinity"
"-Infinity"

View File

@@ -8,11 +8,13 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
json_tokener *tok = json_tokener_new(); json_tokener *tok = json_tokener_new();
json_object *obj = json_tokener_parse_ex(tok, data1, size); json_object *obj = json_tokener_parse_ex(tok, data1, size);
json_object_object_foreach(jobj, key, val) { if (json_object_is_type(obj, json_type_object)) {
(void)json_object_get_type(val); json_object_object_foreach(obj, key, val) {
(void)json_object_get_string(val); (void)json_object_get_type(val);
(void)json_object_get_string(val);
}
} }
(void)json_object_to_json_string(obj, JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED); (void)json_object_to_json_string_ext(obj, JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED);
json_object_put(obj); json_object_put(obj);
json_tokener_free(tok); json_tokener_free(tok);

View File

@@ -16,3 +16,6 @@
"1" "1"
"1.234" "1.234"
"3e4" "3e4"
"NaN"
"Infinity"
"-Infinity"

52
issues_closed_for_0.18.md Normal file
View File

@@ -0,0 +1,52 @@
This list was created with:
```
PREV=2023-08-12
NOW=2024-09-15
curl "https://api.github.com/search/issues?q=repo%3Ajson-c%2Fjson-c+closed%3A>${PREV}+created%3A<${NOW}&sort=created&order=asc&per_page=100&page=1" > issues1.out
jq -r '.items[] | "[" + .title + "](" + .url + ")" | tostring' issues?.out > issues.md
sed -e's,^\[ *\(.*\)\](https://api.github.com/.*/\([0-9].*\)),* [Issue #\2](https://github.com/json-c/json-c/issues/\2) - \1,' -i issues.md
cat issues.md >> issues_closed_for_0.18.md
```
* [Issue #826](https://github.com/json-c/json-c/issues/826) - CMake: remove needless policy setting
* [Issue #827](https://github.com/json-c/json-c/issues/827) - Resolve build issue in tokener_parse_ex_fuzzer.c
* [Issue #828](https://github.com/json-c/json-c/issues/828) - Put arc4random check under DISABLE_EXTRA_LIBS=OFF in CMakeLists.txt.
* [Issue #829](https://github.com/json-c/json-c/issues/829) - Cannot build with clang-cl
* [Issue #830](https://github.com/json-c/json-c/issues/830) - I am looking whether this CVE - CVE-2021-32292 is impacted by json-c version v0.13.1or not ?
* [Issue #831](https://github.com/json-c/json-c/issues/831) - rename WIN32 to _WIN32
* [Issue #833](https://github.com/json-c/json-c/issues/833) - memory leak issue in 0.13
* [Issue #834](https://github.com/json-c/json-c/issues/834) - fix error des of 'error_memory'
* [Issue #835](https://github.com/json-c/json-c/issues/835) - fix error des of 'error_memory'
* [Issue #836](https://github.com/json-c/json-c/issues/836) - Null pointer dereference in tokener_parse_ex_fuzzer.cc
* [Issue #837](https://github.com/json-c/json-c/issues/837) - Add type checking for parsed objects in tokener_parse_ex_fuzzer
* [Issue #838](https://github.com/json-c/json-c/issues/838) - Cannot link properly using cmake
* [Issue #839](https://github.com/json-c/json-c/issues/839) - json_pointer.c: initialize idx
* [Issue #840](https://github.com/json-c/json-c/issues/840) - Memory leak when enable HAVE_SETLOCALE and HAVE_USELOCALE
* [Issue #841](https://github.com/json-c/json-c/issues/841) - Random crash in json_tokener_parse
* [Issue #842](https://github.com/json-c/json-c/issues/842) - Assignment bug in json_pointer.c
* [Issue #843](https://github.com/json-c/json-c/issues/843) - _WIN32 should be used, not WIN32 in source code ifdefs.
* [Issue #844](https://github.com/json-c/json-c/issues/844) - Doxygen: mis-wording in `json_object_put`
* [Issue #845](https://github.com/json-c/json-c/issues/845) - [CMP0153](https://cmake.org/cmake/help/latest/policy/CMP0153.html)
* [Issue #846](https://github.com/json-c/json-c/issues/846) - CMP0153
* [Issue #848](https://github.com/json-c/json-c/issues/848) - json_object_from_file caused calloc SIGSEGV
* [Issue #849](https://github.com/json-c/json-c/issues/849) - random_seed.c: add a Coverity Scan suppression
* [Issue #850](https://github.com/json-c/json-c/issues/850) - Missing return description
* [Issue #851](https://github.com/json-c/json-c/issues/851) - Allow NULL in json_object_new_string() and json_object_new_string_len()
* [Issue #852](https://github.com/json-c/json-c/issues/852) - docs: micro typo in json_object_put doc
* [Issue #853](https://github.com/json-c/json-c/issues/853) - json_tokener_parse_verbose does not set the error indicator when it fails to allocate the tokener
* [Issue #854](https://github.com/json-c/json-c/issues/854) - json_tokener_parse_verbose sets the error indicator to a wrong value when there is a memory allocation failure
* [Issue #856](https://github.com/json-c/json-c/issues/856) - Using libjson-c.so or compiling from source seg faults on json_tokener_parse_ex in alpine docker container
* [Issue #857](https://github.com/json-c/json-c/issues/857) - json_tokener_parse_verbose sets the error indicator to a wrong value when there is a memory allocation failure
* [Issue #858](https://github.com/json-c/json-c/issues/858) - json_tokener.h: json_tokener_parse_verbose: fix typo
* [Issue #859](https://github.com/json-c/json-c/issues/859) - Develop
* [Issue #860](https://github.com/json-c/json-c/issues/860) - Develop
* [Issue #861](https://github.com/json-c/json-c/issues/861) - Handle yet another out-of-memory condition.
* [Issue #862](https://github.com/json-c/json-c/issues/862) - Missing `json-c-targets.cmake` during build cmake build step
* [Issue #863](https://github.com/json-c/json-c/issues/863) - build ios simulator error
* [Issue #864](https://github.com/json-c/json-c/issues/864) - Build pkg-config for msvc as well
* [Issue #865](https://github.com/json-c/json-c/issues/865) - Assertion usage
* [Issue #866](https://github.com/json-c/json-c/issues/866) - Added github actions
* [Issue #868](https://github.com/json-c/json-c/issues/868) - I meet compile error in harmony
* [Issue #869](https://github.com/json-c/json-c/issues/869) - At a high level how are jsons parses? Are they terminated by the new line?
* [Issue #870](https://github.com/json-c/json-c/issues/870) - Non-Compliant features should be optional (and disabled)

91
issues_closed_for_0.19.md Normal file
View File

@@ -0,0 +1,91 @@
This list was created with:
```
PREV=2024-09-15
NOW=2026-01-19
curl "https://api.github.com/search/issues?q=repo%3Ajson-c%2Fjson-c+closed%3A>${PREV}+created%3A<${NOW}&sort=created&order=asc&per_page=100&page=1" > issues1.out
jq -r '.items[] | "[" + .title + "](" + .url + ")" | tostring' issues?.out > issues.md
sed -e's,^\[ *\(.*\)\](https://api.github.com/.*/\([0-9].*\)),* [Issue #\2](https://github.com/json-c/json-c/issues/\2) - \1,' -i issues.md
cat issues.md >> issues_closed_for_0.19.md
```
* [Issue #826](https://github.com/json-c/json-c/issues/826) - CMake: remove needless policy setting
* [Issue #827](https://github.com/json-c/json-c/issues/827) - Resolve build issue in tokener_parse_ex_fuzzer.c
* [Issue #828](https://github.com/json-c/json-c/issues/828) - Put arc4random check under DISABLE_EXTRA_LIBS=OFF in CMakeLists.txt.
* [Issue #829](https://github.com/json-c/json-c/issues/829) - Cannot build with clang-cl
* [Issue #830](https://github.com/json-c/json-c/issues/830) - I am looking whether this CVE - CVE-2021-32292 is impacted by json-c version v0.13.1or not ?
* [Issue #831](https://github.com/json-c/json-c/issues/831) - rename WIN32 to _WIN32
* [Issue #833](https://github.com/json-c/json-c/issues/833) - memory leak issue in 0.13
* [Issue #834](https://github.com/json-c/json-c/issues/834) - fix error des of 'error_memory'
* [Issue #835](https://github.com/json-c/json-c/issues/835) - fix error des of 'error_memory'
* [Issue #836](https://github.com/json-c/json-c/issues/836) - Null pointer dereference in tokener_parse_ex_fuzzer.cc
* [Issue #837](https://github.com/json-c/json-c/issues/837) - Add type checking for parsed objects in tokener_parse_ex_fuzzer
* [Issue #838](https://github.com/json-c/json-c/issues/838) - Cannot link properly using cmake
* [Issue #839](https://github.com/json-c/json-c/issues/839) - json_pointer.c: initialize idx
* [Issue #840](https://github.com/json-c/json-c/issues/840) - Memory leak when enable HAVE_SETLOCALE and HAVE_USELOCALE
* [Issue #841](https://github.com/json-c/json-c/issues/841) - Random crash in json_tokener_parse
* [Issue #842](https://github.com/json-c/json-c/issues/842) - Assignment bug in json_pointer.c
* [Issue #843](https://github.com/json-c/json-c/issues/843) - _WIN32 should be used, not WIN32 in source code ifdefs.
* [Issue #844](https://github.com/json-c/json-c/issues/844) - Doxygen: mis-wording in `json_object_put`
* [Issue #845](https://github.com/json-c/json-c/issues/845) - [CMP0153](https://cmake.org/cmake/help/latest/policy/CMP0153.html)
* [Issue #846](https://github.com/json-c/json-c/issues/846) - CMP0153
* [Issue #848](https://github.com/json-c/json-c/issues/848) - json_object_from_file caused calloc SIGSEGV
* [Issue #849](https://github.com/json-c/json-c/issues/849) - random_seed.c: add a Coverity Scan suppression
* [Issue #850](https://github.com/json-c/json-c/issues/850) - Missing return description
* [Issue #851](https://github.com/json-c/json-c/issues/851) - Allow NULL in json_object_new_string() and json_object_new_string_len()
* [Issue #852](https://github.com/json-c/json-c/issues/852) - docs: micro typo in json_object_put doc
* [Issue #853](https://github.com/json-c/json-c/issues/853) - json_tokener_parse_verbose does not set the error indicator when it fails to allocate the tokener
* [Issue #854](https://github.com/json-c/json-c/issues/854) - json_tokener_parse_verbose sets the error indicator to a wrong value when there is a memory allocation failure
* [Issue #856](https://github.com/json-c/json-c/issues/856) - Using libjson-c.so or compiling from source seg faults on json_tokener_parse_ex in alpine docker container
* [Issue #857](https://github.com/json-c/json-c/issues/857) - json_tokener_parse_verbose sets the error indicator to a wrong value when there is a memory allocation failure
* [Issue #858](https://github.com/json-c/json-c/issues/858) - json_tokener.h: json_tokener_parse_verbose: fix typo
* [Issue #859](https://github.com/json-c/json-c/issues/859) - Develop
* [Issue #860](https://github.com/json-c/json-c/issues/860) - Develop
* [Issue #861](https://github.com/json-c/json-c/issues/861) - Handle yet another out-of-memory condition.
* [Issue #862](https://github.com/json-c/json-c/issues/862) - Missing `json-c-targets.cmake` during build cmake build step
* [Issue #863](https://github.com/json-c/json-c/issues/863) - build ios simulator error
* [Issue #864](https://github.com/json-c/json-c/issues/864) - Build pkg-config for msvc as well
* [Issue #865](https://github.com/json-c/json-c/issues/865) - Assertion usage
* [Issue #866](https://github.com/json-c/json-c/issues/866) - Added github actions
* [Issue #868](https://github.com/json-c/json-c/issues/868) - I meet compile error in harmony
* [Issue #869](https://github.com/json-c/json-c/issues/869) - At a high level how are jsons parses? Are they terminated by the new line?
* [Issue #870](https://github.com/json-c/json-c/issues/870) - Non-Compliant features should be optional (and disabled)
* [Issue #825](https://github.com/json-c/json-c/issues/825) - Add support for WASI
* [Issue #847](https://github.com/json-c/json-c/issues/847) - Add support for Commodore Amiga
* [Issue #867](https://github.com/json-c/json-c/issues/867) - Parsing of control characters
* [Issue #872](https://github.com/json-c/json-c/issues/872) - fix linkhash breaking -std=c89
* [Issue #873](https://github.com/json-c/json-c/issues/873) - Correct year in changelog for 0.18 release
* [Issue #874](https://github.com/json-c/json-c/issues/874) - comparison with infinity
* [Issue #875](https://github.com/json-c/json-c/issues/875) - Unicode characters seem to be rejected with JSON_TOKENER_STRICT
* [Issue #876](https://github.com/json-c/json-c/issues/876) - json_object_from_fd(_ex) doesn't work with a socket descriptor
* [Issue #877](https://github.com/json-c/json-c/issues/877) - Fix underline bug in README
* [Issue #878](https://github.com/json-c/json-c/issues/878) - Fix underline bug in README
* [Issue #879](https://github.com/json-c/json-c/issues/879) - Handle NULL gracefully in json_tokener_free
* [Issue #880](https://github.com/json-c/json-c/issues/880) - Undefined behavior when coercing NaN value to int
* [Issue #881](https://github.com/json-c/json-c/issues/881) - Tokener with depth=0 causes segmentation fault
* [Issue #882](https://github.com/json-c/json-c/issues/882) - Explicitly handle NaN values when converting to integer
* [Issue #883](https://github.com/json-c/json-c/issues/883) - Add fuzz tests for json_object/point/array apis
* [Issue #884](https://github.com/json-c/json-c/issues/884) - fix macro WIN32_LEAN_AND_MEAN redefined
* [Issue #886](https://github.com/json-c/json-c/issues/886) - Linking to json-c using cmake's find_package error
* [Issue #887](https://github.com/json-c/json-c/issues/887) - Can json-c accept invalid JSON strings?
* [Issue #888](https://github.com/json-c/json-c/issues/888) - Allow build with cmake 4.0.0
* [Issue #891](https://github.com/json-c/json-c/issues/891) - Cmake cant build only static library
* [Issue #892](https://github.com/json-c/json-c/issues/892) - JSON_TOKENER_STRICT rejects U+00BA : MASCULINE ORDINAL INDICATOR
* [Issue #893](https://github.com/json-c/json-c/issues/893) - Fix bug involving supplemental code points that look like high surrogates
* [Issue #894](https://github.com/json-c/json-c/issues/894) - json_object_to_json_string_* trims string to 32767 characters
* [Issue #895](https://github.com/json-c/json-c/issues/895) - CMake: sync minimum version
* [Issue #897](https://github.com/json-c/json-c/issues/897) - error: calloc sizes specified with sizeof in the earlier argument and not in the later argument
* [Issue #898](https://github.com/json-c/json-c/issues/898) - bug: Fixing Cmake build when using clang-cl
* [Issue #899](https://github.com/json-c/json-c/issues/899) - Meson support
* [Issue #900](https://github.com/json-c/json-c/issues/900) - meson cleanups
* [Issue #901](https://github.com/json-c/json-c/issues/901) - miscellanious gitignore updates
* [Issue #904](https://github.com/json-c/json-c/issues/904) - Include getopt.h header file if the platform is not AIX.
* [Issue #905](https://github.com/json-c/json-c/issues/905) - Fix typo
* [Issue #906](https://github.com/json-c/json-c/issues/906) - json-c: fix calloc argument order to avoid GCC14 -Wcalloc-transposed-args in arraylist.c and json_object.c
* [Issue #907](https://github.com/json-c/json-c/issues/907) - tests/CMakeLists: Allow build with CMake 4
* [Issue #908](https://github.com/json-c/json-c/issues/908) - [json-c-0.18] tests/CMakeLists: Allow build with CMake 4
* [Issue #909](https://github.com/json-c/json-c/issues/909) - compilation error with MSVC in packages that use GNU Autoconf
* [Issue #910](https://github.com/json-c/json-c/issues/910) - Support MSVC in packages that use GNU Autoconf.
* [Issue #911](https://github.com/json-c/json-c/issues/911) - Building libjson-c DLL for Windows under Cygwin: why it's named cygjson-c?
* [Issue #912](https://github.com/json-c/json-c/issues/912) - libjson-c.dll is missing VERSIONINFO
* [Issue #913](https://github.com/json-c/json-c/issues/913) - Add VERSIONINFO to libjson-c.dll

View File

@@ -176,3 +176,14 @@ JSONC_0.17 {
json_patch_apply; json_patch_apply;
# array_list_insert_idx is intentionally not exported # array_list_insert_idx is intentionally not exported
} JSONC_0.16; } JSONC_0.16;
JSONC_0.18 {
# global:
} JSONC_0.17;
JSONC_0.19 {
global:
json_pointer_set_with_limit_index;
json_pointer_set_with_cb;
json_object_array_put_with_idx_limit_cb;
} JSONC_0.18;

View File

@@ -17,11 +17,11 @@ extern "C" {
#endif #endif
#define JSON_C_MAJOR_VERSION 0 #define JSON_C_MAJOR_VERSION 0
#define JSON_C_MINOR_VERSION 16 #define JSON_C_MINOR_VERSION 18
#define JSON_C_MICRO_VERSION 99 #define JSON_C_MICRO_VERSION 99
#define JSON_C_VERSION_NUM \ #define JSON_C_VERSION_NUM \
((JSON_C_MAJOR_VERSION << 16) | (JSON_C_MINOR_VERSION << 8) | JSON_C_MICRO_VERSION) ((JSON_C_MAJOR_VERSION << 16) | (JSON_C_MINOR_VERSION << 8) | JSON_C_MICRO_VERSION)
#define JSON_C_VERSION "0.16.99" #define JSON_C_VERSION "0.18.99"
#ifndef JSON_EXPORT #ifndef JSON_EXPORT
#if defined(_MSC_VER) && defined(JSON_C_DLL) #if defined(_MSC_VER) && defined(JSON_C_DLL)

View File

@@ -29,7 +29,7 @@ typedef unsigned __int64 uint64_t;
#endif #endif
#if defined(_MSC_VER) #if defined(_MSC_VER) && !defined(ssize_t)
#include <BaseTsd.h> #include <BaseTsd.h>
typedef SSIZE_T ssize_t; typedef SSIZE_T ssize_t;
#endif #endif

View File

@@ -721,6 +721,7 @@ int32_t json_object_get_int(const struct json_object *jso)
int64_t cint64 = 0; int64_t cint64 = 0;
double cdouble; double cdouble;
enum json_type o_type; enum json_type o_type;
errno = 0;
if (!jso) if (!jso)
return 0; return 0;
@@ -756,17 +757,34 @@ int32_t json_object_get_int(const struct json_object *jso)
{ {
case json_type_int: case json_type_int:
/* Make sure we return the correct values for out of range numbers. */ /* Make sure we return the correct values for out of range numbers. */
if (cint64 <= INT32_MIN) if (cint64 < INT32_MIN)
{
errno = ERANGE;
return INT32_MIN; return INT32_MIN;
if (cint64 >= INT32_MAX) }
if (cint64 > INT32_MAX)
{
errno = ERANGE;
return INT32_MAX; return INT32_MAX;
}
return (int32_t)cint64; return (int32_t)cint64;
case json_type_double: case json_type_double:
cdouble = JC_DOUBLE_C(jso)->c_double; cdouble = JC_DOUBLE_C(jso)->c_double;
if (cdouble <= INT32_MIN) if (cdouble < INT32_MIN)
{
errno = ERANGE;
return INT32_MIN; return INT32_MIN;
if (cdouble >= INT32_MAX) }
if (cdouble > INT32_MAX)
{
errno = ERANGE;
return INT32_MAX; return INT32_MAX;
}
if (isnan(cdouble))
{
errno = EINVAL;
return INT32_MIN;
}
return (int32_t)cdouble; return (int32_t)cdouble;
case json_type_boolean: return JC_BOOL_C(jso)->c_boolean; case json_type_boolean: return JC_BOOL_C(jso)->c_boolean;
default: return 0; default: return 0;
@@ -801,6 +819,7 @@ struct json_object *json_object_new_uint64(uint64_t i)
int64_t json_object_get_int64(const struct json_object *jso) int64_t json_object_get_int64(const struct json_object *jso)
{ {
int64_t cint; int64_t cint;
errno = 0;
if (!jso) if (!jso)
return 0; return 0;
@@ -813,8 +832,11 @@ int64_t json_object_get_int64(const struct json_object *jso)
{ {
case json_object_int_type_int64: return jsoint->cint.c_int64; case json_object_int_type_int64: return jsoint->cint.c_int64;
case json_object_int_type_uint64: case json_object_int_type_uint64:
if (jsoint->cint.c_uint64 >= INT64_MAX) if (jsoint->cint.c_uint64 > INT64_MAX)
{
errno = ERANGE;
return INT64_MAX; return INT64_MAX;
}
return (int64_t)jsoint->cint.c_uint64; return (int64_t)jsoint->cint.c_uint64;
default: json_abort("invalid cint_type"); default: json_abort("invalid cint_type");
} }
@@ -822,10 +844,21 @@ int64_t json_object_get_int64(const struct json_object *jso)
case json_type_double: case json_type_double:
// INT64_MAX can't be exactly represented as a double // INT64_MAX can't be exactly represented as a double
// so cast to tell the compiler it's ok to round up. // so cast to tell the compiler it's ok to round up.
if (JC_DOUBLE_C(jso)->c_double >= (double)INT64_MAX) if (JC_DOUBLE_C(jso)->c_double > (double)INT64_MAX)
{
errno = ERANGE;
return INT64_MAX; return INT64_MAX;
if (JC_DOUBLE_C(jso)->c_double <= INT64_MIN) }
if (JC_DOUBLE_C(jso)->c_double < (double)INT64_MIN)
{
errno = ERANGE;
return INT64_MIN; return INT64_MIN;
}
if (isnan(JC_DOUBLE_C(jso)->c_double))
{
errno = EINVAL;
return INT64_MIN;
}
return (int64_t)JC_DOUBLE_C(jso)->c_double; return (int64_t)JC_DOUBLE_C(jso)->c_double;
case json_type_boolean: return JC_BOOL_C(jso)->c_boolean; case json_type_boolean: return JC_BOOL_C(jso)->c_boolean;
case json_type_string: case json_type_string:
@@ -839,6 +872,7 @@ int64_t json_object_get_int64(const struct json_object *jso)
uint64_t json_object_get_uint64(const struct json_object *jso) uint64_t json_object_get_uint64(const struct json_object *jso)
{ {
uint64_t cuint; uint64_t cuint;
errno = 0;
if (!jso) if (!jso)
return 0; return 0;
@@ -851,7 +885,10 @@ uint64_t json_object_get_uint64(const struct json_object *jso)
{ {
case json_object_int_type_int64: case json_object_int_type_int64:
if (jsoint->cint.c_int64 < 0) if (jsoint->cint.c_int64 < 0)
{
errno = ERANGE;
return 0; return 0;
}
return (uint64_t)jsoint->cint.c_int64; return (uint64_t)jsoint->cint.c_int64;
case json_object_int_type_uint64: return jsoint->cint.c_uint64; case json_object_int_type_uint64: return jsoint->cint.c_uint64;
default: json_abort("invalid cint_type"); default: json_abort("invalid cint_type");
@@ -860,10 +897,21 @@ uint64_t json_object_get_uint64(const struct json_object *jso)
case json_type_double: case json_type_double:
// UINT64_MAX can't be exactly represented as a double // UINT64_MAX can't be exactly represented as a double
// so cast to tell the compiler it's ok to round up. // so cast to tell the compiler it's ok to round up.
if (JC_DOUBLE_C(jso)->c_double >= (double)UINT64_MAX) if (JC_DOUBLE_C(jso)->c_double > (double)UINT64_MAX)
{
errno = ERANGE;
return UINT64_MAX; return UINT64_MAX;
}
if (JC_DOUBLE_C(jso)->c_double < 0) if (JC_DOUBLE_C(jso)->c_double < 0)
{
errno = ERANGE;
return 0; return 0;
}
if (isnan(JC_DOUBLE_C(jso)->c_double))
{
errno = EINVAL;
return 0;
}
return (uint64_t)JC_DOUBLE_C(jso)->c_double; return (uint64_t)JC_DOUBLE_C(jso)->c_double;
case json_type_boolean: return JC_BOOL_C(jso)->c_boolean; case json_type_boolean: return JC_BOOL_C(jso)->c_boolean;
case json_type_string: case json_type_string:

View File

@@ -172,10 +172,10 @@ JSON_EXPORT struct json_object *json_object_get(struct json_object *obj);
* is a member of (unless you know you've called `json_object_get(obj)` to * is a member of (unless you know you've called `json_object_get(obj)` to
* explicitly increment the refcount). * explicitly increment the refcount).
* *
* NULL may be passed, which which case this is a no-op. * NULL may be passed, in which case this is a no-op.
* *
* @param obj the json_object instance * @param obj the json_object instance
* @returns 1 if the object was freed. * @returns 1 if the object was freed, 0 if only the refcount was decremented
* @see json_object_get() * @see json_object_get()
*/ */
JSON_EXPORT int json_object_put(struct json_object *obj); JSON_EXPORT int json_object_put(struct json_object *obj);
@@ -191,6 +191,7 @@ JSON_EXPORT int json_object_put(struct json_object *obj);
json_type_object, json_type_object,
json_type_array, json_type_array,
json_type_string json_type_string
* @returns 1 if the object is of the specified type, 0 otherwise
*/ */
JSON_EXPORT int json_object_is_type(const struct json_object *obj, enum json_type type); JSON_EXPORT int json_object_is_type(const struct json_object *obj, enum json_type type);
@@ -458,9 +459,9 @@ JSON_EXPORT struct json_object *json_object_object_get(const struct json_object
* associated with the given field name. * associated with the given field name.
* *
* It is safe to pass a NULL value. * It is safe to pass a NULL value.
* @returns whether or not the key exists * @returns 1 if the key exists, 0 otherwise
*/ */
JSON_EXPORT json_bool json_object_object_get_ex(const struct json_object *obj, const char *key, JSON_EXPORT int json_object_object_get_ex(const struct json_object *obj, const char *key,
struct json_object **value); struct json_object **value);
/** Delete the given json_object field /** Delete the given json_object field
@@ -560,7 +561,7 @@ JSON_EXPORT struct array_list *json_object_get_array(const struct json_object *o
/** Get the length of a json_object of type json_type_array /** Get the length of a json_object of type json_type_array
* @param obj the json_object instance * @param obj the json_object instance
* @returns an int * @returns the length of the array
*/ */
JSON_EXPORT size_t json_object_array_length(const struct json_object *obj); JSON_EXPORT size_t json_object_array_length(const struct json_object *obj);
@@ -692,7 +693,7 @@ JSON_EXPORT struct json_object *json_object_new_boolean(json_bool b);
* The type is coerced to a json_bool if the passed object is not a json_bool. * The type is coerced to a json_bool if the passed object is not a json_bool.
* integer and double objects will return 0 if there value is zero * integer and double objects will return 0 if there value is zero
* or 1 otherwise. If the passed object is a string it will return * or 1 otherwise. If the passed object is a string it will return
* 1 if it has a non zero length. * 1 if it has a non zero length.
* If any other object type is passed 0 will be returned, even non-empty * If any other object type is passed 0 will be returned, even non-empty
* json_type_array and json_type_object objects. * json_type_array and json_type_object objects.
* *
@@ -738,9 +739,12 @@ JSON_EXPORT struct json_object *json_object_new_uint64(uint64_t i);
/** Get the int value of a json_object /** Get the int value of a json_object
* *
* The type is coerced to a int if the passed object is not a int. * The type is coerced to a int if the passed object is not a int.
* double objects will return their integer conversion. Strings will be * double objects will return their integer conversion except for NaN values
* parsed as an integer. If no conversion exists then 0 is returned * which return INT32_MIN and the errno is set to EINVAL.
* and errno is set to EINVAL. null is equivalent to 0 (no error values set) * Strings will be parsed as an integer. If no conversion exists then 0 is
* returned and errno is set to EINVAL. null is equivalent to 0 (no error values
* set).
* Sets errno to ERANGE if the value exceeds the range of int.
* *
* Note that integers are stored internally as 64-bit values. * Note that integers are stored internally as 64-bit values.
* If the value of too big or too small to fit into 32-bit, INT32_MAX or * If the value of too big or too small to fit into 32-bit, INT32_MAX or
@@ -782,8 +786,12 @@ JSON_EXPORT int json_object_int_inc(struct json_object *obj, int64_t val);
/** Get the int value of a json_object /** Get the int value of a json_object
* *
* The type is coerced to a int64 if the passed object is not a int64. * The type is coerced to a int64 if the passed object is not a int64.
* double objects will return their int64 conversion. Strings will be * double objects will return their int64 conversion except for NaN values
* parsed as an int64. If no conversion exists then 0 is returned. * which return INT64_MIN and the errno is set to EINVAL.
* Strings will be parsed as an int64. If no conversion exists then 0 is
* returned and errno is set to EINVAL. null is equivalent to 0 (no error values
* set).
* Sets errno to ERANGE if the value exceeds the range of int64.
* *
* NOTE: Set errno to 0 directly before a call to this function to determine * NOTE: Set errno to 0 directly before a call to this function to determine
* whether or not conversion was successful (it does not clear the value for * whether or not conversion was successful (it does not clear the value for
@@ -797,8 +805,12 @@ JSON_EXPORT int64_t json_object_get_int64(const struct json_object *obj);
/** Get the uint value of a json_object /** Get the uint value of a json_object
* *
* The type is coerced to a uint64 if the passed object is not a uint64. * The type is coerced to a uint64 if the passed object is not a uint64.
* double objects will return their uint64 conversion. Strings will be * double objects will return their uint64 conversion except for NaN values
* parsed as an uint64. If no conversion exists then 0 is returned. * which return 0 and the errno is set to EINVAL.
* Strings will be parsed as an uint64. If no conversion exists then 0 is
* returned and errno is set to EINVAL. null is equivalent to 0 (no error values
* set).
* Sets errno to ERANGE if the value exceeds the range of uint64.
* *
* NOTE: Set errno to 0 directly before a call to this function to determine * NOTE: Set errno to 0 directly before a call to this function to determine
* whether or not conversion was successful (it does not clear the value for * whether or not conversion was successful (it does not clear the value for
@@ -1042,7 +1054,7 @@ JSON_EXPORT struct json_object *json_object_new_null(void);
* *
* @param obj1 the first json_object instance * @param obj1 the first json_object instance
* @param obj2 the second json_object instance * @param obj2 the second json_object instance
* @returns whether both objects are equal or not * @returns 1 if both objects are equal, 0 otherwise
*/ */
JSON_EXPORT int json_object_equal(struct json_object *obj1, struct json_object *obj2); JSON_EXPORT int json_object_equal(struct json_object *obj1, struct json_object *obj2);

View File

@@ -28,7 +28,7 @@ struct json_object;
#include <unistd.h> #include <unistd.h>
#endif /* HAVE_UNISTD_H */ #endif /* HAVE_UNISTD_H */
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(ssize_t)
#include <BaseTsd.h> #include <BaseTsd.h>
typedef SSIZE_T ssize_t; typedef SSIZE_T ssize_t;
#endif #endif

View File

@@ -108,8 +108,9 @@ static int json_patch_apply_remove(struct json_object **res, const char *path, s
return rc; return rc;
} }
// callback for json_pointer_set_with_array_cb() // callback for json_pointer_set_with_cb()
static int json_object_array_insert_idx_cb(struct json_object *parent, size_t idx, // key is ignored because this callback is only for arrays
static int json_object_array_insert_idx_cb(struct json_object *parent, const char *key, size_t idx,
struct json_object *value, void *priv) struct json_object *value, void *priv)
{ {
int rc; int rc;
@@ -117,7 +118,7 @@ static int json_object_array_insert_idx_cb(struct json_object *parent, size_t id
if (idx > json_object_array_length(parent)) if (idx > json_object_array_length(parent))
{ {
// Note: will propagate back out through json_pointer_set_with_array_cb() // Note: will propagate back out through json_pointer_set_with_cb()
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
@@ -148,8 +149,8 @@ static int json_patch_apply_add_replace(struct json_object **res,
return -1; return -1;
} }
rc = json_pointer_set_with_array_cb(res, path, json_object_get(value), rc = json_pointer_set_with_cb(res, path, json_object_get(value),
json_object_array_insert_idx_cb, &add); json_object_array_insert_idx_cb, 0, &add);
if (rc) if (rc)
{ {
_set_err(errno, "Failed to set value at path referenced by 'path' field"); _set_err(errno, "Failed to set value at path referenced by 'path' field");
@@ -159,8 +160,9 @@ static int json_patch_apply_add_replace(struct json_object **res,
return rc; return rc;
} }
// callback for json_pointer_set_with_array_cb() // callback for json_pointer_set_with_cb()
static int json_object_array_move_cb(struct json_object *parent, size_t idx, // key is ignored because this callback is only for arrays
static int json_object_array_move_cb(struct json_object *parent, const char *key, size_t idx,
struct json_object *value, void *priv) struct json_object *value, void *priv)
{ {
int rc; int rc;
@@ -178,7 +180,7 @@ static int json_object_array_move_cb(struct json_object *parent, size_t idx,
if (idx > len) if (idx > len)
{ {
// Note: will propagate back out through json_pointer_set_with_array_cb() // Note: will propagate back out through json_pointer_set_with_cb()
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
@@ -193,7 +195,7 @@ static int json_patch_apply_move_copy(struct json_object **res,
struct json_object *patch_elem, struct json_object *patch_elem,
const char *path, int move, struct json_patch_error *patch_error) const char *path, int move, struct json_patch_error *patch_error)
{ {
json_pointer_array_set_cb array_set_cb; json_pointer_set_cb array_set_cb;
struct json_pointer_get_result from; struct json_pointer_get_result from;
struct json_object *jfrom; struct json_object *jfrom;
const char *from_s; const char *from_s;
@@ -244,7 +246,7 @@ static int json_patch_apply_move_copy(struct json_object **res,
array_set_cb = json_object_array_move_cb; array_set_cb = json_object_array_move_cb;
} }
rc = json_pointer_set_with_array_cb(res, path, from.obj, array_set_cb, &from); rc = json_pointer_set_with_cb(res, path, from.obj, array_set_cb, 0, &from);
if (rc) if (rc)
{ {
_set_err(errno, "Failed to set value at path referenced by 'path' field"); _set_err(errno, "Failed to set value at path referenced by 'path' field");

View File

@@ -120,15 +120,9 @@ static int json_pointer_get_single_path(struct json_object *obj, char *path,
return 0; return 0;
} }
static int json_object_array_put_idx_cb(struct json_object *parent, size_t idx,
struct json_object *value, void *priv)
{
return json_object_array_put_idx(parent, idx, value);
}
static int json_pointer_set_single_path(struct json_object *parent, const char *path, static int json_pointer_set_single_path(struct json_object *parent, const char *path,
struct json_object *value, struct json_object *value,
json_pointer_array_set_cb array_set_cb, void *priv) json_pointer_set_cb set_cb, int cb_handles_obj, void *priv)
{ {
if (json_object_is_type(parent, json_type_array)) if (json_object_is_type(parent, json_type_array))
{ {
@@ -138,14 +132,23 @@ static int json_pointer_set_single_path(struct json_object *parent, const char *
return json_object_array_add(parent, value); return json_object_array_add(parent, value);
if (!is_valid_index(path, &idx)) if (!is_valid_index(path, &idx))
return -1; return -1;
return array_set_cb(parent, idx, value, priv); return set_cb(parent, NULL, idx, value, priv);
} }
/* path replacements should have been done in json_pointer_get_single_path(), /* path replacements should have been done in json_pointer_get_single_path(),
* and we should still be good here * and we should still be good here
*/ */
if (json_object_is_type(parent, json_type_object)) if (json_object_is_type(parent, json_type_object))
return json_object_object_add(parent, path, value); {
if (cb_handles_obj)
{
return set_cb(parent, path, (size_t)-1, value, priv);
}
else
{
return json_object_object_add(parent, path, value);
}
}
/* Getting here means that we tried to "dereference" a primitive JSON type /* Getting here means that we tried to "dereference" a primitive JSON type
* (like string, int, bool).i.e. add a sub-object to it * (like string, int, bool).i.e. add a sub-object to it
@@ -158,7 +161,7 @@ static int json_pointer_result_get_recursive(struct json_object *obj, char *path
struct json_pointer_get_result *res) struct json_pointer_get_result *res)
{ {
struct json_object *parent_obj = obj; struct json_object *parent_obj = obj;
size_t idx; size_t idx = 0;
char *endp; char *endp;
int rc; int rc;
@@ -231,7 +234,7 @@ int json_pointer_get_internal(struct json_object *obj, const char *path,
res->parent = NULL; res->parent = NULL;
res->obj = obj; res->obj = obj;
res->key_in_parent = NULL; res->key_in_parent = NULL;
res->index_in_parent = -1; res->index_in_parent = UINT32_MAX;
return 0; return 0;
} }
@@ -298,9 +301,9 @@ out:
return rc; return rc;
} }
int json_pointer_set_with_array_cb(struct json_object **obj, const char *path, int json_pointer_set_with_cb(struct json_object **obj, const char *path,
struct json_object *value, struct json_object *value,
json_pointer_array_set_cb array_set_cb, void *priv) json_pointer_set_cb set_cb, int cb_handles_obj, void *priv)
{ {
const char *endp; const char *endp;
char *path_copy = NULL; char *path_copy = NULL;
@@ -330,7 +333,7 @@ int json_pointer_set_with_array_cb(struct json_object **obj, const char *path,
if ((endp = strrchr(path, '/')) == path) if ((endp = strrchr(path, '/')) == path)
{ {
path++; path++;
return json_pointer_set_single_path(*obj, path, value, array_set_cb, priv); return json_pointer_set_single_path(*obj, path, value, set_cb, cb_handles_obj, priv);
} }
/* pass a working copy to the recursive call */ /* pass a working copy to the recursive call */
@@ -347,12 +350,21 @@ int json_pointer_set_with_array_cb(struct json_object **obj, const char *path,
return rc; return rc;
endp++; endp++;
return json_pointer_set_single_path(set, endp, value, array_set_cb, priv); return json_pointer_set_single_path(set, endp, value, set_cb, cb_handles_obj, priv);
}
static int default_put_cb(struct json_object *parent, const char *key, size_t idx,
struct json_object *value, void *priv)
{
if (key == NULL)
return json_object_array_put_idx(parent, idx, value);
else
return json_object_object_add(parent, key, value);
} }
int json_pointer_set(struct json_object **obj, const char *path, struct json_object *value) int json_pointer_set(struct json_object **obj, const char *path, struct json_object *value)
{ {
return json_pointer_set_with_array_cb(obj, path, value, json_object_array_put_idx_cb, NULL); return json_pointer_set_with_cb(obj, path, value, default_put_cb, 1, NULL);
} }
int json_pointer_setf(struct json_object **obj, struct json_object *value, const char *path_fmt, int json_pointer_setf(struct json_object **obj, struct json_object *value, const char *path_fmt,
@@ -407,9 +419,57 @@ int json_pointer_setf(struct json_object **obj, struct json_object *value, const
set_single_path: set_single_path:
endp++; endp++;
rc = json_pointer_set_single_path(set, endp, value, rc = json_pointer_set_single_path(set, endp, value, default_put_cb, 1, NULL);
json_object_array_put_idx_cb, NULL);
out: out:
free(path_copy); free(path_copy);
return rc; return rc;
} }
int json_pointer_set_with_limit_index(struct json_object **obj, const char *path,
struct json_object *value, size_t limit_index)
{
// -1 means no limits
if (limit_index == (size_t)-1)
{
return json_pointer_set_with_cb(obj, path, value, default_put_cb, 1, NULL);
}
return json_pointer_set_with_cb(obj, path, value,
json_object_array_put_with_idx_limit_cb, 0, &limit_index);
}
/* safe callback for array index limit */
int json_object_array_put_with_idx_limit_cb(struct json_object *jso, const char *key, size_t idx,
struct json_object *jso_new, void *priv)
{
size_t max_idx;
if (key == NULL)
{
// array operation
// use priv as a size_t pointer to pass in the maximum allowed index.
// The priv is required context for this callback and must not be NULL.
if (!priv)
{
errno = EFAULT;
return -1;
}
max_idx = *(size_t*)priv;
// Check against a maximum to prevent excessive memory allocations.
// An extremely large index, even if it doesn't overflow size_t,
// will cause a huge memory allocation request via realloc,
// leading to an OOM.
if (idx > max_idx)
{
errno = EINVAL;
return -1;
}
return json_object_array_put_idx(jso, idx, jso_new);
}
else
{
// object operation
return json_object_object_add(jso, key, jso_new);
}
}

View File

@@ -81,6 +81,10 @@ JSON_EXPORT int json_pointer_getf(struct json_object *obj, struct json_object **
* That also implies that 'json_pointer_set()' does not do any refcount incrementing. * That also implies that 'json_pointer_set()' does not do any refcount incrementing.
* (Just that single decrement that was mentioned above). * (Just that single decrement that was mentioned above).
* *
* @warning This function is vulnerable to an OOM.
* To prevent this, use the safer variant 'json_pointer_set_with_limit_index()'
* or the flexible 'json_pointer_set_with_array_cb()' with a custom callback.
*
* @param obj the json_object instance/tree to which to add a sub-object * @param obj the json_object instance/tree to which to add a sub-object
* @param path a (RFC6901) string notation for the sub-object to set in the tree * @param path a (RFC6901) string notation for the sub-object to set in the tree
* @param value object to set at path * @param value object to set at path
@@ -110,6 +114,73 @@ JSON_EXPORT int json_pointer_set(struct json_object **obj, const char *path,
JSON_EXPORT int json_pointer_setf(struct json_object **obj, struct json_object *value, JSON_EXPORT int json_pointer_setf(struct json_object **obj, struct json_object *value,
const char *path_fmt, ...); const char *path_fmt, ...);
/**
* A convenient and safe variant of 'json_pointer_set()' that prevents excessive memory allocations
* by enforcing a limit on array indices.
*
* @param obj the json_object instance/tree to which to add a sub-object
* @param path a (RFC6901) string notation for the sub-object to set in the tree
* @param value object to set at path
* @param limit_index The maximum allowed value for an array index. If a path
* contains an index larger than this, the function will fail
* with errno set to EINVAL. A value of -1 can be used to specify
* no limit, reverting to the original behavior
*
* @return negative if an error (or not found), or 0 if succeeded
*/
JSON_EXPORT int json_pointer_set_with_limit_index(struct json_object **obj, const char *path,
struct json_object *value, size_t limit_index);
/**
* Callback function type.
*
* When setting an array element, 'key' will be NULL and 'idx' will be the
* target index.
* When setting an object field, 'key' will be the target key and 'idx' will
* be -1.
*/
typedef int(*json_pointer_set_cb)(json_object *parent, const char *key, size_t idx,
json_object *value, void *priv);
/**
* Variant of 'json_pointer_set()' that allows specifying a custom callback
*
* @param obj the json_object instance/tree to which to add a sub-object
* @param path a (RFC6901) string notation for the sub-object to set in the tree
* @param value object to set at path
* @param set_cb A custom callback function to handle setting the element
* @param cb_handles_obj If 0, the callback is only invoked for array modifications.
* If 1, the callback is invoked for both array and object
* modifications.
* @param priv A private pointer passed through to the set_cb callback,
* for user-defined context
*
* @return negative if an error (or not found), or 0 if succeeded
*/
JSON_EXPORT int json_pointer_set_with_cb(struct json_object **obj, const char *path,
struct json_object *value,
json_pointer_set_cb set_cb, int cb_handles_obj, void *priv);
/**
* A safer callback for 'json_pointer_set_with_cb()' that enforces a
* maximum array index.
*
* This function can be used as the 'set_cb' argument to prevent OOM.
* It expects the 'priv' argument to be a valid pointer to a 'size_t' variable
* that holds the maximum allowed index.
*
* @param jso the parent json_object array.
* @param key the object field where the element is to be placed, should be NULL here.
* @param idx the index where the element is to be placed.
* @param jso_new the new json_object to place at the index.
* @param priv A pointer to a 'size_t' variable specifying the maximum index.
* This pointer must not be NULL.
*
* @return 0 on success, or a negative value if idx exceeds the limit or 'priv' is NULL.
*/
JSON_EXPORT int json_object_array_put_with_idx_limit_cb(struct json_object *jso, const char *key, size_t idx,
struct json_object *jso_new, void *priv);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -29,12 +29,19 @@ struct json_pointer_get_result {
int json_pointer_get_internal(struct json_object *obj, const char *path, int json_pointer_get_internal(struct json_object *obj, const char *path,
struct json_pointer_get_result *res); struct json_pointer_get_result *res);
typedef int(*json_pointer_array_set_cb)(json_object *parent, size_t idx, // replaced by json_pointer_set_cb
json_object *value, void *priv); // typedef int(*json_pointer_array_set_cb)(json_object *parent, size_t idx,
// json_object *value, void *priv);
typedef int(*json_pointer_set_cb)(json_object *parent, const char *key, size_t idx,
json_object *value, void *priv);
int json_pointer_set_with_array_cb(struct json_object **obj, const char *path, // replaced by json_pointer_set_with_cb
// int json_pointer_set_with_array_cb(struct json_object **obj, const char *path,
// struct json_object *value,
// json_pointer_array_set_cb array_set_cb, void *priv);
int json_pointer_set_with_cb(struct json_object **obj, const char *path,
struct json_object *value, struct json_object *value,
json_pointer_array_set_cb array_set_cb, void *priv); json_pointer_set_cb set_cb, int cb_handles_obj, void *priv);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -46,7 +46,7 @@
#define jt_hexdigit(x) (((x) <= '9') ? (x) - '0' : ((x)&7) + 9) #define jt_hexdigit(x) (((x) <= '9') ? (x) - '0' : ((x)&7) + 9)
#if !HAVE_STRNCASECMP && defined(_MSC_VER) #if !HAVE_STRNCASECMP && defined(_WIN32)
/* MSC has the version as _strnicmp */ /* MSC has the version as _strnicmp */
#define strncasecmp _strnicmp #define strncasecmp _strnicmp
#elif !HAVE_STRNCASECMP #elif !HAVE_STRNCASECMP
@@ -145,8 +145,8 @@ enum json_tokener_error json_tokener_get_error(struct json_tokener *tok)
} }
/* Stuff for decoding unicode sequences */ /* Stuff for decoding unicode sequences */
#define IS_HIGH_SURROGATE(uc) (((uc)&0xFC00) == 0xD800) #define IS_HIGH_SURROGATE(uc) (((uc)&0xFFFFFC00) == 0xD800)
#define IS_LOW_SURROGATE(uc) (((uc)&0xFC00) == 0xDC00) #define IS_LOW_SURROGATE(uc) (((uc)&0xFFFFFC00) == 0xDC00)
#define DECODE_SURROGATE_PAIR(hi, lo) ((((hi)&0x3FF) << 10) + ((lo)&0x3FF) + 0x10000) #define DECODE_SURROGATE_PAIR(hi, lo) ((((hi)&0x3FF) << 10) + ((lo)&0x3FF) + 0x10000)
static unsigned char utf8_replacement_char[3] = {0xEF, 0xBF, 0xBD}; static unsigned char utf8_replacement_char[3] = {0xEF, 0xBF, 0xBD};
@@ -154,6 +154,9 @@ struct json_tokener *json_tokener_new_ex(int depth)
{ {
struct json_tokener *tok; struct json_tokener *tok;
if (depth < 1)
return NULL;
tok = (struct json_tokener *)calloc(1, sizeof(struct json_tokener)); tok = (struct json_tokener *)calloc(1, sizeof(struct json_tokener));
if (!tok) if (!tok)
return NULL; return NULL;
@@ -182,6 +185,8 @@ struct json_tokener *json_tokener_new(void)
void json_tokener_free(struct json_tokener *tok) void json_tokener_free(struct json_tokener *tok)
{ {
if (!tok)
return;
json_tokener_reset(tok); json_tokener_reset(tok);
if (tok->pb) if (tok->pb)
printbuf_free(tok->pb); printbuf_free(tok->pb);
@@ -226,7 +231,10 @@ struct json_object *json_tokener_parse_verbose(const char *str, enum json_tokene
tok = json_tokener_new(); tok = json_tokener_new();
if (!tok) if (!tok)
{
*error = json_tokener_error_memory;
return NULL; return NULL;
}
obj = json_tokener_parse_ex(tok, str, -1); obj = json_tokener_parse_ex(tok, str, -1);
*error = tok->err; *error = tok->err;
if (tok->err != json_tokener_success if (tok->err != json_tokener_success
@@ -337,17 +345,31 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
#ifdef HAVE_USELOCALE #ifdef HAVE_USELOCALE
{ {
#ifdef HAVE_DUPLOCALE
locale_t duploc = duplocale(oldlocale); locale_t duploc = duplocale(oldlocale);
if (duploc == NULL && errno == ENOMEM)
{
tok->err = json_tokener_error_memory;
return NULL;
}
newloc = newlocale(LC_NUMERIC_MASK, "C", duploc); newloc = newlocale(LC_NUMERIC_MASK, "C", duploc);
#else
newloc = newlocale(LC_NUMERIC_MASK, "C", oldlocale);
#endif
if (newloc == NULL) if (newloc == NULL)
{ {
tok->err = json_tokener_error_memory;
#ifdef HAVE_DUPLOCALE
freelocale(duploc); freelocale(duploc);
#endif
return NULL; return NULL;
} }
#ifdef NEWLOCALE_NEEDS_FREELOCALE #ifdef NEWLOCALE_NEEDS_FREELOCALE
#ifdef HAVE_DUPLOCALE
// Older versions of FreeBSD (<12.4) don't free the locale // Older versions of FreeBSD (<12.4) don't free the locale
// passed to newlocale(), so do it here // passed to newlocale(), so do it here
freelocale(duploc); freelocale(duploc);
#endif
#endif #endif
uselocale(newloc); uselocale(newloc);
} }
@@ -359,7 +381,10 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
{ {
oldlocale = strdup(tmplocale); oldlocale = strdup(tmplocale);
if (oldlocale == NULL) if (oldlocale == NULL)
{
tok->err = json_tokener_error_memory;
return NULL; return NULL;
}
} }
setlocale(LC_NUMERIC, "C"); setlocale(LC_NUMERIC, "C");
} }
@@ -666,6 +691,12 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
state = json_tokener_state_string_escape; state = json_tokener_state_string_escape;
break; break;
} }
else if ((tok->flags & JSON_TOKENER_STRICT) && (unsigned char)c <= 0x1f)
{
// Disallow control characters in strict mode
tok->err = json_tokener_error_parse_string;
goto out;
}
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
{ {
printbuf_memappend_checked(tok->pb, case_start, printbuf_memappend_checked(tok->pb, case_start,
@@ -1219,6 +1250,12 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
state = json_tokener_state_string_escape; state = json_tokener_state_string_escape;
break; break;
} }
else if ((tok->flags & JSON_TOKENER_STRICT) && (unsigned char)c <= 0x1f)
{
// Disallow control characters in strict mode
tok->err = json_tokener_error_parse_string;
goto out;
}
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
{ {
printbuf_memappend_checked(tok->pb, case_start, printbuf_memappend_checked(tok->pb, case_start,
@@ -1254,7 +1291,11 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
goto redo_char; goto redo_char;
case json_tokener_state_object_value_add: case json_tokener_state_object_value_add:
json_object_object_add(current, obj_field_name, obj); if (json_object_object_add(current, obj_field_name, obj) != 0)
{
tok->err = json_tokener_error_memory;
goto out;
}
free(obj_field_name); free(obj_field_name);
obj_field_name = NULL; obj_field_name = NULL;
saved_state = json_tokener_state_object_sep; saved_state = json_tokener_state_object_sep;

View File

@@ -40,8 +40,8 @@ enum json_tokener_error
json_tokener_error_parse_string, json_tokener_error_parse_string,
json_tokener_error_parse_comment, json_tokener_error_parse_comment,
json_tokener_error_parse_utf8_string, json_tokener_error_parse_utf8_string,
json_tokener_error_memory, json_tokener_error_size, /* A string longer than INT32_MAX was passed as input */
json_tokener_error_size json_tokener_error_memory /* Failed to allocate memory */
}; };
/** /**
@@ -206,6 +206,7 @@ JSON_EXPORT struct json_tokener *json_tokener_new(void);
/** /**
* Allocate a new json_tokener with a custom max nesting depth. * Allocate a new json_tokener with a custom max nesting depth.
* The depth must be at least 1.
* @see JSON_TOKENER_DEFAULT_DEPTH * @see JSON_TOKENER_DEFAULT_DEPTH
*/ */
JSON_EXPORT struct json_tokener *json_tokener_new_ex(int depth); JSON_EXPORT struct json_tokener *json_tokener_new_ex(int depth);
@@ -230,7 +231,7 @@ JSON_EXPORT void json_tokener_reset(struct json_tokener *tok);
JSON_EXPORT struct json_object *json_tokener_parse(const char *str); JSON_EXPORT struct json_object *json_tokener_parse(const char *str);
/** /**
* Parser a json_object out of the string `str`, but if it fails * Parse a json_object out of the string `str`, but if it fails
* return the error in `*error`. * return the error in `*error`.
* @see json_tokener_parse() * @see json_tokener_parse()
* @see json_tokener_parse_ex() * @see json_tokener_parse_ex()

View File

@@ -37,13 +37,15 @@
#include <unistd.h> #include <unistd.h>
#endif /* HAVE_UNISTD_H */ #endif /* HAVE_UNISTD_H */
#ifdef WIN32 #ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#endif
#include <io.h> #include <io.h>
#include <windows.h> #include <windows.h>
#endif /* defined(WIN32) */ #endif /* defined(_WIN32) */
#if !defined(HAVE_OPEN) && defined(WIN32) #if !defined(HAVE_OPEN) && defined(_WIN32)
#define open _open #define open _open
#endif #endif

37
libjson.rc Normal file
View File

@@ -0,0 +1,37 @@
#include <winver.h>
#include "json_c_version.h"
VS_VERSION_INFO VERSIONINFO
FILEVERSION JSON_C_MAJOR_VERSION,JSON_C_MINOR_VERSION,JSON_C_MICRO_VERSION,0
PRODUCTVERSION JSON_C_MAJOR_VERSION,JSON_C_MINOR_VERSION,JSON_C_MICRO_VERSION,0
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
#ifdef _DEBUG
FILEFLAGS VS_FF_DEBUG
#else
FILEFLAGS 0x0L
#endif
FILEOS VOS_DOS_WINDOWS32
FILETYPE VFT_DLL
FILESUBTYPE VFT2_UNKNOWN
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "04090000" /* Lang = US English, Charset = ASCII */
BEGIN
VALUE "Comments", "A JSON implementation in C\0"
VALUE "CompanyName", "Eric Haszlakiewicz\0"
VALUE "FileDescription", "JSON-C\0"
VALUE "FileVersion", JSON_C_VERSION "\0"
VALUE "InternalName", "libjson-c.dll\0"
VALUE "LegalCopyright", "MIT License, 2009-2012\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "libjson-c.dll\0"
VALUE "ProductName", "JSON-C\0"
VALUE "ProductVersion", JSON_C_VERSION "\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0409, 0 /* US English, ASCII */
END
END

View File

@@ -25,7 +25,9 @@
#endif #endif
#if defined(_MSC_VER) || defined(__MINGW32__) #if defined(_MSC_VER) || defined(__MINGW32__)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h> /* Get InterlockedCompareExchange */ #include <windows.h> /* Get InterlockedCompareExchange */
#endif #endif

View File

@@ -334,8 +334,9 @@ int lh_table_resize(struct lh_table *t, int new_size);
/** /**
* @deprecated Don't use this outside of linkhash.h: * @deprecated Don't use this outside of linkhash.h:
*/ */
#if (defined(AIX_CC) || (defined(_MSC_VER) && (_MSC_VER <= 1800)) ) #if !defined (__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
/* VS2010 can't handle inline funcs, so skip it there */ /* C89 compilers like VS2010 can't handle inline funcs, so skip it there,
note: this also applies to -std=c89 in GCC! */
#define _LH_INLINE #define _LH_INLINE
#else #else
#define _LH_INLINE inline #define _LH_INLINE inline

284
meson.build Normal file
View File

@@ -0,0 +1,284 @@
project('json-c', 'c', version: '0.18.99',
meson_version: '>=0.54.0',
license: 'MIT',
default_options: ['buildtype=release', 'warning_level=2'])
cc = meson.get_compiler('c')
# Configuration header generation
conf_data = configuration_data()
jconf_data = configuration_data()
conf_data.set('VERSION', meson.project_version())
has_std_lib = cc.has_header('stdlib.h')
has_std_arg = cc.has_header('stdarg.h')
has_string = cc.has_header('string.h')
has_float = cc.has_header('float.h')
if has_std_lib and has_std_arg and has_string and has_float
conf_data.set('STDC_HEADERS', 1, description : 'Define to 1 if you have the ANSI C header files.')
endif
bsd_dep = dependency('libbsd', required: false)
headers = {
'bsd/stdlib.h': bsd_dep,
'dlfcn.h': [],
'endian.h': [],
'fcntl.h': [],
'inttypes.h': [],
'limits.h': [],
'locale.h': [],
'memory.h': [],
'stdarg.h': [],
'stdint.h': [],
'stdlib.h': [],
'string.h': [],
'strings.h': [],
'syslog.h': [],
'sys/cdefs.h': [],
'sys/param.h': [],
'sys/random.h': [],
'sys/resource.h': [],
'sys/stat.h': [],
'sys/types.h': [],
'unistd.h': [],
'xlocale.h': [],
}
foreach h, d : headers
if cc.has_header(h, dependencies: d)
conf_data.set('HAVE_@0@'.format(h.underscorify().to_upper()), 1, description : 'Define to 1 if you have the <@0@> header file'.format(h))
endif
endforeach
if cc.has_header('inttypes.h')
conf_data.set('JSON_C_HAVE_INTTYPES_H', 1, description : 'Define to 1 if you have the <inttypes.h> header file.')
jconf_data.set('JSON_C_HAVE_INTTYPES_H', 1, description : 'Define to 1 if you have the <inttypes.h> header file.')
endif
if cc.has_header('stdint.h')
conf_data.set('JSON_C_HAVE_STDINT_H', 1, description : 'Define to 1 if you have the <stdint.h> header file.')
jconf_data.set('JSON_C_HAVE_STDINT_H', 1, description : 'Define to 1 if you have the <stdint.h> header file.')
endif
funcs = [
'open',
'realloc',
'setlocale',
'strdup',
'strerror',
'uselocale',
'duplocale',
'vsyslog',
'getrandom',
'getrusage',
'strtoll',
'strtoull',
'arc4random',
'vasprintf',
]
if conf_data.has('HAVE_STRINGS_H')
funcs += ['strcasecmp', 'strncasecmp']
endif
foreach f : funcs
if cc.has_function(f)
conf_data.set('HAVE_@0@'.format(f.to_upper()), 1, description : 'Define to 1 if you have the `@0@` function.'.format(f))
endif
endforeach
foreach f : ['snprintf', 'vsnprintf', 'vprintf']
if cc.has_header_symbol('stdio.h', f)
conf_data.set('HAVE_@0@'.format(f.to_upper()), 1, description : 'Define to 1 if you have the `@0@` function.'.format(f))
endif
endforeach
if not conf_data.has('HAVE_VPRINTF') and cc.has_function('_doprnt')
conf_data.set('HAVE_DOPRNT', 1, description : 'Define to 1 if you have _doprnt but not vprintf.')
endif
if conf_data.has('HAVE_STRTOLL')
conf_data.set('json_c_strtoll', 'strtoll')
elif cc.has_function('_strtoi64', prefix : '#include <stdlib.h>')
conf_data.set('json_c_strtoll', '_strtoi64')
endif
if conf_data.has('HAVE_STRTOULL')
conf_data.set('json_c_strtoull', 'strtoull')
elif cc.has_function('_strtoui64', prefix : '#include <stdlib.h>')
conf_data.set('json_c_strtoull', '_strtoui64')
endif
decls = {
'INFINITY': 'math.h',
'isinf': 'math.h',
'isnan': 'math.h',
'NAN': 'math.h',
'_finite': 'float.h',
'_isnan': 'float.h',
}
foreach d, h : decls
if cc.has_header_symbol(h, d)
conf_data.set('HAVE_DECL_@0@'.format(d.to_upper()), 1, description : 'Define to 1 if you have the declaration of `@0@`'.format(d))
endif
endforeach
check_thread = cc.compiles('__thread int x;', name: 'Check for __thread support')
if check_thread
conf_data.set('HAVE___THREAD', 1)
conf_data.set('SPEC___THREAD', '__thread')
elif cc.get_argument_syntax() == 'msvc'
conf_data.set('SPEC___THREAD', '__declspec(thread)')
endif
gnu_warning_section_support = cc.compiles('''
extern void json_object_get();
__asm__(".section .gnu.json_object_get\n\t.ascii \"Please link against libjson-c instead of libjson\"\n\t.text");
int main(int c, char *v) { return 0; }
''', name: 'Check for GNU warning section support')
if gnu_warning_section_support
conf_data.set('HAS_GNU_WARNING_LONG', 1, description : 'Define to 1 if the compiler supports .gnu.warning sections.')
endif
atomic_builtin_support = cc.compiles('''
int main() {
int x = 0;
int i = __sync_add_and_fetch(&x, 1);
return x;
}
''',
name: 'Check for atomic builtins')
if atomic_builtin_support
conf_data.set('HAVE_ATOMIC_BUILTINS', 1, description : 'Define to 1 if the compiler supports atomic builtins.')
endif
if get_option('enable_rdrand')
conf_data.set('ENABLE_RDRAND', 1)
endif
if get_option('override_get_random_seed')
conf_data.set('OVERRIDE_GET_RANDOM_SEED', get_option('override_get_random_seed'))
endif
if get_option('enable_threading')
conf_data.set('ENABLE_THREADING', 1)
endif
if get_option('newlocale_needs_freelocale')
conf_data.set('NEWLOCALE_NEEDS_FREELOCALE', 1)
endif
conf_data.set('SIZEOF_INT', cc.sizeof('int'))
conf_data.set('SIZEOF_INT64_T', cc.sizeof('int64_t', prefix : '#include <stdint.h>'))
conf_data.set('SIZEOF_LONG', cc.sizeof('long'))
conf_data.set('SIZEOF_LONG_LONG', cc.sizeof('long long'))
conf_data.set('SIZEOF_SIZE_T', cc.sizeof('size_t', prefix : '#include <stddef.h>'))
if cc.get_argument_syntax() == 'msvc'
conf_data.set('SIZEOF_SSIZE_T', cc.sizeof('SSIZE_T', prefix : '#include <BaseTsd.h>\n#include <stddef.h>'))
else
conf_data.set('SIZEOF_SSIZE_T', cc.sizeof('ssize_t', prefix : '#include <sys/types.h>'))
endif
conf_data.set('PACKAGE_VERSION', meson.project_version())
conf_data.set('PROJECT_NAME', meson.project_name())
configure_header = configure_file(
output: 'config.h',
configuration: conf_data
)
json_configure_header = configure_file(
output: 'json_config.h',
configuration: jconf_data
)
jhconf_data = configuration_data()
jhconf_data.set('JSON_H_JSON_PATCH',
get_option('disable_json_patch') ? '' : '#include "json_patch.h"'
)
jhconf_data.set('JSON_H_JSON_POINTER',
get_option('disable_json_pointer') ? '' : '#include "json_pointer.h"'
)
json_header = configure_file(
input: 'json.h.cmakein',
output: 'json.h',
configuration: jhconf_data
)
# Platform-specific flags
add_project_arguments('-D_GNU_SOURCE', language: 'c')
if host_machine.system() == 'windows'
add_project_arguments('-DWIN32', language: 'c')
endif
# Compiler flags
message('target is ' + host_machine.system())
if host_machine.system() == 'windows'
# Cover any compiler on Windows attempting to use MSVC's standard library
add_project_arguments('-D_CRT_NONSTDC_NO_DEPRECATE', '-D_CRT_SECURE_NO_WARNINGS', language: 'c')
endif
add_project_arguments(cc.get_supported_arguments('-Wno-unused-parameter'), language : 'c')
sym = cc.get_supported_link_arguments(
'-Wl,--version-script,@0@/json-c.sym'.format(
meson.current_source_dir(),
),
)
# Source files
sources = files(
'arraylist.c', 'debug.c', 'json_c_version.c', 'json_object.c',
'json_object_iterator.c', 'json_tokener.c', 'json_util.c',
'json_visit.c', 'linkhash.c', 'printbuf.c', 'random_seed.c',
'strerror_override.c'
)
if not get_option('disable_json_pointer')
sources += files('json_pointer.c')
if not get_option('disable_json_patch')
sources += files('json_patch.c')
endif
endif
# Include directories
inc = include_directories('.')
# Build library
libjson = library('json-c',
sources,
include_directories: inc,
dependencies: bsd_dep,
install: true,
link_args: sym,
version: '5.4.0',
soversion: '5',
)
jsonc_dep = declare_dependency(link_with: libjson, include_directories: inc)
meson.override_dependency('json-c', jsonc_dep)
# Install headers
install_headers(
'arraylist.h', 'debug.h', 'json_c_version.h', 'json_inttypes.h',
'json_object.h', 'json_object_iterator.h', 'json_tokener.h',
'json_types.h', 'json_util.h', 'json_visit.h', 'linkhash.h',
'printbuf.h', json_configure_header, json_header
)
# Optional apps
if get_option('build_apps') and host_machine.system() != 'windows'
subdir('apps')
endif
# Optional tests
if get_option('buildtype') == 'debug'
subdir('tests')
endif

11
meson_options.txt Normal file
View File

@@ -0,0 +1,11 @@
option('disable_bsymbolic', type: 'boolean', value: false, description: 'Avoid linking with -Bsymbolic-function')
option('disable_thread_local_storage', type: 'boolean', value: false, description: 'Disable Thread-Local Storage')
option('enable_rdrand', type: 'boolean', value: false, description: 'Enable RDRAND Hardware RNG')
option('enable_threading', type: 'boolean', value: false, description: 'Enable partial threading support')
option('override_get_random_seed', type: 'boolean', value: false, description: 'Override json_c_get_random_seed()')
option('disable_extra_libs', type: 'boolean', value: false, description: 'Avoid linking extra libraries like libbsd')
option('disable_json_pointer', type: 'boolean', value: false, description: 'Disable JSON pointer support')
option('disable_json_patch', type: 'boolean', value: false, description: 'Disable JSON patch support')
option('newlocale_needs_freelocale', type: 'boolean', value: false, description: 'FreeBSD workaround for newlocale')
option('build_apps', type: 'boolean', value: true, description: 'Build command-line apps')

View File

@@ -46,7 +46,7 @@ static void do_cpuid(int regs[], int h)
/* clang-format on */ /* clang-format on */
} }
#elif defined _MSC_VER #elif defined _MSC_VER && (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64))
#define HAS_X86_CPUID 1 #define HAS_X86_CPUID 1
#define do_cpuid __cpuid #define do_cpuid __cpuid
@@ -129,7 +129,7 @@ static int get_rdrand_seed(void)
#endif #endif
#if defined _MSC_VER #if defined _MSC_VER && (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64))
#if _MSC_VER >= 1700 #if _MSC_VER >= 1700
#define HAVE_RDRAND 1 #define HAVE_RDRAND 1
@@ -229,6 +229,7 @@ static int get_dev_random_seed(int *seed)
if ((buf.st_mode & S_IFCHR) == 0) if ((buf.st_mode & S_IFCHR) == 0)
return -1; return -1;
/* coverity[toctou] */
int fd = open(dev_random_file, O_RDONLY); int fd = open(dev_random_file, O_RDONLY);
if (fd < 0) if (fd < 0)
{ {
@@ -253,7 +254,7 @@ static int get_dev_random_seed(int *seed)
/* get_cryptgenrandom_seed */ /* get_cryptgenrandom_seed */
#ifdef WIN32 #ifdef _WIN32
#define HAVE_CRYPTGENRANDOM 1 #define HAVE_CRYPTGENRANDOM 1

View File

@@ -36,6 +36,6 @@ static int json_c_snprintf(char *str, size_t size, const char *format, ...)
#elif !defined(HAVE_SNPRINTF) /* !HAVE_SNPRINTF */ #elif !defined(HAVE_SNPRINTF) /* !HAVE_SNPRINTF */
#error snprintf is required but was not found #error snprintf is required but was not found
#endif /* !HAVE_SNPRINTF && defined(WIN32) */ #endif /* !HAVE_SNPRINTF */
#endif /* __snprintf_compat_h */ #endif /* __snprintf_compat_h */

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.1) cmake_minimum_required(VERSION 3.9...3.12) # see ../CMakeLists.txt for why
add_executable(test1Formatted test1.c parse_flags.c parse_flags.h) add_executable(test1Formatted test1.c parse_flags.c parse_flags.h)
target_compile_definitions(test1Formatted PRIVATE TEST_FORMATTED=1) target_compile_definitions(test1Formatted PRIVATE TEST_FORMATTED=1)
target_link_libraries(test1Formatted PRIVATE ${PROJECT_NAME}) target_link_libraries(test1Formatted PRIVATE ${PROJECT_NAME})
@@ -39,6 +39,7 @@ set(ALL_TEST_NAMES
if (NOT DISABLE_JSON_POINTER) if (NOT DISABLE_JSON_POINTER)
set(ALL_TEST_NAMES ${ALL_TEST_NAMES} test_json_pointer) set(ALL_TEST_NAMES ${ALL_TEST_NAMES} test_json_pointer)
set(ALL_TEST_NAMES ${ALL_TEST_NAMES} test_safe_json_pointer_set)
if (NOT DISABLE_JSON_PATCH) if (NOT DISABLE_JSON_PATCH)
set(ALL_TEST_NAMES ${ALL_TEST_NAMES} test_json_patch) set(ALL_TEST_NAMES ${ALL_TEST_NAMES} test_json_patch)
endif() endif()

76
tests/meson.build Normal file
View File

@@ -0,0 +1,76 @@
#This hack is needed for Windows tests
test_lib = static_library(
'jsonctest',
objects: libjson.extract_all_objects(
recursive: false,
),
install: false,
)
test_deps = declare_dependency(
include_directories: '..',
link_with: test_lib,
)
# List of test sources and expected output files
test_cases = [
['test1', 'test1.expected'],
['test2', 'test2.expected'],
['test4', 'test4.expected'],
['testReplaceExisting', 'testReplaceExisting.expected'],
['test_cast', 'test_cast.expected'],
['test_charcase', 'test_charcase.expected'],
['test_compare', 'test_compare.expected'],
['test_deep_copy', 'test_deep_copy.expected'],
['test_double_serializer', 'test_double_serializer.expected'],
['test_float', 'test_float.expected'],
['test_int_add', 'test_int_add.expected'],
['test_int_get', 'test_int_get.expected'],
['test_locale', 'test_locale.expected'],
['test_null', 'test_null.expected'],
['test_parse', 'test_parse.expected'],
['test_parse_int64', 'test_parse_int64.expected'],
['test_printbuf', 'test_printbuf.expected'],
['test_set_serializer', 'test_set_serializer.expected'],
['test_set_value', 'test_set_value.expected'],
['test_strerror', 'test_strerror.expected'],
['test_util_file', 'test_util_file.expected'],
['test_visit', 'test_visit.expected'],
['test_object_iterator', 'test_object_iterator.expected'],
['test_json_pointer', 'test_json_pointer.expected'],
['test_safe_json_pointer_set', 'test_safe_json_pointer_set.expected'],
['test_json_patch', 'test_json_patch.expected'],
]
# Copy expected files and test data
expected_files = []
foreach t : test_cases
expected_files += t[1]
endforeach
foreach f : expected_files + ['valid.json', 'valid_nested.json', 'json_patch_spec_tests.json', 'json_patch_tests.json']
configure_file(input: f, output: f, copy: true)
endforeach
# Build and register tests
special_args = {
'test_json_patch': ['.'],
'test_util_file': ['.'],
}
testdir = meson.current_build_dir()
message('Test data directory: ' + testdir)
foreach t : test_cases
name = t[0]
expected = t[1]
exe = executable(name, name + '.c',
dependencies: test_deps
)
test(name, exe,
args: special_args.get(name, []),
env: ['EXPECTED_FILE=' + meson.current_build_dir() / expected],
workdir: testdir
)
endforeach

View File

@@ -36,6 +36,7 @@ int main(int argc, char **argv)
\"array_with_zero\": [ 0 ],\n\ \"array_with_zero\": [ 0 ],\n\
\"empty_object\": {},\n\ \"empty_object\": {},\n\
\"nonempty_object\": { \"a\": 123 },\n\ \"nonempty_object\": { \"a\": 123 },\n\
\"nan\": NaN,\n\
}"; }";
/* Note: 2147483649 = INT_MAX + 2 */ /* Note: 2147483649 = INT_MAX + 2 */
/* Note: 9223372036854775809 = INT64_MAX + 2 */ /* Note: 9223372036854775809 = INT64_MAX + 2 */
@@ -62,6 +63,7 @@ int main(int argc, char **argv)
getit(new_obj, "array_with_zero"); getit(new_obj, "array_with_zero");
getit(new_obj, "empty_object"); getit(new_obj, "empty_object");
getit(new_obj, "nonempty_object"); getit(new_obj, "nonempty_object");
getit(new_obj, "nan");
// Now check the behaviour of the json_object_is_type() function. // Now check the behaviour of the json_object_is_type() function.
printf("\n================================\n"); printf("\n================================\n");
@@ -75,6 +77,7 @@ int main(int argc, char **argv)
checktype(new_obj, "int64_number"); checktype(new_obj, "int64_number");
checktype(new_obj, "negative_number"); checktype(new_obj, "negative_number");
checktype(new_obj, "a_null"); checktype(new_obj, "a_null");
checktype(new_obj, "nan");
json_object_put(new_obj); json_object_put(new_obj);

View File

@@ -12,6 +12,7 @@ Parsed input: {
"array_with_zero": [ 0 ], "array_with_zero": [ 0 ],
"empty_object": {}, "empty_object": {},
"nonempty_object": { "a": 123 }, "nonempty_object": { "a": 123 },
"nan": NaN,
} }
Result is not NULL Result is not NULL
new_obj.string_of_digits json_object_get_type()=string new_obj.string_of_digits json_object_get_type()=string
@@ -92,6 +93,12 @@ new_obj.nonempty_object json_object_get_int64()=0
new_obj.nonempty_object json_object_get_uint64()=0 new_obj.nonempty_object json_object_get_uint64()=0
new_obj.nonempty_object json_object_get_boolean()=0 new_obj.nonempty_object json_object_get_boolean()=0
new_obj.nonempty_object json_object_get_double()=0.000000 new_obj.nonempty_object json_object_get_double()=0.000000
new_obj.nan json_object_get_type()=double
new_obj.nan json_object_get_int()=-2147483648
new_obj.nan json_object_get_int64()=-9223372036854775808
new_obj.nan json_object_get_uint64()=0
new_obj.nan json_object_get_boolean()=1
new_obj.nan json_object_get_double()=nan
================================ ================================
json_object_is_type: null,boolean,double,int,object,array,string json_object_is_type: null,boolean,double,int,object,array,string
@@ -104,3 +111,4 @@ new_obj.boolean_false : 0,1,0,0,0,0,0
new_obj.int64_number : 0,0,0,1,0,0,0 new_obj.int64_number : 0,0,0,1,0,0,0
new_obj.negative_number : 0,0,0,1,0,0,0 new_obj.negative_number : 0,0,0,1,0,0,0
new_obj.a_null : 1,0,0,0,0,0,0 new_obj.a_null : 1,0,0,0,0,0,0
new_obj.nan : 0,0,1,0,0,0,0

View File

@@ -4,9 +4,12 @@
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <errno.h> #include <errno.h>
#include <math.h>
#include "json.h" #include "json.h"
#define I32_MAX_S "2147483647"
#define I32_MIN_S "-2147483648"
#define I64_MAX_S "9223372036854775807" #define I64_MAX_S "9223372036854775807"
#define I64_OVER "9223372036854775808" #define I64_OVER "9223372036854775808"
#define I64_MIN_S "-9223372036854775808" #define I64_MIN_S "-9223372036854775808"
@@ -25,6 +28,7 @@
#define N_I64 json_object_new_int64 #define N_I64 json_object_new_int64
#define N_U64 json_object_new_uint64 #define N_U64 json_object_new_uint64
#define N_STR json_object_new_string #define N_STR json_object_new_string
#define N_DBL json_object_new_double
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
@@ -41,10 +45,15 @@ int main(int argc, char **argv)
CHECK_GET_INT(N_I64(INT32_MAX), INT32_MAX && errno == 0); CHECK_GET_INT(N_I64(INT32_MAX), INT32_MAX && errno == 0);
CHECK_GET_INT(N_I64(INT32_MIN), INT32_MIN && errno == 0); CHECK_GET_INT(N_I64(INT32_MIN), INT32_MIN && errno == 0);
CHECK_GET_INT(N_I64(INT64_MAX), INT32_MAX && errno == 0); CHECK_GET_INT(N_I64(INT64_MAX), INT32_MAX && errno == ERANGE);
CHECK_GET_INT(N_I64(INT64_MIN), INT32_MIN && errno == 0); CHECK_GET_INT(N_I64(INT64_MIN), INT32_MIN && errno == ERANGE);
CHECK_GET_INT(N_STR(I64_MAX_S), INT32_MAX && errno == 0); CHECK_GET_INT(N_STR(I32_MAX_S), INT32_MAX && errno == 0);
CHECK_GET_INT(N_STR(I64_MIN_S), INT32_MIN && errno == 0); CHECK_GET_INT(N_STR(I32_MIN_S), INT32_MIN && errno == 0);
CHECK_GET_INT(N_STR(I64_MAX_S), INT32_MAX && errno == ERANGE);
CHECK_GET_INT(N_STR(I64_MIN_S), INT32_MIN && errno == ERANGE);
CHECK_GET_INT(N_DBL(INFINITY), INT32_MAX && errno == ERANGE);
CHECK_GET_INT(N_DBL(-INFINITY), INT32_MIN && errno == ERANGE);
CHECK_GET_INT(N_DBL(NAN), INT32_MIN && errno == EINVAL);
printf("INT GET PASSED\n"); printf("INT GET PASSED\n");
CHECK_GET_INT64(N_I64(INT64_MAX), INT64_MAX && errno == 0); CHECK_GET_INT64(N_I64(INT64_MAX), INT64_MAX && errno == 0);
@@ -53,11 +62,17 @@ int main(int argc, char **argv)
CHECK_GET_INT64(N_STR(I64_MIN_S), INT64_MIN && errno == 0); CHECK_GET_INT64(N_STR(I64_MIN_S), INT64_MIN && errno == 0);
CHECK_GET_INT64(N_STR(I64_OVER), INT64_MAX && errno == ERANGE); CHECK_GET_INT64(N_STR(I64_OVER), INT64_MAX && errno == ERANGE);
CHECK_GET_INT64(N_STR(I64_UNDER), INT64_MIN && errno == ERANGE); CHECK_GET_INT64(N_STR(I64_UNDER), INT64_MIN && errno == ERANGE);
CHECK_GET_INT64(N_DBL(INFINITY), INT64_MAX && errno == ERANGE);
CHECK_GET_INT64(N_DBL(-INFINITY), INT64_MIN && errno == ERANGE);
CHECK_GET_INT64(N_DBL(NAN), INT64_MIN && errno == EINVAL);
printf("INT64 GET PASSED\n"); printf("INT64 GET PASSED\n");
CHECK_GET_UINT64(N_U64(UINT64_MAX), UINT64_MAX && errno == 0); CHECK_GET_UINT64(N_U64(UINT64_MAX), UINT64_MAX && errno == 0);
CHECK_GET_UINT64(N_U64(-1), UINT64_MAX && errno == 0); CHECK_GET_UINT64(N_U64(-1), UINT64_MAX && errno == 0);
CHECK_GET_UINT64(N_STR(U64_OUT_S), UINT64_MAX && errno == ERANGE); CHECK_GET_UINT64(N_STR(U64_OUT_S), UINT64_MAX && errno == ERANGE);
CHECK_GET_UINT64(N_DBL(INFINITY), UINT64_MAX && errno == ERANGE);
CHECK_GET_UINT64(N_DBL(-INFINITY), 0 && errno == ERANGE);
CHECK_GET_UINT64(N_DBL(NAN), 0 && errno == EINVAL);
printf("UINT64 GET PASSED\n"); printf("UINT64 GET PASSED\n");
printf("PASSED\n"); printf("PASSED\n");

View File

@@ -113,6 +113,9 @@ static void test_basic_parse(void)
single_basic_parse("\"\\udd27\"", 0); single_basic_parse("\"\\udd27\"", 0);
// Test with a "short" high surrogate // Test with a "short" high surrogate
single_basic_parse("[9,'\\uDAD", 0); single_basic_parse("[9,'\\uDAD", 0);
single_basic_parse("\"[9,'\\uDAD\"", 0);
// Test with a supplemental character that looks like a high surrogate
single_basic_parse("\"\\uD836\\uDE87\"", 0);
single_basic_parse("null", 0); single_basic_parse("null", 0);
single_basic_parse("NaN", 0); single_basic_parse("NaN", 0);
single_basic_parse("-NaN", 0); /* non-sensical, returns null */ single_basic_parse("-NaN", 0); /* non-sensical, returns null */
@@ -297,6 +300,7 @@ struct incremental_step
{"d", -1, -1, json_tokener_continue, 0, 0}, {"d", -1, -1, json_tokener_continue, 0, 0},
{"1", -1, -1, json_tokener_continue, 0, 0}, {"1", -1, -1, json_tokener_continue, 0, 0},
{"e\"", -1, -1, json_tokener_success, 1, 0}, {"e\"", -1, -1, json_tokener_success, 1, 0},
/* parse two char at every time */ /* parse two char at every time */
{"\"\\u", -1, -1, json_tokener_continue, 0, 0}, {"\"\\u", -1, -1, json_tokener_continue, 0, 0},
{"d8", -1, -1, json_tokener_continue, 0, 0}, {"d8", -1, -1, json_tokener_continue, 0, 0},
@@ -322,10 +326,20 @@ struct incremental_step
{"\"fff \\ud83d\\ude", -1, -1, json_tokener_continue, 0, 0}, {"\"fff \\ud83d\\ude", -1, -1, json_tokener_continue, 0, 0},
{"00 bar\"", -1, -1, json_tokener_success, 1, 0}, {"00 bar\"", -1, -1, json_tokener_success, 1, 0},
/* Check a utf-8 char (a+umlaut) that has bytes that look negative when
char are signed (see also control char check below) */
{"\"\xc3\xa4\"", -1, -1, json_tokener_success, 1, 0},
{"\"\xc3\xa4\"", -1, -1, json_tokener_success, 1, JSON_TOKENER_STRICT},
/* Check that json_tokener_reset actually resets */ /* Check that json_tokener_reset actually resets */
{"{ \"foo", -1, -1, json_tokener_continue, 1, 0}, {"{ \"foo", -1, -1, json_tokener_continue, 1, 0},
{": \"bar\"}", -1, 0, json_tokener_error_parse_unexpected, 1, 0}, {": \"bar\"}", -1, 0, json_tokener_error_parse_unexpected, 1, 0},
/* Check a supplemental code point that looks like a high surrogate */
{"\"\\uD836", -1, -1, json_tokener_continue, 0, 0},
{"\\uDE87", -1, -1, json_tokener_continue, 0, 0},
{"\"", -1, -1, json_tokener_success, 1, 0},
/* Check incremental parsing with trailing characters */ /* Check incremental parsing with trailing characters */
{"{ \"foo", -1, -1, json_tokener_continue, 0, 0}, {"{ \"foo", -1, -1, json_tokener_continue, 0, 0},
{"\": {\"bar", -1, -1, json_tokener_continue, 0, 0}, {"\": {\"bar", -1, -1, json_tokener_continue, 0, 0},
@@ -394,8 +408,8 @@ struct incremental_step
{"Infinity", 9, 8, json_tokener_success, 1, 0}, {"Infinity", 9, 8, json_tokener_success, 1, 0},
{"infinity", 9, 8, json_tokener_success, 1, 0}, {"infinity", 9, 8, json_tokener_success, 1, 0},
{"-infinity", 10, 9, json_tokener_success, 1, 0},
{"infinity", 9, 0, json_tokener_error_parse_unexpected, 1, JSON_TOKENER_STRICT}, {"infinity", 9, 0, json_tokener_error_parse_unexpected, 1, JSON_TOKENER_STRICT},
{"-infinity", 10, 9, json_tokener_success, 1, 0},
{"-infinity", 10, 1, json_tokener_error_parse_unexpected, 1, JSON_TOKENER_STRICT}, {"-infinity", 10, 1, json_tokener_error_parse_unexpected, 1, JSON_TOKENER_STRICT},
{"inf", 3, 3, json_tokener_continue, 0, 0}, {"inf", 3, 3, json_tokener_continue, 0, 0},
@@ -462,12 +476,15 @@ struct incremental_step
{"[18446744073709551616]", 23, 21, json_tokener_error_parse_number, 1, JSON_TOKENER_STRICT}, {"[18446744073709551616]", 23, 21, json_tokener_error_parse_number, 1, JSON_TOKENER_STRICT},
/* XXX this seems like a bug, should fail with _error_parse_number instead */ /* XXX this seems like a bug, should fail with _error_parse_number instead */
{"18446744073709551616", 21, 20, json_tokener_success, 1, 0},
{"18446744073709551616", 21, 20, json_tokener_error_parse_eof, 1, JSON_TOKENER_STRICT}, {"18446744073709551616", 21, 20, json_tokener_error_parse_eof, 1, JSON_TOKENER_STRICT},
/* Exceeding integer limits as double parse OK */ /* Exceeding integer limits as double parse OK */
{"[9223372036854775808.0]", 24, 23, json_tokener_success, 1, 0}, {"[9223372036854775808.0]", 24, 23, json_tokener_success, 1, 0},
{"[-9223372036854775809.0]", 25, 24, json_tokener_success, 1, 0},
{"[-9223372036854775809.0]", 25, 24, json_tokener_success, 1, JSON_TOKENER_STRICT}, {"[-9223372036854775809.0]", 25, 24, json_tokener_success, 1, JSON_TOKENER_STRICT},
{"[18446744073709551615.0]", 25, 24, json_tokener_success, 1, 0}, {"[18446744073709551615.0]", 25, 24, json_tokener_success, 1, 0},
{"[18446744073709551616.0]", 25, 24, json_tokener_success, 1, 0},
{"[18446744073709551616.0]", 25, 24, json_tokener_success, 1, JSON_TOKENER_STRICT}, {"[18446744073709551616.0]", 25, 24, json_tokener_success, 1, JSON_TOKENER_STRICT},
/* offset=1 because "n" is the start of "null". hmm... */ /* offset=1 because "n" is the start of "null". hmm... */
@@ -524,6 +541,7 @@ struct incremental_step
{"\"\\a\"", -1, 2, json_tokener_error_parse_string, 1, 0}, {"\"\\a\"", -1, 2, json_tokener_error_parse_string, 1, 0},
/* Check '\'' in strict model */ /* Check '\'' in strict model */
{"\'foo\'", -1, 5, json_tokener_success, 1, 0},
{"\'foo\'", -1, 0, json_tokener_error_parse_unexpected, 1, JSON_TOKENER_STRICT}, {"\'foo\'", -1, 0, json_tokener_error_parse_unexpected, 1, JSON_TOKENER_STRICT},
/* Parse array/object */ /* Parse array/object */
@@ -535,7 +553,7 @@ struct incremental_step
{"{\"a\":}", -1, 5, json_tokener_error_parse_unexpected, 1, 0}, {"{\"a\":}", -1, 5, json_tokener_error_parse_unexpected, 1, 0},
{"{\"a\":1,\"a\":2}", -1, -1, json_tokener_success, 1, 0}, {"{\"a\":1,\"a\":2}", -1, -1, json_tokener_success, 1, 0},
{"\"a\":1}", -1, 3, json_tokener_success, 1, 0}, {"\"a\":1}", -1, 3, json_tokener_success, 1, 0},
{"{\"a\":1", -1, -1, json_tokener_continue, 1, 0}, {"{\"a\":1", -1, -1, json_tokener_continue, 1, 0}, //}
{"[,]", -1, 1, json_tokener_error_parse_unexpected, 1, 0}, {"[,]", -1, 1, json_tokener_error_parse_unexpected, 1, 0},
{"[,1]", -1, 1, json_tokener_error_parse_unexpected, 1, 0}, {"[,1]", -1, 1, json_tokener_error_parse_unexpected, 1, 0},
@@ -544,9 +562,10 @@ struct incremental_step
* in what we accept (up to a point). * in what we accept (up to a point).
*/ */
{"[1,2,3,]", -1, -1, json_tokener_success, 0, 0}, {"[1,2,3,]", -1, -1, json_tokener_success, 0, 0},
{"[1,2,,3,]", -1, 5, json_tokener_error_parse_unexpected, 0, 0},
{"[1,2,3,]", -1, 7, json_tokener_error_parse_unexpected, 1, JSON_TOKENER_STRICT}, {"[1,2,3,]", -1, 7, json_tokener_error_parse_unexpected, 1, JSON_TOKENER_STRICT},
{"[1,2,,3,]", -1, 5, json_tokener_error_parse_unexpected, 0, 0},
{"[1,2,,3,]", -1, 5, json_tokener_error_parse_unexpected, 0, JSON_TOKENER_STRICT},
{"{\"a\":1,}", -1, 7, json_tokener_error_parse_unexpected, 1, JSON_TOKENER_STRICT}, {"{\"a\":1,}", -1, 7, json_tokener_error_parse_unexpected, 1, JSON_TOKENER_STRICT},
// utf-8 test // utf-8 test
@@ -595,6 +614,80 @@ struct incremental_step
{"\x7b\x22\x31\x81\x22\x3a\x31\x7d", -1, 3, json_tokener_error_parse_utf8_string, 1, {"\x7b\x22\x31\x81\x22\x3a\x31\x7d", -1, 3, json_tokener_error_parse_utf8_string, 1,
JSON_TOKENER_VALIDATE_UTF8}, JSON_TOKENER_VALIDATE_UTF8},
// Note, current asciiz APIs can't parse \x00, skip it
{ "\"0\x01\x02\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" \
"\x10\x11\x12\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\"",
-1, -1, json_tokener_success, 1, 0 },
{ "{\"0\x01\x02\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" \
"\x10\x11\x12\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\":1}",
-1, -1, json_tokener_success, 1, 0 },
// Test control chars again, this time in strict mode, which should fail
{ "\"\x01\"", -1, 1, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "\"\x02\"", -1, 1, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "\"\x03\"", -1, 1, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "\"\x04\"", -1, 1, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "\"\x05\"", -1, 1, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "\"\x06\"", -1, 1, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "\"\x07\"", -1, 1, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "\"\x08\"", -1, 1, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "\"\x09\"", -1, 1, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "\"\x0a\"", -1, 1, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "\"\x0b\"", -1, 1, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "\"\x0c\"", -1, 1, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "\"\x0d\"", -1, 1, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "\"\x0e\"", -1, 1, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "\"\x0f\"", -1, 1, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "\"\x10\"", -1, 1, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "\"\x11\"", -1, 1, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "\"\x12\"", -1, 1, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "\"\x13\"", -1, 1, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "\"\x14\"", -1, 1, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "\"\x15\"", -1, 1, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "\"\x16\"", -1, 1, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "\"\x17\"", -1, 1, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "\"\x18\"", -1, 1, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "\"\x19\"", -1, 1, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "\"\x1a\"", -1, 1, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "\"\x1b\"", -1, 1, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "\"\x1c\"", -1, 1, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "\"\x1d\"", -1, 1, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "\"\x1e\"", -1, 1, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "\"\x1f\"", -1, 1, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "{\"\x01\":1}", -1, 2, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "{\"\x02\":1}", -1, 2, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "{\"\x03\":1}", -1, 2, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "{\"\x04\":1}", -1, 2, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "{\"\x05\":1}", -1, 2, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "{\"\x06\":1}", -1, 2, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "{\"\x07\":1}", -1, 2, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "{\"\x08\":1}", -1, 2, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "{\"\x09\":1}", -1, 2, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "{\"\x0a\":1}", -1, 2, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "{\"\x0b\":1}", -1, 2, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "{\"\x0c\":1}", -1, 2, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "{\"\x0d\":1}", -1, 2, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "{\"\x0e\":1}", -1, 2, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "{\"\x0f\":1}", -1, 2, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "{\"\x10\":1}", -1, 2, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "{\"\x11\":1}", -1, 2, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "{\"\x12\":1}", -1, 2, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "{\"\x13\":1}", -1, 2, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "{\"\x14\":1}", -1, 2, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "{\"\x15\":1}", -1, 2, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "{\"\x16\":1}", -1, 2, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "{\"\x17\":1}", -1, 2, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "{\"\x18\":1}", -1, 2, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "{\"\x19\":1}", -1, 2, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "{\"\x1a\":1}", -1, 2, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "{\"\x1b\":1}", -1, 2, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "{\"\x1c\":1}", -1, 2, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "{\"\x1d\":1}", -1, 2, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "{\"\x1e\":1}", -1, 2, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{ "{\"\x1f\":1}", -1, 2, json_tokener_error_parse_string, 1, JSON_TOKENER_STRICT },
{NULL, -1, -1, json_tokener_success, 0, 0}, {NULL, -1, -1, json_tokener_success, 0, 0},
}; };
@@ -618,7 +711,7 @@ static void test_incremental_parse(void)
printf("json_tokener_parse(%s) ... ", string_to_parse); printf("json_tokener_parse(%s) ... ", string_to_parse);
new_obj = json_tokener_parse(string_to_parse); new_obj = json_tokener_parse(string_to_parse);
if (new_obj == NULL) if (new_obj == NULL)
puts("got error as expected"); printf("%s", "got error as expected\n");
/* test incremental parsing in various forms */ /* test incremental parsing in various forms */
tok = json_tokener_new(); tok = json_tokener_new();

View File

@@ -13,6 +13,8 @@ new_obj.to_string("\ud840\u4e16")="<22>世"
new_obj.to_string("\ud840")="<22>" new_obj.to_string("\ud840")="<22>"
new_obj.to_string("\udd27")="<22>" new_obj.to_string("\udd27")="<22>"
new_obj.to_string([9,'\uDAD)=null new_obj.to_string([9,'\uDAD)=null
new_obj.to_string("[9,'\uDAD")=null
new_obj.to_string("\uD836\uDE87")="𝪇"
new_obj.to_string(null)=null new_obj.to_string(null)=null
new_obj.to_string(NaN)=NaN new_obj.to_string(NaN)=NaN
new_obj.to_string(-NaN)=null new_obj.to_string(-NaN)=null
@@ -134,8 +136,13 @@ json_tokener_parse_ex(tok, "fff \ud834\udd, 15) ... OK: got correct error: cont
json_tokener_parse_ex(tok, 1e bar" , 7) ... OK: got object of type [string]: "fff 𝄞 bar" json_tokener_parse_ex(tok, 1e bar" , 7) ... OK: got object of type [string]: "fff 𝄞 bar"
json_tokener_parse_ex(tok, "fff \ud83d\ude, 15) ... OK: got correct error: continue json_tokener_parse_ex(tok, "fff \ud83d\ude, 15) ... OK: got correct error: continue
json_tokener_parse_ex(tok, 00 bar" , 7) ... OK: got object of type [string]: "fff 😀 bar" json_tokener_parse_ex(tok, 00 bar" , 7) ... OK: got object of type [string]: "fff 😀 bar"
json_tokener_parse_ex(tok, "ä" , 4) ... OK: got object of type [string]: "ä"
json_tokener_parse_ex(tok, "ä" , 4) ... OK: got object of type [string]: "ä"
json_tokener_parse_ex(tok, { "foo , 6) ... OK: got correct error: continue json_tokener_parse_ex(tok, { "foo , 6) ... OK: got correct error: continue
json_tokener_parse_ex(tok, : "bar"} , 8) ... OK: got correct error: unexpected character json_tokener_parse_ex(tok, : "bar"} , 8) ... OK: got correct error: unexpected character
json_tokener_parse_ex(tok, "\uD836 , 7) ... OK: got correct error: continue
json_tokener_parse_ex(tok, \uDE87 , 6) ... OK: got correct error: continue
json_tokener_parse_ex(tok, " , 1) ... OK: got object of type [string]: "𝪇"
json_tokener_parse_ex(tok, { "foo , 6) ... OK: got correct error: continue json_tokener_parse_ex(tok, { "foo , 6) ... OK: got correct error: continue
json_tokener_parse_ex(tok, ": {"bar , 8) ... OK: got correct error: continue json_tokener_parse_ex(tok, ": {"bar , 8) ... OK: got correct error: continue
json_tokener_parse_ex(tok, ":13}}XXXX , 10) ... OK: got object of type [object]: { "foo": { "bar": 13 } } json_tokener_parse_ex(tok, ":13}}XXXX , 10) ... OK: got object of type [object]: { "foo": { "bar": 13 } }
@@ -177,8 +184,8 @@ json_tokener_parse_ex(tok, null , 4) ... OK: got correct error: continu
json_tokener_parse_ex(tok, null , 5) ... OK: got object of type [null]: null json_tokener_parse_ex(tok, null , 5) ... OK: got object of type [null]: null
json_tokener_parse_ex(tok, Infinity , 9) ... OK: got object of type [double]: Infinity json_tokener_parse_ex(tok, Infinity , 9) ... OK: got object of type [double]: Infinity
json_tokener_parse_ex(tok, infinity , 9) ... OK: got object of type [double]: Infinity json_tokener_parse_ex(tok, infinity , 9) ... OK: got object of type [double]: Infinity
json_tokener_parse_ex(tok, -infinity , 10) ... OK: got object of type [double]: -Infinity
json_tokener_parse_ex(tok, infinity , 9) ... OK: got correct error: unexpected character json_tokener_parse_ex(tok, infinity , 9) ... OK: got correct error: unexpected character
json_tokener_parse_ex(tok, -infinity , 10) ... OK: got object of type [double]: -Infinity
json_tokener_parse_ex(tok, -infinity , 10) ... OK: got correct error: unexpected character json_tokener_parse_ex(tok, -infinity , 10) ... OK: got correct error: unexpected character
json_tokener_parse_ex(tok, inf , 3) ... OK: got correct error: continue json_tokener_parse_ex(tok, inf , 3) ... OK: got correct error: continue
json_tokener_parse_ex(tok, inity , 6) ... OK: got object of type [double]: Infinity json_tokener_parse_ex(tok, inity , 6) ... OK: got object of type [double]: Infinity
@@ -218,11 +225,14 @@ json_tokener_parse_ex(tok, [-9223372036854775809], 23) ... OK: got correct erro
json_tokener_parse_ex(tok, [18446744073709551615], 23) ... OK: got object of type [array]: [ 18446744073709551615 ] json_tokener_parse_ex(tok, [18446744073709551615], 23) ... OK: got object of type [array]: [ 18446744073709551615 ]
json_tokener_parse_ex(tok, [18446744073709551616], 23) ... OK: got object of type [array]: [ 18446744073709551615 ] json_tokener_parse_ex(tok, [18446744073709551616], 23) ... OK: got object of type [array]: [ 18446744073709551615 ]
json_tokener_parse_ex(tok, [18446744073709551616], 23) ... OK: got correct error: number expected json_tokener_parse_ex(tok, [18446744073709551616], 23) ... OK: got correct error: number expected
json_tokener_parse_ex(tok, 18446744073709551616, 21) ... OK: got object of type [int]: 18446744073709551615
json_tokener_parse_ex(tok, 18446744073709551616, 21) ... OK: got correct error: unexpected end of data json_tokener_parse_ex(tok, 18446744073709551616, 21) ... OK: got correct error: unexpected end of data
json_tokener_parse_ex(tok, [9223372036854775808.0], 24) ... OK: got object of type [array]: [ 9223372036854775808.0 ] json_tokener_parse_ex(tok, [9223372036854775808.0], 24) ... OK: got object of type [array]: [ 9223372036854775808.0 ]
json_tokener_parse_ex(tok, [-9223372036854775809.0], 25) ... OK: got object of type [array]: [ -9223372036854775809.0 ] json_tokener_parse_ex(tok, [-9223372036854775809.0], 25) ... OK: got object of type [array]: [ -9223372036854775809.0 ]
json_tokener_parse_ex(tok, [-9223372036854775809.0], 25) ... OK: got object of type [array]: [ -9223372036854775809.0 ]
json_tokener_parse_ex(tok, [18446744073709551615.0], 25) ... OK: got object of type [array]: [ 18446744073709551615.0 ] json_tokener_parse_ex(tok, [18446744073709551615.0], 25) ... OK: got object of type [array]: [ 18446744073709551615.0 ]
json_tokener_parse_ex(tok, [18446744073709551616.0], 25) ... OK: got object of type [array]: [ 18446744073709551616.0 ] json_tokener_parse_ex(tok, [18446744073709551616.0], 25) ... OK: got object of type [array]: [ 18446744073709551616.0 ]
json_tokener_parse_ex(tok, [18446744073709551616.0], 25) ... OK: got object of type [array]: [ 18446744073709551616.0 ]
json_tokener_parse_ex(tok, noodle , 7) ... OK: got correct error: null expected json_tokener_parse_ex(tok, noodle , 7) ... OK: got correct error: null expected
json_tokener_parse_ex(tok, naodle , 7) ... OK: got correct error: null expected json_tokener_parse_ex(tok, naodle , 7) ... OK: got correct error: null expected
json_tokener_parse_ex(tok, track , 6) ... OK: got correct error: boolean expected json_tokener_parse_ex(tok, track , 6) ... OK: got correct error: boolean expected
@@ -250,6 +260,7 @@ json_tokener_parse_ex(tok, "\t" , 4) ... OK: got object of type [string
json_tokener_parse_ex(tok, "\/" , 4) ... OK: got object of type [string]: "\/" json_tokener_parse_ex(tok, "\/" , 4) ... OK: got object of type [string]: "\/"
json_tokener_parse_ex(tok, "/" , 3) ... OK: got object of type [string]: "\/" json_tokener_parse_ex(tok, "/" , 3) ... OK: got object of type [string]: "\/"
json_tokener_parse_ex(tok, "\a" , 4) ... OK: got correct error: invalid string sequence json_tokener_parse_ex(tok, "\a" , 4) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, 'foo' , 5) ... OK: got object of type [string]: "foo"
json_tokener_parse_ex(tok, 'foo' , 5) ... OK: got correct error: unexpected character json_tokener_parse_ex(tok, 'foo' , 5) ... OK: got correct error: unexpected character
json_tokener_parse_ex(tok, [1,2,3] , 7) ... OK: got object of type [array]: [ 1, 2, 3 ] json_tokener_parse_ex(tok, [1,2,3] , 7) ... OK: got object of type [array]: [ 1, 2, 3 ]
json_tokener_parse_ex(tok, [1,2,3} , 7) ... OK: got correct error: array value separator ',' expected json_tokener_parse_ex(tok, [1,2,3} , 7) ... OK: got correct error: array value separator ',' expected
@@ -263,8 +274,9 @@ json_tokener_parse_ex(tok, {"a":1 , 6) ... OK: got correct error: continu
json_tokener_parse_ex(tok, [,] , 3) ... OK: got correct error: unexpected character json_tokener_parse_ex(tok, [,] , 3) ... OK: got correct error: unexpected character
json_tokener_parse_ex(tok, [,1] , 4) ... OK: got correct error: unexpected character json_tokener_parse_ex(tok, [,1] , 4) ... OK: got correct error: unexpected character
json_tokener_parse_ex(tok, [1,2,3,] , 8) ... OK: got object of type [array]: [ 1, 2, 3 ] json_tokener_parse_ex(tok, [1,2,3,] , 8) ... OK: got object of type [array]: [ 1, 2, 3 ]
json_tokener_parse_ex(tok, [1,2,,3,] , 9) ... OK: got correct error: unexpected character
json_tokener_parse_ex(tok, [1,2,3,] , 8) ... OK: got correct error: unexpected character json_tokener_parse_ex(tok, [1,2,3,] , 8) ... OK: got correct error: unexpected character
json_tokener_parse_ex(tok, [1,2,,3,] , 9) ... OK: got correct error: unexpected character
json_tokener_parse_ex(tok, [1,2,,3,] , 9) ... OK: got correct error: unexpected character
json_tokener_parse_ex(tok, {"a":1,} , 8) ... OK: got correct error: unexpected character json_tokener_parse_ex(tok, {"a":1,} , 8) ... OK: got correct error: unexpected character
json_tokener_parse_ex(tok, "123asc$%&" , 11) ... OK: got object of type [string]: "123asc$%&" json_tokener_parse_ex(tok, "123asc$%&" , 11) ... OK: got object of type [string]: "123asc$%&"
json_tokener_parse_ex(tok, "123asc$%&" , 11) ... OK: got object of type [string]: "123asc$%&" json_tokener_parse_ex(tok, "123asc$%&" , 11) ... OK: got object of type [string]: "123asc$%&"
@@ -288,5 +300,73 @@ json_tokener_parse_ex(tok, "\ud855
json_tokener_parse_ex(tok, "\ud0031<33>" , 10) ... OK: got correct error: invalid utf-8 string json_tokener_parse_ex(tok, "\ud0031<33>" , 10) ... OK: got correct error: invalid utf-8 string
json_tokener_parse_ex(tok, 11<31>11 , 5) ... OK: got correct error: invalid utf-8 string json_tokener_parse_ex(tok, 11<31>11 , 5) ... OK: got correct error: invalid utf-8 string
json_tokener_parse_ex(tok, {"1<>":1} , 8) ... OK: got correct error: invalid utf-8 string json_tokener_parse_ex(tok, {"1<>":1} , 8) ... OK: got correct error: invalid utf-8 string
End Incremental Tests OK=198 ERROR=0 json_tokener_parse_ex(tok, "0
", 36) ... OK: got object of type [string]: "0\u0001\u0002\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f\u0010\u0011\u0012\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f"
json_tokener_parse_ex(tok, {"0
":1}, 40) ... OK: got object of type [object]: { "0\u0001\u0002\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f\u0010\u0011\u0012\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f": 1 }
json_tokener_parse_ex(tok, "" , 3) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, "" , 3) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, "" , 3) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, "" , 3) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, "" , 3) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, "" , 3) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, "" , 3) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, "" , 3) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, " " , 3) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, "
" , 3) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, " " , 3) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, " " , 3) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, "
" , 3) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, "" , 3) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, "" , 3) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, "" , 3) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, "" , 3) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, "" , 3) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, "" , 3) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, "" , 3) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, "" , 3) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, "" , 3) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, "" , 3) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, "" , 3) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, "" , 3) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, "" , 3) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, "" , 3) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, "" , 3) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, "" , 3) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, "" , 3) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, "" , 3) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, {"":1} , 7) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, {"":1} , 7) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, {"":1} , 7) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, {"":1} , 7) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, {"":1} , 7) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, {"":1} , 7) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, {"":1} , 7) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, {"":1} , 7) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, {" ":1} , 7) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, {"
":1} , 7) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, {" ":1} , 7) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, {" ":1} , 7) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, {"
":1} , 7) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, {"":1} , 7) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, {"":1} , 7) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, {"":1} , 7) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, {"":1} , 7) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, {"":1} , 7) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, {"":1} , 7) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, {"":1} , 7) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, {"":1} , 7) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, {"":1} , 7) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, {"":1} , 7) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, {"":1} , 7) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, {"":1} , 7) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, {"":1} , 7) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, {"":1} , 7) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, {"":1} , 7) ... OK: got correct error: invalid string sequence
json_tokener_parse_ex(tok, {"":1} , 7) ... OK: got correct error: invalid string sequence json_tokener_parse_ex(tok, {"":1} , 7) ... OK: got correct error: invalid string sequence

View File

@@ -0,0 +1,249 @@
#ifdef NDEBUG
#undef NDEBUG
#endif
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include "json.h"
static const char *input_json_str = "{ "
"'foo': ['bar', 'baz'], "
"'': 0, "
"'a/b': 1, "
"'c%d': 2, "
"'e^f': 3, "
"'g|h': 4, "
"'i\\\\j': 5, "
"'k\\\"l': 6, "
"' ': 7, "
"'m~n': 8 "
"}";
static void test_example_set_with_limit_index(void)
{
struct json_object *jo2, *jo1 = json_tokener_parse(input_json_str);
size_t limit_index = 10;
// testing if json_pointer_set_with_limit_index() works as json_pointer_set()
assert(jo1 != NULL);
printf("PASSED - SET_WITH_LIMIT - LOADED TEST JSON\n");
printf("%s\n", json_object_get_string(jo1));
assert(0 == json_pointer_set_with_limit_index(&jo1, "/foo/1", json_object_new_string("cod"), limit_index));
assert(0 == strcmp("cod", json_object_get_string(json_object_array_get_idx(
json_object_object_get(jo1, "foo"), 1))));
printf("PASSED - SET_WITH_LIMIT - 'cod' in /foo/1\n");
assert(0 != json_pointer_set_with_limit_index(&jo1, "/fud/gaw", (jo2 = json_tokener_parse("[1,2,3]")), limit_index));
assert(errno == ENOENT);
printf("PASSED - SET_WITH_LIMIT - non-existing /fud/gaw\n");
assert(0 == json_pointer_set_with_limit_index(&jo1, "/fud", json_object_new_object(), limit_index));
printf("PASSED - SET_WITH_LIMIT - /fud == {}\n");
assert(0 == json_pointer_set_with_limit_index(&jo1, "/fud/gaw", jo2, limit_index)); /* re-using jo2 from above */
printf("PASSED - SET_WITH_LIMIT - /fug/gaw == [1,2,3]\n");
assert(0 == json_pointer_set_with_limit_index(&jo1, "/fud/gaw/0", json_object_new_int(0), limit_index));
assert(0 == json_pointer_setf(&jo1, json_object_new_int(0), "%s%s/%d", "/fud", "/gaw", 0));
printf("PASSED - SET_WITH_LIMIT - /fug/gaw == [0,2,3]\n");
assert(0 == json_pointer_set_with_limit_index(&jo1, "/fud/gaw/-", json_object_new_int(4), limit_index));
printf("PASSED - SET_WITH_LIMIT - /fug/gaw == [0,2,3,4]\n");
assert(0 == json_pointer_set_with_limit_index(&jo1, "/", json_object_new_int(9), limit_index));
printf("PASSED - SET_WITH_LIMIT - / == 9\n");
jo2 = json_tokener_parse(
"{ 'foo': [ 'bar', 'cod' ], '': 9, 'a/b': 1, 'c%d': 2, 'e^f': 3, 'g|h': 4, 'i\\\\j': "
"5, 'k\\\"l': 6, ' ': 7, 'm~n': 8, 'fud': { 'gaw': [ 0, 2, 3, 4 ] } }");
assert(json_object_equal(jo2, jo1));
printf("PASSED - SET_WITH_LIMIT - Final JSON is: %s\n", json_object_get_string(jo1));
json_object_put(jo2);
assert(0 == json_pointer_set_with_limit_index(&jo1, "", json_object_new_int(10), limit_index));
assert(10 == json_object_get_int(jo1));
printf("%s\n", json_object_get_string(jo1));
json_object_put(jo1);
jo1 = json_tokener_parse("[0, 1, 2, 3]");
jo2 = json_tokener_parse("[0, 1, 2, 3, null, null, null, 7]");
assert(0 == json_pointer_set_with_limit_index(&jo1, "/7", json_object_new_int(7), limit_index));
assert(1 == json_object_equal(jo1, jo2));
json_object_put(jo1);
jo1 = json_tokener_parse("[0, 1, 2, 3]");
assert(0 == json_pointer_setf(&jo1, json_object_new_int(7), "/%u", 7));
assert(1 == json_object_equal(jo1, jo2));
json_object_put(jo1);
json_object_put(jo2);
// testing with limit_index
jo1 = json_tokener_parse("{'foo': ['bar', 'baz']}");
jo2 = json_tokener_parse("{'foo': ['bar', 'cod']}");
assert(0 == json_pointer_set_with_limit_index(&jo1, "/foo/1", json_object_new_string("cod"), limit_index));
assert(json_object_equal(jo1, jo2));
printf("PASSED - SET_LIMIT - Set value within limit (/foo/1 with limit 10)\n");
assert(0 == json_pointer_set_with_limit_index(&jo1, "/bar", json_object_new_string("new_field"), limit_index));
printf("PASSED - SET_LIMIT - Set value on an object (limit is ignored)\n");
assert(0 == json_pointer_set_with_limit_index(&jo1, "/foo/20", json_object_new_string("big_index"), (size_t)-1));
printf("PASSED - SET_LIMIT - Set value with limit_index = -1 (no limit)\n");
json_object_put(jo1);
json_object_put(jo2);
}
static void test_wrong_inputs_set_with_limit_index(void)
{
struct json_object *jo2, *jo1 = json_tokener_parse(input_json_str);
size_t limit_index = 10;
// testing if json_pointer_set_with_limit_index() works as json_pointer_set()
assert(jo1 != NULL);
printf("PASSED - SET_WITH_LIMIT - LOADED TEST JSON\n");
printf("%s\n", json_object_get_string(jo1));
assert(0 != json_pointer_set_with_limit_index(NULL, NULL, NULL, limit_index));
assert(0 != json_pointer_set_with_limit_index(&jo1, NULL, NULL, limit_index));
printf("PASSED - SET_WITH_LIMIT - failed with NULL params for input json & path\n");
assert(0 != json_pointer_set_with_limit_index(&jo1, "foo/bar", (jo2 = json_object_new_string("cod")), limit_index));
printf("PASSED - SET_WITH_LIMIT - failed 'cod' with path 'foo/bar'\n");
json_object_put(jo2);
// assert(0 !=
// json_pointer_setf(&jo1, (jo2 = json_object_new_string("cod")), "%s", "foo/bar"));
// printf("PASSED - SET_WITH_LIMIT - failed 'cod' with path 'foo/bar'\n");
// json_object_put(jo2);
assert(0 != json_pointer_set_with_limit_index(&jo1, "0", (jo2 = json_object_new_string("cod")), limit_index));
printf("PASSED - SET_WITH_LIMIT - failed with invalid array index'\n");
json_object_put(jo2);
jo2 = json_object_new_string("whatever");
assert(0 != json_pointer_set_with_limit_index(&jo1, "/fud/gaw", jo2, limit_index));
assert(0 == json_pointer_set_with_limit_index(&jo1, "/fud", json_object_new_object(), limit_index));
assert(0 == json_pointer_set_with_limit_index(&jo1, "/fud/gaw", jo2, limit_index)); /* re-using jo2 from above */
// ownership of jo2 transferred into jo1
jo2 = json_object_new_int(0);
assert(0 != json_pointer_set_with_limit_index(&jo1, "/fud/gaw/0", jo2, limit_index));
json_object_put(jo2);
jo2 = json_object_new_int(0);
assert(0 != json_pointer_set_with_limit_index(&jo1, "/fud/gaw/", jo2, limit_index));
json_object_put(jo2);
printf("PASSED - SET_WITH_LIMIT - failed to set index to non-array\n");
// assert(0 == json_pointer_setf(&jo1, json_object_new_string("cod"), "%s", "\0"));
json_object_put(jo1);
// testing with limit_index
jo1 = json_tokener_parse("{'foo': ['bar', 'baz']}");
errno = 0;
jo2 = json_object_new_string("out_of_bounds");
assert(0 != json_pointer_set_with_limit_index(&jo1, "/foo/20", jo2, limit_index));
assert(errno == EINVAL);
printf("PASSED - SET_LIMIT - Failed to set index 20 with limit 10\n");
// The value object was not consumed, so we must put it.
json_object_put(jo2);
// corner case: setting an index that equals the limit (should be ok, as it's idx > max_idx)
errno = 0;
assert(0 == json_pointer_set_with_limit_index(&jo1, "/foo/10", json_object_new_string("at_the_limit"), limit_index));
printf("PASSED - SET_LIMIT - Succeeded to set index 10 with limit 10\n");
json_object_put(jo1);
}
// callback for testing json_pointer_set_with_cb()
static int test_cb_print_msg(json_object *parent, const char *key, size_t idx,
json_object *value, void *priv)
{
printf("PASSED - SET_WITH_CB - This callback is called\n");
json_object_put(value);
return 0;
}
// callback for testing json_pointer_set_with_cb() with rejection logic
static int test_cb_reject_logic(json_object *parent, const char *key, size_t idx,
json_object *value, void *priv)
{
// Reject any operation if the key is "reject"
if (key && strcmp(key, "reject") == 0)
{
printf("PASSED - SET_WITH_CB - Callback correctly identified key 'reject' to reject\n");
// Note: caller of json_pointer_set must free value
return -1;
}
json_object_put(value);
return 0;
}
static void test_set_with_cb(void)
{
struct json_object *jo2, *jo1 = json_tokener_parse(input_json_str);
size_t limit_index = 5;
assert(jo1 != NULL);
printf("PASSED - SET_WITH_CB - LOADED TEST JSON\n");
printf("%s\n", json_object_get_string(jo1));
assert(0 == json_pointer_set_with_cb(&jo1, "/foo/1", json_object_new_string("cod"), test_cb_print_msg, 1, NULL));
printf("PASSED - SET_WITH_CB - callback test_cb_print_msg for /foo/1\n");
assert(0 == json_pointer_set_with_cb(&jo1, "/foo/4", json_object_new_string("in"), json_object_array_put_with_idx_limit_cb, 0, &limit_index));
printf("PASSED - SET_WITH_CB - callback json_object_array_put_with_idx_limit_cb for /foo/4 with limit_index 5\n");
assert(0 == json_pointer_set_with_cb(&jo1, "/foo/5", json_object_new_string("border"), json_object_array_put_with_idx_limit_cb, 0, &limit_index));
printf("PASSED - SET_WITH_CB - failed with callback json_object_array_put_with_idx_limit_cb for /foo/5 with limit_index 5\n");
assert(0 != json_pointer_set_with_cb(&jo1, "/foo/10", (jo2 = json_object_new_string("out")), json_object_array_put_with_idx_limit_cb, 0, &limit_index));
json_object_put(jo2);
assert(errno == EINVAL);
printf("PASSED - SET_WITH_CB - failed with callback json_object_array_put_with_idx_limit_cb for /foo/10 with limit_index 5\n");
assert(0 != json_pointer_set_with_cb(&jo1, "/foo/2", (jo2 = json_object_new_string("null_priv")), json_object_array_put_with_idx_limit_cb, 0, NULL));
json_object_put(jo2);
assert(errno == EFAULT);
printf("PASSED - SET_WITH_CB - failed with callback json_object_array_put_with_idx_limit_cb with NULL priv\n");
json_object_put(jo1);
jo1 = json_tokener_parse("{'foo': 'bar'}");
assert(jo1 != NULL);
assert(0 == json_pointer_set_with_cb(&jo1, "/foo", json_object_new_string("cod"), test_cb_print_msg, 1, NULL));
printf("PASSED - SET_WITH_CB - cb_handles_obj=1: callback was triggered for object operation\n");
assert(0 == json_pointer_set_with_cb(&jo1, "/new_key", json_object_new_string("new_value"), test_cb_print_msg, 0, NULL));
printf("PASSED - SET_WITH_CB - cb_handles_obj=0: callback was NOT triggered for object operation, default logic was used\n");
json_object_put(jo1);
// testing rejection logic callback
jo1 = json_tokener_parse("{'data': {} }");
assert(jo1 != NULL);
assert(0 == json_pointer_set_with_cb(&jo1, "/data/accept", json_object_new_string("accepted_value"), test_cb_reject_logic, 1, NULL));
printf("PASSED - SET_WITH_CB - Rejection callback approved an allowed key\n");
assert(0 != json_pointer_set_with_cb(&jo1, "/data/reject", (jo2 = json_object_new_string("rejected_value")), test_cb_reject_logic, 1, NULL));
json_object_put(jo2);
printf("PASSED - SET_WITH_CB - Rejection callback rejected a forbidden key\n");
json_object_put(jo1);
}
int main(int argc, char **argv)
{
test_example_set_with_limit_index();
test_wrong_inputs_set_with_limit_index();
test_set_with_cb();
return 0;
}

View File

@@ -0,0 +1,36 @@
PASSED - SET_WITH_LIMIT - LOADED TEST JSON
{ "foo": [ "bar", "baz" ], "": 0, "a\/b": 1, "c%d": 2, "e^f": 3, "g|h": 4, "i\\j": 5, "k\"l": 6, " ": 7, "m~n": 8 }
PASSED - SET_WITH_LIMIT - 'cod' in /foo/1
PASSED - SET_WITH_LIMIT - non-existing /fud/gaw
PASSED - SET_WITH_LIMIT - /fud == {}
PASSED - SET_WITH_LIMIT - /fug/gaw == [1,2,3]
PASSED - SET_WITH_LIMIT - /fug/gaw == [0,2,3]
PASSED - SET_WITH_LIMIT - /fug/gaw == [0,2,3,4]
PASSED - SET_WITH_LIMIT - / == 9
PASSED - SET_WITH_LIMIT - Final JSON is: { "foo": [ "bar", "cod" ], "": 9, "a\/b": 1, "c%d": 2, "e^f": 3, "g|h": 4, "i\\j": 5, "k\"l": 6, " ": 7, "m~n": 8, "fud": { "gaw": [ 0, 2, 3, 4 ] } }
10
PASSED - SET_LIMIT - Set value within limit (/foo/1 with limit 10)
PASSED - SET_LIMIT - Set value on an object (limit is ignored)
PASSED - SET_LIMIT - Set value with limit_index = -1 (no limit)
PASSED - SET_WITH_LIMIT - LOADED TEST JSON
{ "foo": [ "bar", "baz" ], "": 0, "a\/b": 1, "c%d": 2, "e^f": 3, "g|h": 4, "i\\j": 5, "k\"l": 6, " ": 7, "m~n": 8 }
PASSED - SET_WITH_LIMIT - failed with NULL params for input json & path
PASSED - SET_WITH_LIMIT - failed 'cod' with path 'foo/bar'
PASSED - SET_WITH_LIMIT - failed with invalid array index'
PASSED - SET_WITH_LIMIT - failed to set index to non-array
PASSED - SET_LIMIT - Failed to set index 20 with limit 10
PASSED - SET_LIMIT - Succeeded to set index 10 with limit 10
PASSED - SET_WITH_CB - LOADED TEST JSON
{ "foo": [ "bar", "baz" ], "": 0, "a\/b": 1, "c%d": 2, "e^f": 3, "g|h": 4, "i\\j": 5, "k\"l": 6, " ": 7, "m~n": 8 }
PASSED - SET_WITH_CB - This callback is called
PASSED - SET_WITH_CB - callback test_cb_print_msg for /foo/1
PASSED - SET_WITH_CB - callback json_object_array_put_with_idx_limit_cb for /foo/4 with limit_index 5
PASSED - SET_WITH_CB - failed with callback json_object_array_put_with_idx_limit_cb for /foo/5 with limit_index 5
PASSED - SET_WITH_CB - failed with callback json_object_array_put_with_idx_limit_cb for /foo/10 with limit_index 5
PASSED - SET_WITH_CB - failed with callback json_object_array_put_with_idx_limit_cb with NULL priv
PASSED - SET_WITH_CB - This callback is called
PASSED - SET_WITH_CB - cb_handles_obj=1: callback was triggered for object operation
PASSED - SET_WITH_CB - cb_handles_obj=0: callback was NOT triggered for object operation, default logic was used
PASSED - SET_WITH_CB - Rejection callback approved an allowed key
PASSED - SET_WITH_CB - Callback correctly identified key 'reject' to reject
PASSED - SET_WITH_CB - Rejection callback rejected a forbidden key

View File

@@ -0,0 +1 @@
test_basic.test

View File

@@ -2,11 +2,11 @@
#undef NDEBUG #undef NDEBUG
#endif #endif
#include "strerror_override.h" #include "strerror_override.h"
#ifdef WIN32 #ifdef _WIN32
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <io.h> #include <io.h>
#include <windows.h> #include <windows.h>
#endif /* defined(WIN32) */ #endif /* defined(_WIN32) */
#include <fcntl.h> #include <fcntl.h>
#include <limits.h> #include <limits.h>
#include <stddef.h> #include <stddef.h>
@@ -27,7 +27,9 @@
static void test_read_valid_with_fd(const char *testdir); static void test_read_valid_with_fd(const char *testdir);
static void test_read_valid_nested_with_fd(const char *testdir); static void test_read_valid_nested_with_fd(const char *testdir);
static void test_read_nonexistant(void); static void test_read_nonexistant(void);
#ifndef _WIN32
static void test_read_closed(void); static void test_read_closed(void);
#endif
static void test_write_to_file(void); static void test_write_to_file(void);
static void stat_and_cat(const char *file); static void stat_and_cat(const char *file);
@@ -92,7 +94,12 @@ static void test_write_to_file(void)
static void stat_and_cat(const char *file) static void stat_and_cat(const char *file)
{ {
struct stat sb; struct stat sb;
int d = open(file, O_RDONLY); int flags = O_RDONLY;
#ifdef O_BINARY
// This fixes Windows which otherwise opens this in text mode and returns different counts
flags |= O_BINARY;
#endif
int d = open(file, flags);
if (d < 0) if (d < 0)
{ {
printf("FAIL: unable to open %s: %s\n", file, strerror(errno)); printf("FAIL: unable to open %s: %s\n", file, strerror(errno));
@@ -159,7 +166,10 @@ int main(int argc, char **argv)
test_read_valid_with_fd(testdir); test_read_valid_with_fd(testdir);
test_read_valid_nested_with_fd(testdir); test_read_valid_nested_with_fd(testdir);
test_read_nonexistant(); test_read_nonexistant();
#ifndef _WIN32
// Disabled because the Windows CRT causes a crash during this test that cannot be disabled/stopped/worked around
test_read_closed(); test_read_closed();
#endif
test_write_to_file(); test_write_to_file();
test_read_fd_equal(testdir); test_read_fd_equal(testdir);
return EXIT_SUCCESS; return EXIT_SUCCESS;
@@ -169,8 +179,12 @@ static void test_read_valid_with_fd(const char *testdir)
{ {
char filename[PATH_MAX]; char filename[PATH_MAX];
(void)snprintf(filename, sizeof(filename), "%s/valid.json", testdir); (void)snprintf(filename, sizeof(filename), "%s/valid.json", testdir);
int flags = O_RDONLY;
int d = open(filename, O_RDONLY); #ifdef O_BINARY
// This fixes Windows which otherwise opens this in text mode and returns different counts
flags |= O_BINARY;
#endif
int d = open(filename, flags);
if (d < 0) if (d < 0)
{ {
fprintf(stderr, "FAIL: unable to open %s: %s\n", filename, strerror(errno)); fprintf(stderr, "FAIL: unable to open %s: %s\n", filename, strerror(errno));
@@ -194,8 +208,12 @@ static void test_read_valid_nested_with_fd(const char *testdir)
{ {
char filename[PATH_MAX]; char filename[PATH_MAX];
(void)snprintf(filename, sizeof(filename), "%s/valid_nested.json", testdir); (void)snprintf(filename, sizeof(filename), "%s/valid_nested.json", testdir);
int flags = O_RDONLY;
int d = open(filename, O_RDONLY); #ifdef O_BINARY
// This fixes Windows which otherwise opens this in text mode and returns different counts
flags |= O_BINARY;
#endif
int d = open(filename, flags);
if (d < 0) if (d < 0)
{ {
fprintf(stderr, "FAIL: unable to open %s: %s\n", filename, strerror(errno)); fprintf(stderr, "FAIL: unable to open %s: %s\n", filename, strerror(errno));
@@ -250,7 +268,7 @@ static void test_read_nonexistant(void)
json_util_get_last_err()); json_util_get_last_err());
} }
} }
#ifndef _WIN32
static void test_read_closed(void) static void test_read_closed(void)
{ {
// Test reading from a closed fd // Test reading from a closed fd
@@ -258,6 +276,7 @@ static void test_read_closed(void)
if (d < 0) if (d < 0)
{ {
puts("FAIL: unable to open"); puts("FAIL: unable to open");
return;
} }
// Copy over to a fixed fd number so test output is consistent. // Copy over to a fixed fd number so test output is consistent.
int fixed_d = 10; int fixed_d = 10;
@@ -281,6 +300,7 @@ static void test_read_closed(void)
"expecting NULL, EBADF, got:NULL, %s\n", "expecting NULL, EBADF, got:NULL, %s\n",
json_util_get_last_err()); json_util_get_last_err());
} }
#endif
static void test_read_fd_equal(const char *testdir) static void test_read_fd_equal(const char *testdir)
{ {
@@ -288,8 +308,12 @@ static void test_read_fd_equal(const char *testdir)
(void)snprintf(filename, sizeof(filename), "%s/valid_nested.json", testdir); (void)snprintf(filename, sizeof(filename), "%s/valid_nested.json", testdir);
json_object *jso = json_object_from_file(filename); json_object *jso = json_object_from_file(filename);
int flags = O_RDONLY;
int d = open(filename, O_RDONLY); #ifdef O_BINARY
// This fixes Windows which otherwise opens this in text mode and returns different counts
flags |= O_BINARY;
#endif
int d = open(filename, flags);
if (d < 0) if (d < 0)
{ {
fprintf(stderr, "FAIL: unable to open %s: %s\n", filename, strerror(errno)); fprintf(stderr, "FAIL: unable to open %s: %s\n", filename, strerror(errno));

View File

@@ -8,9 +8,9 @@
#include "snprintf_compat.h" #include "snprintf_compat.h"
#ifndef WIN32 #ifndef _WIN32
#include <stdarg.h> #include <stdarg.h>
#endif /* !defined(WIN32) */ #endif /* !defined(_WIN32) */
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
@@ -18,10 +18,10 @@
/* CAW: compliant version of vasprintf */ /* CAW: compliant version of vasprintf */
static int vasprintf(char **buf, const char *fmt, va_list ap) static int vasprintf(char **buf, const char *fmt, va_list ap)
{ {
#ifndef WIN32 #ifndef _WIN32
static char _T_emptybuffer = '\0'; static char _T_emptybuffer = '\0';
va_list ap2; va_list ap2;
#endif /* !defined(WIN32) */ #endif /* !defined(_WIN32) */
int chars; int chars;
char *b; char *b;
@@ -30,16 +30,16 @@ static int vasprintf(char **buf, const char *fmt, va_list ap)
return -1; return -1;
} }
#ifdef WIN32 #ifdef _WIN32
chars = _vscprintf(fmt, ap); chars = _vscprintf(fmt, ap);
#else /* !defined(WIN32) */ #else /* !defined(_WIN32) */
/* CAW: RAWR! We have to hope to god here that vsnprintf doesn't overwrite /* CAW: RAWR! We have to hope to god here that vsnprintf doesn't overwrite
* our buffer like on some 64bit sun systems... but hey, it's time to move on * our buffer like on some 64bit sun systems... but hey, it's time to move on
*/ */
va_copy(ap2, ap); va_copy(ap2, ap);
chars = vsnprintf(&_T_emptybuffer, 0, fmt, ap2); chars = vsnprintf(&_T_emptybuffer, 0, fmt, ap2);
va_end(ap2); va_end(ap2);
#endif /* defined(WIN32) */ #endif /* defined(_WIN32) */
if (chars < 0 || (size_t)chars + 1 > SIZE_MAX / sizeof(char)) if (chars < 0 || (size_t)chars + 1 > SIZE_MAX / sizeof(char))
{ {
return -1; return -1;