Compare commits

...

237 Commits

Author SHA1 Message Date
Nicolas Badoux
12c4bf1986 Wrong counter increment 2024-09-23 19:08:58 +08:00
Nicolas Badoux
9d1b229086 Added max recusrion depth for cJSONDuplicate to prevent stack exhaustion in case of circular reference 2024-09-23 19:08:58 +08:00
Nicolas Badoux
078c4e6c53 Free mem in cjson_set_valuestring_should_return_null_if_strings_overlap 2024-08-30 11:29:28 +08:00
Nicolas Badoux
4f4d7f70c2 CJSON_SetValuestring: better test for overlapping string 2024-08-30 11:29:28 +08:00
Nicolas Badoux
b47edc4750 CJSON_SetValuestring: add test for overlapping string 2024-08-30 11:29:28 +08:00
Nicolas Badoux
d6d5449e1f fix #881, check overlap before calling strcpy in cJSON_SetValuestring 2024-08-30 11:29:28 +08:00
Nicolas Badoux
a78d975537 cJSON_DetachItemViaPointer: added test and fix for check for null in item->prev 2024-08-30 11:29:05 +08:00
Nicolas Badoux
f28a468e3b Check for NULL in cJSON_DetachItemViaPointer 2024-08-30 11:29:05 +08:00
Alanscut
424ce4ce96 Revert "feat: add tests for #842" to fix test failures
This reverts commit 5b502cdbfb.

Related to #860
2024-06-19 10:58:01 +08:00
Shaun Case
324973008c Fix spelling errors found by CodeSpell. See https://github.com/codespell-project/codespell 2024-05-14 09:43:59 +08:00
DL6ER
8a334b0140 Fix indentation (should use spaces)
Signed-off-by: DL6ER <dl6er@dl6er.de>
2024-05-14 09:42:46 +08:00
Alanscut
acc76239be add contributors 2024-05-13 18:26:15 +08:00
Alanscut
76be8fcf15 Release 1.7.18 2024-05-13 18:26:15 +08:00
Alanscut
5b502cdbfb feat: add tests for #842
Add some tests for setting NULL to deallocated pointers
releated to #842 and #833
2024-05-13 17:18:46 +08:00
maebex
542fb0eadd Set free'd pointers to NULL whenever they are not reassigned immediately after 2024-05-13 17:18:46 +08:00
Alanscut
a20be7996d fix: remove misused optimization flag -01
related to #850
2024-05-09 10:09:18 +08:00
orri
3ef4e4e730 Fix heap buffer overflow
Fixes #800
2024-05-06 11:33:33 +08:00
orri
826cd6f842 Add test for heap buffer overflow
From #800
2024-05-06 11:33:33 +08:00
orri
98f9eb0412 Remove non-functional list handling of compiler flags 2024-05-06 10:48:17 +08:00
Alanscut
19396a49a6 update comments and add tests for cJSON_SetValuestring 2024-04-29 10:01:35 +08:00
Alanscut
5671646e97 fix: fix incorrect name in security.md
Related to #845
2024-04-28 10:10:58 +08:00
Alan Wang
66e9dff670 Create SECURITY.md 2024-04-26 16:58:00 +08:00
Up-wind
7e4d5dabe7 Add NULL check to cJSON_SetValuestring()
If the valuestring passed to cJSON_SetValuestring is NULL, a null pointer dereference will happen.

This commit adds the NULL check of valuestring before it is dereferenced.
2024-04-26 16:34:05 +08:00
Alanscut
87d8f0961a Release 1.7.17
update version to 1.7.17
2023-12-26 10:24:36 +08:00
Lee
f66cbab4bf fix error in null checkings (#810)
fixes #802 and #803
2023-12-20 11:05:23 +08:00
Lee
60ff122ef5 add NULL checkings (#809)
* add NULL checks in cJSON_SetValuestring

Fixes #803(CVE-2023-50472)

* add NULL check in cJSON_InsertItemInArray

Fixes #802(CVE-2023-50471)

* add tests for NULL checks

add tests for NULL checks in cJSON_InsertItemInArray and cJSON_SetValuestring
2023-12-18 11:47:52 +08:00
Alan Wang
cb8693b058 Release 1.7.16 (#770)
* Update version to 1.7.16

* Update contributors
2023-07-05 11:22:19 +08:00
Alan Wang
545710e3bf upgrade clang to fix actions error (#768)
Actions builds are failing because clang-8 is failing to be installed. Upgrade clang-8 to clang-14 to fix this.
2023-07-04 17:02:03 +08:00
MaxBrandtner
543c28869e Add meson documentation (#761) 2023-07-03 09:35:30 +08:00
hopper-vul
766dd9d590 Fix a null pointer crash in cJSON_ReplaceItemViaPointer (#726)
If the parent passed in cJSON_ReplaceItemViaPointer has not a child, which means parent->child is null, a null pointer dereference crash will be happened inside cJSON_ReplaceItemViaPointer.

This commit adds the NULL check of `parent->child` beforehand to inform user such incorrect usage.

Signed-off-by: hopper-vul <hopper.vul@gmail.com>
2023-07-01 16:18:32 +08:00
Junbo Zheng
b45f48e600 fix: add allocate check for replace_item_in_object (#675)
Signed-off-by: Junbo Zheng <zhengjunbo1@xiaomi.com>
2022-03-29 15:02:59 +08:00
Stoian Ivanov
a6424b85dd feat: add cJSON_SetBoolValue and test (#639)
* cJSON_SetBoolValue plus test

* cJSON_Invalid insted of just 0

* Update tests/misc_tests.c

* VSCode standard C formater applied

Co-authored-by: Alan Wang <wp_scut@163.com>
2022-01-26 20:24:50 +08:00
mohawk2
3cecc40466 docs: Fix README typo (#664) 2022-01-26 20:23:33 +08:00
Randy
2fc55f6793 chore: add CIFuzz integration (#437)
* CIFuzz integration

* Rename main.yml to ci-fuzz.yml
2022-01-20 14:23:57 +08:00
Tony Langhammer
c7025b093a chore: ignore all .dylib files (#628)
This fixes some .dylib files being flagged as added when compiled e.g. `libcjson.dylib.1.7.14`
2022-01-20 14:17:46 +08:00
10km
e7ebe77ebf fix: 'cjson_utils-static' target not exist(#625)
* Update CMakeLists.txt

fix the bug:when build with cmake using option '-DBUILD_SHARED_AND_STATIC_LIBS=ON -DENABLE_CJSON_UTILS=ON', build sucess,
but use cmake comand 'find_package(cjson CONFIG)', 'cjson_utils' target is available,but  'cjson_utils-static' target not exist.
2022-01-19 16:28:29 +08:00
Andy
61eb84d991 add an option for ENABLE_CJSON_VERSION_SO in CMakeLists.txt (#534)
Co-authored-by: m00209177 <malihu@huawei.com>
2022-01-19 14:45:02 +08:00
AlexanderVasiljev
d321fa9e6e fix: print int without decimal places (#630) 2022-01-19 10:30:31 +08:00
Alan Wang
203a0dec6f chore: ignore *.lst/*.lss file (#623) 2021-10-22 16:21:55 +08:00
Joshua Arulsamy
c77a688927 build: Bump cmake version and use new version syntax (#587)
Co-authored-by: Alan Wang <wp_scut@163.com>
2021-10-22 16:15:19 +08:00
Alan Wang
e5dbaee131 docs: update comment (#622) 2021-10-22 16:09:45 +08:00
SuperHuan
189dcde644 fix: add cmake_policy to CMakeLists.txt (#613)
Use the cmake_policy() command to set CMP0054 to NEW explicitly.
2021-10-22 16:02:06 +08:00
Sayan Bandyopadhyay
b9eff8b02a fix: for issue #569, now use the guard to turn it off (#617) 2021-10-22 15:57:05 +08:00
Alan Wang
f50dafc7d0 fix: potential memory leak in merge_patch() (#611) 2021-08-26 14:13:42 +08:00
Alan Wang
d348621ca9 chore: update version and changelog (#610) 2021-08-25 19:15:09 +08:00
Alan Wang
744e47353a fix: remove redundant condition (#605) 2021-08-25 15:02:00 +08:00
Dimitri Papadopoulos Orfanos
7795249dd4 Typos found by codespell (#607) 2021-08-25 15:01:12 +08:00
CoffeeTableEspresso
324a6ac9a9 Update .gitattributes (#544) 2020-12-31 10:38:10 +08:00
Alan Wang
6ea4c01e4e Fix potential core dumped for strrchr (#546) 2020-12-31 10:26:39 +08:00
Jordan IMBERT
9226e4ed8c Remove always true condition in cJSON.c (#539) 2020-12-17 17:07:18 +08:00
Alan Wang
7b6645794d Fix null pointer crash, closes #536 (#538) 2020-12-17 15:42:31 +08:00
Tim Gates
4100379a04 docs: fix simple typo, transfering -> transferring (#527)
There is a small typo in tests/readme_examples.c.

Should read `transferring` rather than `transfering`.
2020-11-16 08:57:02 +08:00
mongobaba
2f6fc7f0f2 fix several null pointer problems on allocation failure (#526) 2020-11-12 11:46:15 +08:00
Alan Wang
a1e1c208ff Merge pull request #519 from Alanscut/issue-516
fix a possible dereference of null pointer
2020-10-16 17:12:54 +08:00
Alanscut
9bf4960cd5 fix a possible dereference of null pointer 2020-10-16 17:06:29 +08:00
Alan Wang
488169faca Merge pull request #518 from fpnuseis/master
fix: windows build failure about defining nan
2020-10-16 16:52:10 +08:00
Use
9931900768 fix: windows build failure about defining nan 2020-10-15 11:52:06 +09:00
Alan Wang
d2735278ed Merge pull request #505 from Alanscut/release-1.7.14
Release 1.7.14
2020-09-03 17:14:26 +08:00
Alanscut
8e84db4c4e Update changelog and contributors 2020-09-03 17:11:02 +08:00
Alanscut
8e357f825b Update version to 1.7.14 2020-09-03 17:07:49 +08:00
Alan Wang
2e5171d8d6 Merge pull request #503 from Alanscut/issue499
optimize the way to find tail node
2020-09-03 11:51:54 +08:00
Alanscut
c8ca78a3cc optimize the way to find tail node 2020-09-02 20:23:52 +08:00
Alan Wang
0b13220419 Merge pull request #502 from Alanscut/nan
remove float-divide-by-zero for supporting NAN
2020-08-27 20:48:25 +08:00
Alanscut
23f027139e remove float-divide-by-zero for supporting NAN 2020-08-27 20:46:00 +08:00
Alan Wang
60c3b0a571 Merge pull request #501 from Alanscut/actions
add github actions CI
2020-08-27 20:28:06 +08:00
Alanscut
857c037ccc add github actions CI 2020-08-27 20:26:04 +08:00
Alan Wang
3fb9d929e1 Merge pull request #484 from sappo/master
Problem: WError error on macosx because NAN is a float
2020-08-21 21:30:19 +08:00
Alan Wang
cf97c6f066 Merge pull request #485 from HuKeping/fix-git-archive
Remove unnecessary files in release tarball
2020-06-27 16:13:52 +08:00
h00283522
1ef4deec06 Remove unnecessary files in release tarball
Prior to this patch, we would find '.gitignore', '.travisCI.yml' in
the release tarball.

This patch adds a few entries in .gitattributes to specify files that
should never end up in a distribution tarball.

Signed-off-by: Hu Keping <hukeping@huawei.com>
2020-06-26 10:53:16 +08:00
Kevin Sapper
4578d3a9e1 Problem: WError error on macosx because NAN is a float
Solution: Add explicit cast from NAN to double
2020-06-23 09:17:32 +02:00
Alanscut
b95a4c56b0 fix #376 2020-06-22 11:23:24 +08:00
Alan Wang
7db005e028 Merge pull request #472 from Alanscut/parse-array
array's item should be in the list
2020-05-06 17:34:15 +08:00
Alanscut
1fc755ac09 array's item should be in the list 2020-05-06 17:18:42 +08:00
Alan Wang
a82449fa3e Merge pull request #456 from miaoerduo/master
fix: some bugs in detach and replace, resolved #467
2020-05-06 17:07:33 +08:00
Alan Wang
2a6299d904 Merge pull request #469 from moorthy-bs/master
pkgconfig: cjson include dir added
2020-05-05 11:34:23 +08:00
Alan Wang
43f471bff1 Merge pull request #465 from Summus-git/fix_make_install_config
Make install unwanted config files
2020-05-05 11:31:39 +08:00
Moorthy
7103844037 pkgconfig: cjson include dir added
fixed #468
2020-04-30 12:45:10 +02:00
Romain Lesteven
3442b36672 Fix make.sh install unwanted config files 2020-04-17 12:01:39 +02:00
miaoerduo
cb4661cd91 fix: errors in replacing the first item when array_size is 1, and replacing the last item 2020-04-03 17:21:02 +08:00
miaoerduo
a65abf2f4f fix: error list head's prev when detach the last item 2020-04-03 17:20:57 +08:00
miaoerduo
3999b12848 feat: set list head's prev in parse_array and parse_object 2020-04-03 17:20:42 +08:00
Alanscut
39853e5148 Update changelog 2020-04-02 23:35:50 +08:00
Alanscut
ff0dabc72e Update version to 1.7.13 2020-04-02 23:34:28 +08:00
Alanscut
5d55c6c2ee fix error C2124 in visual studio 2020-04-02 23:32:30 +08:00
Alan Wang
23e4fbc639 Merge pull request #454 from Alanscut/float-compare
comparing double value with DBL_EPSILON
2020-04-02 20:09:42 +08:00
Alan Wang
65578af8cc Merge pull request #453 from Alanscut/add-return-value
add return value for  cJSON_AddItemTo... and cJSON_ReplaceItemxxx
2020-04-02 19:41:56 +08:00
Alan Wang
f12cd7b701 Merge pull request #451 from Alanscut/20200324
add new function of `cJSON_SetValuestring`
2020-04-02 19:40:03 +08:00
Sang-Heon Jeon
97cf1d84e4 Add getNumberValue function
* Add GetNumberValue function and testcase

Co-authored-by: Alan Wang <wp_scut@163.com>
2020-04-02 19:36:35 +08:00
caglarivriz
983bb2b4d6 Added cJSON_ParseWithLength (#358)
Co-authored-by: Caglar Ivriz <caglar.ivriz@siemens.com>
2020-04-02 19:24:36 +08:00
Alanscut
4e114c1f31 update testcase, fixes #433 2020-04-02 16:24:10 +08:00
Alanscut
8943c73345 comparing double value with DBL_EPSILON 2020-04-02 16:02:24 +08:00
Alanscut
af56a146fd update testcase 2020-04-02 11:06:47 +08:00
Alanscut
131966f748 add return value for cJSON_ReplaceItemxxx 2020-04-02 11:00:10 +08:00
Alanscut
bd7cbe9776 false has been redefined to cJSON_False 2020-04-01 19:19:00 +08:00
Alanscut
54d6b8016e add return value for cJSON_AddItemTo... 2020-03-26 14:18:52 +08:00
Alanscut
31c7880fab update cJSON_SetValuestring and testcase 2020-03-25 15:38:54 +08:00
Alanscut
34e102d0dc update README 2020-03-24 22:28:35 +08:00
Alanscut
4790c3c8f5 add testcase for cJSON_SetValuestringToObject 2020-03-24 22:28:27 +08:00
Alanscut
6b35f1c5bc add new function of setValuestringToObject 2020-03-24 22:28:15 +08:00
Alan Wang
3ece4c893c Improve performance of adding item to array (#448)
* use prev pointer when adding item to array

Co-authored-by: xiaomianhehe <hongshaokai@hotmail.com>
Co-authored-by: Alanscut <scut@163.com>

Date:   Tue Feb 18 11:54:23 2020 +0800

* add testcase for cJSON_DeleteItemFromArray
2020-03-24 16:17:25 +08:00
Alanscut
fa28d82f2e update contributors 2020-03-19 22:58:04 +08:00
Alan Wang
1be85ff26d Merge pull request #447 from Alanscut/fix_encode_string_as_pointer
Fix encode_string_as_pointer
2020-03-18 16:53:52 +08:00
Alanscut
d92c0de7e8 fix encode_string_as_pointer 2020-03-18 16:04:58 +08:00
Alan Wang
ae7a7a1d0c Merge pull request #440 from Square789/patch-1
updating doc
2020-03-16 23:12:14 +08:00
Alan Wang
0586a6c437 Merge pull request #446 from DaveGamble/revert-430-array_add
Revert "use prev pointer when array do adding"
2020-03-16 23:08:06 +08:00
Alan Wang
9034a9cd0b Revert "use prev pointer when array do adding (#430)"
This reverts commit e8077d0150.
2020-03-16 23:04:39 +08:00
Square789
b0e7195a74 Spelling; "it's"->"its" 2020-03-09 13:40:08 +01:00
xiaomianhehe
e8077d0150 use prev pointer when array do adding (#430)
* use prev pointer when array do adding
2020-02-18 11:54:23 +08:00
Alan Wang
2955fe5ec4 Merge pull request #431 from DevGim/dev
formatting README.md
2020-02-11 14:18:50 +08:00
dm8.kim
895b9ad344 formatting README.md 2020-02-11 13:25:02 +09:00
Alanscut
f790e17b6c update content in README 2020-01-19 15:23:48 +08:00
Alan Wang
2c97086b97 Merge pull request #425 from NancyLi1013/vcpkg-instructions
Add vcpkg installation instructions
2020-01-19 15:10:54 +08:00
NancyLi1013
ada2169183 Update changes 2020-01-18 23:08:59 -08:00
NancyLi1013
cc78050ff4 Add vcpkg installation instructions 2020-01-18 22:47:46 -08:00
Alanscut
74b2f03837 remove annoying float-equal option 2020-01-18 23:18:19 +08:00
Alanscut
fa8b454552 correct mistake 2020-01-16 17:10:52 +08:00
Alanscut
2d4ad84192 Merge pull request #418 from Alanscut/update_Changelog
update CHANGELOG
2019-12-10 17:38:45 +08:00
Alanscut
ea532cdd61 update CHANGELOG.md 2019-12-10 17:20:46 +08:00
Alanscut
4e3335618f improve compare_double 2019-12-09 10:36:45 +08:00
Alanscut
69bc9ccc20 Merge pull request #417 from zjuchenyuan/patch-1
Update cJSON_Utils.c to avoid ‘CJSON_DOUBLE_PRECIION’ undeclared
2019-12-09 08:54:55 +08:00
ChenYuan
ea3a6dcd69 Update cJSON_Utils.c
fix typo
2019-12-07 20:24:07 +08:00
Alanscut
c06d8264d0 improve compare_double function 2019-12-06 18:16:27 +08:00
Alanscut
1f970e7db3 fix double comparison 2019-12-06 17:11:12 +08:00
Alanscut
98ecc0245a revert R_CFLAGS 2019-12-06 15:32:45 +08:00
Alanscut
6434d8643e Merge pull request #368 from paulmalovanyi/master
Fix clang -Wfloat-equal warning
2019-12-06 15:18:55 +08:00
Alanscut
51f6b4c07e Merge branch 'master' into master 2019-12-06 15:14:26 +08:00
Alanscut
d31fdefa38 Merge pull request #412 from Alanscut/fix_issue_327
fix issue#327
2019-12-06 14:43:58 +08:00
Alanscut
8badd19b64 Merge pull request #415 from Alanscut/fix_issue_414
fix memory leak mentioned in issue 414
2019-12-05 11:13:20 +08:00
Alanscut
500a9db81b fix memory leak mentioned in issue 414 2019-12-05 11:05:07 +08:00
Alanscut
95368da1a1 Merge pull request #413 from erez-o/master
Added blank lines in Readme.md
2019-11-29 11:04:49 +08:00
Erez Oxman
f3b6ad15f0 Added blank lines in Readme.md
Added blank lines before list items and headings. This change creates consistency between different markdown parsers. There's no difference in the output of Github flavored markdown.

See https://babelmark.github.io/
2019-11-28 14:15:44 +02:00
Alanscut
446ff0d6cc fix issue#327 2019-11-28 09:56:04 +08:00
Alanscut
6a848fce32 Merge pull request #408 from rolegic/patch-api-h-c
Fixed different argument between declaration and definition
2019-11-19 10:51:13 +08:00
rolegic
c64854b26e Fixed different argument between declaration and definition 2019-11-15 15:43:43 +01:00
Alanscut
533ff8a783 Merge pull request #405 from Alanscut/issue-404
fix make failed in mac os
2019-11-02 22:38:33 +08:00
Alanscut
4755aea837 fix make failed in mac os 2019-11-01 11:30:14 +08:00
Alanscut
4454731775 update readme 2019-10-29 16:14:22 +08:00
Alanscut
326f1f5ed5 Merge pull request #402 from Alanscut/cmake_add_uninstall_target
CMake: add uninstall target
2019-10-29 16:09:32 +08:00
Alanscut
bb059dc2e1 add uninstall target in cmake 2019-10-29 15:48:11 +08:00
Alanscut
de99175cd0 fix rmdir error (#401)
* fix rmdir error
2019-10-29 14:21:16 +08:00
Alanscut
a417b183c6 add new line to endif 2019-10-29 12:47:36 +08:00
Alanscut
f589f81a42 Merge pull request #400 from randy408/fuzz
OSS-Fuzz: build with $CXX
2019-10-22 21:07:52 +08:00
Randy
49a0ede475 ossfuzz: build with c++ compiler 2019-10-22 13:37:41 +02:00
Randy
73b0e739d0 fuzz: add support for compiling with c++ compiler 2019-10-22 13:32:41 +02:00
Alanscut
a0fdf115be Merge pull request #398 from randy408/fuzz
ossfuzz.sh: fix permission bits
2019-10-22 18:48:47 +08:00
Randy
6b728982f2 ossfuzz.sh: fix permission bits 2019-10-22 12:45:13 +02:00
Alanscut
f00060af44 Merge pull request #378 from randy408/fuzz
Add libFuzzer fuzz target / OSS-Fuzz integration
2019-10-22 11:22:30 +08:00
randy408
ec8d2f9c2e convert fuzz target to c89, optimize 2019-10-21 15:27:47 +02:00
Alanscut
18b7113b49 Merge pull request #351 from GitMensch/patch-1
allow to override PIC_FLAGS and compiler std
2019-10-21 17:06:14 +08:00
Alanscut
18dad60035 Merge pull request #377 from Alanscut/20190628
fix bug: add const to the parameter in the cJSON_GetStringValue function
2019-10-20 22:47:11 +08:00
Alanscut
66d0a1793f Merge pull request #395 from bjda/more_const
Add const qualifier to cJSON_CreateStringArray
2019-10-20 22:46:05 +08:00
Alanscut
a8dbf6d878 Merge pull request #343 from myd7349/fix-install-path
CMake: Improve install target
2019-10-19 22:57:48 +08:00
Alanscut
60fb788aa5 Merge pull request #396 from julian-st/master
initialize variables in print_number
2019-10-19 22:23:45 +08:00
Julian Ste
bcc91ecbc3 initilize variables in print_number 2019-10-19 13:53:21 +02:00
Bernt Johan Damslora
26772a8ef7 Add const qualifier to cJSON_CreateStringArray
Adds a const qualifier to the strings in the array to avoid discarding
it from arguments.
2019-10-17 14:03:15 +02:00
randy408
dc56e24f7f add build script 2019-10-14 17:12:13 +02:00
Alanscut
f31ff795bd Merge pull request #392 from Alanscut/fix-readme-typos
Fix typos in REAM.md file
2019-10-08 09:10:54 +08:00
Alanscut
e52b212dbf fix typos in REAM.md file 2019-09-29 19:06:47 +08:00
Alanscut
2de7d04aaf Merge pull request #389 from DaveGamble/revert-388-secure_c
Revert "Replace strcpy with strncpy, sprintf with snprintf"
2019-09-24 10:20:41 +08:00
Alanscut
ae49da2b61 Revert "Replace strcpy with strncpy, sprintf with snprintf" 2019-09-21 17:42:25 +08:00
Alanscut
a3154a36f1 Merge pull request #388 from singku/secure_c
Replace strcpy with strncpy, sprintf with snprintf
2019-09-21 15:43:13 +08:00
Alanscut
189b51c5da format comment 2019-09-11 10:42:44 +08:00
Alanscut
709c3dcf32 Merge pull request #374 from Alanscut/20190625
Add a comment to the parameter count of the cJSON_CreateIntArray function
2019-09-11 09:53:19 +08:00
Alanscut
c61573f1af format adjustment 2019-09-11 09:51:30 +08:00
Alanscut
20cffa37a8 Merge pull request #380 from vemakereporter/master
Fixed 1 missing dependency in Makefile
2019-09-11 09:00:44 +08:00
Alanscut
cf0d87a095 Merge pull request #384 from Alanscut/eliminate_warning
eliminate warning when compiling cJSON
2019-08-28 20:57:02 +08:00
Alanscut
e750194cb1 Merge pull request #386 from lntuition/master
Correct typo error in cJSON.h
2019-08-28 20:56:06 +08:00
Alanscut
e13f11ba79 Merge pull request #360 from Alanscut/master
add comment for cJSON_Minify function
2019-08-27 14:50:48 +08:00
Alanscut
8872b1429a Merge pull request #371 from basanjeev/master
Fix typos.
2019-08-26 16:33:05 +08:00
Randy
bd1a375028 add fuzzer driver, integrate with build system 2019-08-24 17:42:48 +02:00
Sang-Heon Jeon
b6da0d6565 Correct typo error 2019-08-24 22:43:33 +09:00
Alanscut
166c814cda eliminate warning when compiling cJSON 2019-08-12 17:06:29 +08:00
Vemake
c680faea56 Update Makefile 2019-07-24 20:46:41 +08:00
Randy
2d6db59c7b update fuzzer 2019-07-11 15:09:10 +02:00
Randy
e6bc5d16e6 update fuzzer 2019-07-11 15:03:04 +02:00
Randy
2691e142f4 update fuzzer 2019-07-11 14:42:27 +02:00
Randy
f7f175fdf2 add fuzz target 2019-07-11 13:56:07 +02:00
Alanscut
9d766f07a7 fix const cast warnings in cJSON_GetStringValue 2019-06-28 14:22:02 +08:00
Alanscut
85ceadb4b4 Add a comment to the parameter count of the cJSON_CreateIntArray function. 2019-06-25 17:25:23 +08:00
Sanjeev BA
110f184d18 Fix typos.
Signed-off-by: Sanjeev BA <iamsanjeev@gmail.com>
2019-06-16 07:58:03 +09:00
Paweł Malowany
c9e8a68b00 Fix clang -Wfloat-equal warning 2019-06-10 11:37:03 +02:00
singku
16f56300e4 Replace strcpy with strncpy, sprintf with snprintf 2019-05-29 21:25:33 +00:00
Alan_scut
5fe80a94b6 add comment for cJSON_Minify function 2019-05-22 10:24:13 +08:00
Max Bruckner
3c8935676a Merge pull request #355 from DaveGamble/release-1.7.12
Release 1.7.12
2019-05-17 01:05:59 +02:00
Max Bruckner
b93fd34044 Update changelog and contributors 2019-05-17 00:37:26 +02:00
Max Bruckner
687b1a2fe1 Update version to 1.7.12 2019-05-16 20:03:12 +02:00
Max Bruckner
08d2bc766a Fix infinite loop in cJSON_Minify 2019-05-16 20:01:02 +02:00
Max Bruckner
465352fb99 Merge pull request #352 from tan-wei/master
Add link dependency to fix tests link error when ENABLE_CJSON_UTILS is ON
2019-05-11 12:06:26 +02:00
Winterreise
19ff92da79 Add link dependency to fix tests link error when ENABLE_CJSON_UTILS is ON 2019-05-11 07:37:33 +08:00
Simon Sobisch
3a4cfa84c3 allow to override PIC_FLAGS and compiler std 2019-05-06 21:07:06 +02:00
Max Bruckner
62bc2e3432 Merge pull request #347 from raiden00pl/master
Undef true and false first also for cJSON_Utils.c
2019-04-28 13:31:46 +02:00
raiden00pl
359567fdde Undef true and false first also for cJSON_Utils.c 2019-04-28 10:33:44 +02:00
Max Bruckner
0b5a7abf48 Merge pull request #340 from ldm0/master
Typo Fix
2019-04-15 23:06:11 +02:00
Max Bruckner
93688cbe72 Merge pull request #344 from DaveGamble/release-1.7.11
Release 1.7.11
2019-04-15 00:17:19 +02:00
Max Bruckner
6b249213dd Fix clang -Wcomma warning 2019-04-15 00:06:35 +02:00
Max Bruckner
09ebae8149 Release cJSON 1.7.11 2019-04-14 23:58:02 +02:00
Max Bruckner
a43fa56a63 Rewrite cJSON_Minify, fixing buffer overflows, fixes #338
Also first tests for cJSON_Minify.
Thanks @bigric3 for reporting
2019-04-14 23:18:48 +02:00
myd7349
9a970b9ff6 CMake: Improve install target 2019-04-14 19:41:28 +08:00
Max Bruckner
5a52eaddfd Undef true and false first, fixes #339
Thanks  @raiden00pl for reporting
2019-04-13 01:44:23 +02:00
Donough Liu
add86a6be8 Update cJSON.c 2019-03-18 22:56:34 +08:00
Max Bruckner
c69134d017 Release Version 1.7.10 2018-12-20 18:15:05 +01:00
Max Bruckner
563d861f92 cJSON_Utils: sort_lists: Properly split the lists
Since `prev` is not used anymore after that by the algorithm it should
have been fine anyways, still splitting it correctly in the first place
is probably a good idea.
Thanks @andysCaplin for the fix!
2018-12-20 18:12:23 +01:00
Max Bruckner
6820448db5 libcjson.pc.in: Use Libs.private instead of Private
Thanks @shiluotang
2018-12-20 18:04:52 +01:00
Max Bruckner
d44b594ab3 Add missing changelog entry 2018-12-16 11:21:35 +01:00
Max Bruckner
f110bd2e58 Release Version 1.7.9 2018-12-16 11:17:20 +01:00
Max Bruckner
5cd1dabb30 Add yuta-oxo to the Contributors 2018-12-16 11:16:31 +01:00
Max Bruckner
d606cbbc64 Merge pull request #317 from yuta-oxo/fix_sort_list
fix bug: sort_list() returns strange results
2018-12-16 11:10:06 +01:00
Max Bruckner
be749d7efa Fix crash of cJSON_GetObjectItemCaseSensitive when calling it on arrays 2018-12-16 11:06:40 +01:00
yuta-oxo
eaec82c3c5 fix bug: sort_list() returns strange results 2018-12-12 15:09:53 +09:00
Max Bruckner
cb1df2f88c README: Add note about needing to free print results in examples 2018-12-03 23:07:36 +01:00
Max Bruckner
2c914c073d Gitignore: Ignore CLion directories 2018-10-14 11:52:41 +02:00
Max Bruckner
4917024741 Makefile: Fix indentation 2018-10-14 11:52:19 +02:00
Max Bruckner
a3fadd44d1 Add .editorconfig 2018-10-14 11:51:56 +02:00
Max Bruckner
feb05fb2fd Add Benbuck Nason to the list of contributors 2018-10-14 11:22:14 +02:00
Max Bruckner
26f38f4782 Merge pull request #307 from bnason-nf/vstudio_static_analyzer_warnings
Fix most of the issues reported by the Visual Studio code analysis tool
2018-10-14 11:17:34 +02:00
Benbuck Nason
8e742e4869 Fix most of the issues reported by the Visual Studio code analysis tool. 2018-10-12 14:29:59 -07:00
Max Bruckner
543ab5d08a Update json-patch-tests 2018-10-11 00:30:43 +02:00
Max Bruckner
e2162adeed Squashed 'tests/json-patch-tests/' changes from 99264bb..9ecd703
9ecd703 Merge pull request #39 from mr-mixas/test-absent-from-location-for-copy-and-move-ops
66817e7 test absent 'from' location for copy and move
09dee56 Fix anonymous test
8bae8ed Fix « test should pass - no error » test
855f2a4 Fix « test should pass despite (nested) rearrangement » test
53283fc Fix « test should pass despite rearrangement » test
ecf01e7 Fix « null value should be valid obj property » test
1586cdf Fix « Empty-string element » test

git-subtree-dir: tests/json-patch-tests
git-subtree-split: 9ecd703c08cda4864cd2d2fb580a513ec5740934
2018-10-11 00:30:43 +02:00
Max Bruckner
08103f048e Release version 1.7.8 2018-09-21 19:29:42 +02:00
Max Bruckner
ace800e444 Update changelog for 1.7.8 2018-09-21 19:28:25 +02:00
Max Bruckner
00544a4a74 Contributors: Add Zach Hindes 2018-09-21 19:26:01 +02:00
Max Bruckner
3550a5553d Merge pull request #295 from zhindes/master
Support default __stdcall calling convention (/Gz) on Windows
2018-09-21 19:23:31 +02:00
Zach Hindes
d9fe34bade Add newline to end of unity_setup.c 2018-09-17 09:10:20 -05:00
Zach Hindes
f25b8448e4 Support default __stdcall calling convention on tests as well 2018-09-12 15:32:30 -05:00
Zach Hindes
ad2cb5b7ea Enable build and test on Windows 2018-09-04 14:36:21 -05:00
Zach Hindes
f32703a7a1 Support default __stdcall calling convention (/Gz) on Windows 2018-08-29 16:25:46 -05:00
Max Bruckner
86234db095 Release cJSON v1.7.7 2018-05-21 22:08:21 +02:00
Max Bruckner
af5b4911de Fix memory leak if realloc returns NULL
Thanks @AlfieDeng for reporting
2018-05-21 22:00:07 +02:00
Max Bruckner
787d651e81 Contributors: Add Zhao Zhixu 2018-05-08 21:33:33 +02:00
Max Bruckner
1571a3ebe4 Merge pull request #266 from zhaozhixu/master
fix a typo in cJSON.h
2018-05-08 21:31:00 +02:00
Zhao Zhixu
0d5ecc11b6 fix typo 2018-05-08 22:45:14 +08:00
Max Bruckner
529ec06abb Makefile: Fix #263, use $(CC) instead of 'gcc' for detecting the version 2018-04-29 09:20:08 +02:00
Max Bruckner
3349978268 cJSON.c: Remove unnecessary include of float.h, fix #259 2018-04-26 23:58:51 +02:00
Max Bruckner
cbc05de76f Release version 1.7.6 2018-04-13 12:32:30 +08:00
Max Bruckner
7996a4a2ee Readme: Deprecate the Makefile 2018-04-13 12:12:26 +08:00
Max Bruckner
ed8fefc9ca Makefile: Fix #252, put soname in the ELF file 2018-04-13 12:03:33 +08:00
Max Bruckner
e6869c2e03 cJSON_Utils.h: Add include guards and extern C for C++ 2018-04-13 10:32:29 +08:00
51 changed files with 2089 additions and 485 deletions

23
.editorconfig Normal file
View File

@@ -0,0 +1,23 @@
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[Makefile]
indent_style = tab
indent_size = unset
# ignore external repositories and test inputs
[tests/{unity,json-patch-tests,inputs}/*]
indent_style = unset
indent_size = unset
end_of_line = unset
charset = unset
trim_trailing_whitespace = unset
insert_final_newline = unset

11
.gitattributes vendored Normal file
View File

@@ -0,0 +1,11 @@
* text=auto
/tests/inputs/* text eol=lf
.gitattributes export-ignore
.gitignore export-ignore
.github export-ignore
.editorconfig export-ignore
.travis.yml export-ignore
# Linguist incorrectly identified the headers as C++, manually override this.
*.h linguist-language=C

102
.github/workflows/CI.yml vendored Normal file
View File

@@ -0,0 +1,102 @@
name: CI
on:
push:
branches: [ master ]
paths-ignore:
- '**.md'
- 'LICENSE'
pull_request:
types: [opened, synchronize]
paths-ignore:
- '**.md'
- 'LICENSE'
jobs:
linux:
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, 'ci skip')"
strategy:
fail-fast: false
matrix:
mem_check:
- ENABLE_VALGRIND
- ENABLE_SANITIZERS
- NONE_MEM_CHECK
compiler:
- GCC
- CLANG
steps:
- uses: actions/checkout@v2
- name: install build dependencies
run: |
sudo apt-get update
sudo apt-get install clang-14 valgrind
- name: build and test
shell: bash
run: |
if [ "${{ matrix.mem_check }}" == "ENABLE_VALGRIND" ]; then
EVENT_CMAKE_OPTIONS="-DENABLE_CJSON_UTILS=ON -DENABLE_VALGRIND=ON -DENABLE_SAFE_STACK=ON -DENABLE_SANITIZERS=OFF"
elif [ "${{ matrix.mem_check }}" == "ENABLE_SANITIZERS" ]; then
EVENT_CMAKE_OPTIONS="-DENABLE_CJSON_UTILS=ON -DENABLE_VALGRIND=OFF -DENABLE_SAFE_STACK=OFF -DENABLE_SANITIZERS=ON"
else
EVENT_CMAKE_OPTIONS="-DENABLE_CJSON_UTILS=ON -DENABLE_VALGRIND=OFF -DENABLE_SAFE_STACK=OFF -DENABLE_SANITIZERS=OFF"
fi
if [ "${{ matrix.compiler }}" == "GCC" ]; then
export CC=gcc
else
export CC=clang
fi
#run build and test
JOBS=20
export CTEST_PARALLEL_LEVEL=$JOBS
export CTEST_OUTPUT_ON_FAILURE=1
mkdir -p build
cd build
echo [cmake]: cmake .. $EVENT_CMAKE_OPTIONS
cmake .. $EVENT_CMAKE_OPTIONS || (rm -rf * && cmake .. $EVENT_CMAKE_OPTIONS)
cmake --build .
make
make test
macos:
runs-on: macos-latest
if: "!contains(github.event.head_commit.message, 'ci skip')"
strategy:
fail-fast: false
matrix:
mem_check:
- ENABLE_VALGRIND
- ENABLE_SANITIZERS
- NONE_MEM_CHECK
compiler:
- GCC
- CLANG
steps:
- uses: actions/checkout@v2
- name: build and test
shell: bash
run: |
if [ "${{ matrix.mem_check }}" == "ENABLE_VALGRIND" ]; then
EVENT_CMAKE_OPTIONS="-DENABLE_CJSON_UTILS=ON -DENABLE_VALGRIND=ON -DENABLE_SAFE_STACK=ON -DENABLE_SANITIZERS=OFF"
elif [ "${{ matrix.mem_check }}" == "ENABLE_SANITIZERS" ]; then
EVENT_CMAKE_OPTIONS="-DENABLE_CJSON_UTILS=ON -DENABLE_VALGRIND=OFF -DENABLE_SAFE_STACK=OFF -DENABLE_SANITIZERS=ON"
else
EVENT_CMAKE_OPTIONS="-DENABLE_CJSON_UTILS=ON -DENABLE_VALGRIND=OFF -DENABLE_SAFE_STACK=OFF -DENABLE_SANITIZERS=OFF"
fi
if [ "${{ matrix.compiler }}" == "GCC" ]; then
export CC=gcc
else
export CC=clang
fi
#run build and test
JOBS=20
export CTEST_PARALLEL_LEVEL=$JOBS
export CTEST_OUTPUT_ON_FAILURE=1
mkdir -p build
cd build
echo [cmake]: cmake .. $EVENT_CMAKE_OPTIONS
cmake .. $EVENT_CMAKE_OPTIONS || (rm -rf * && cmake .. $EVENT_CMAKE_OPTIONS)
cmake --build .
make
make test

23
.github/workflows/ci-fuzz.yml vendored Normal file
View File

@@ -0,0 +1,23 @@
name: CIFuzz
on: [pull_request]
jobs:
Fuzzing:
runs-on: ubuntu-latest
steps:
- name: Build Fuzzers
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
with:
oss-fuzz-project-name: 'cjson'
dry-run: false
- name: Run Fuzzers
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
with:
oss-fuzz-project-name: 'cjson'
fuzz-seconds: 600
dry-run: false
- name: Upload Crash
uses: actions/upload-artifact@v1
if: failure()
with:
name: artifacts
path: ./out/artifacts

6
.gitignore vendored
View File

@@ -6,7 +6,7 @@ test
*.swp
*.patch
tags
*.dylib
*.dylib*
build/
cJSON_test
cJSON_test_utils
@@ -14,3 +14,7 @@ libcjson.so.*
libcjson_utils.so.*
*.orig
.vscode
.idea
cmake-build-debug
*.lst
*.lss

View File

@@ -1,64 +1,189 @@
1.7.5
1.7.18 (May 13, 2024)
======
Fixes:
------
* Add NULL check to cJSON_SetValuestring()(CVE-2024-31755), see #839 and #840
* Remove non-functional list handling of compiler flags, see #851
* Fix heap buffer overflow, see #852
* remove misused optimization flag -01, see #854
* Set free'd pointers to NULL whenever they are not reassigned immediately after, see #855 and #833
1.7.17 (Dec 26, 2023)
======
Fixes:
------
* Fix null reference in cJSON_SetValuestring(CVE-2023-50472), see #809
* Fix null reference in cJSON_InsertItemInArray(CVE-2023-50471), see #809 and #810
1.7.16 (Jul 5, 2023)
======
Features:
------
* Add an option for ENABLE_CJSON_VERSION_SO in CMakeLists.txt, see #534
* Add cmake_policy to CMakeLists.txt, see #163
* Add cJSON_SetBoolValue, see #639
* Add meson documentation, see #761
Fixes:
------
* Fix memory leak in merge_patch, see #611
* Fix conflicting target names 'uninstall', see #617
* Bump cmake version to 3.0 and use new version syntax, see #587
* Print int without decimal places, see #630
* Fix 'cjson_utils-static' target not exist, see #625
* Add allocate check for replace_item_in_object, see #675
* Fix a null pointer crash in cJSON_ReplaceItemViaPointer, see #726
1.7.15 (Aug 25, 2021)
======
Fixes:
------
* Fix potential core dumped for strrchr, see [#546](https://github.com/DaveGamble/cJSON/pull/546)
* Fix null pointer crash in cJSON_CreateXxArray, see [#538](https://github.com/DaveGamble/cJSON/pull/538)
* Fix several null pointer problems on allocation failure, see [#526](https://github.com/DaveGamble/cJSON/pull/526)
* Fix a possible dereference of null pointer, see [#519](https://github.com/DaveGamble/cJSON/pull/519)
* Fix windows build failure about defining nan, see [#518](https://github.com/DaveGamble/cJSON/pull/518)
1.7.14 (Sep 3, 2020)
======
Fixes:
------
* optimize the way to find tail node, see [#503](https://github.com/DaveGamble/cJSON/pull/503)
* Fix WError error on macosx because NAN is a float. Thanks @sappo, see [#484](https://github.com/DaveGamble/cJSON/pull/484)
* Fix some bugs in detach and replace. Thanks @miaoerduo, see [#456](https://github.com/DaveGamble/cJSON/pull/456)
1.7.13 (Apr 2, 2020)
======
Features:
---------
* add new API of cJSON_ParseWithLength without breaking changes. Thanks @caglarivriz, see [#358](https://github.com/DaveGamble/cJSON/pull/358)
* add new API of cJSON_GetNumberValue. Thanks @Intuition, see[#385](https://github.com/DaveGamble/cJSON/pull/385)
* add uninstall target function for CMake. See [#402](https://github.com/DaveGamble/cJSON/pull/402)
* Improve performance of adding item to array. Thanks @xiaomianhehe, see [#430](https://github.com/DaveGamble/cJSON/pull/430), [#448](https://github.com/DaveGamble/cJSON/pull/448)
* add new API of cJSON_SetValuestring, for changing the valuestring safely. See [#451](https://github.com/DaveGamble/cJSON/pull/451)
* add return value for cJSON_AddItemTo... and cJSON_ReplaceItem... (check if the operation successful). See [#453](https://github.com/DaveGamble/cJSON/pull/453)
Fixes:
------
* Fix clang -Wfloat-equal warning. Thanks @paulmalovanyi, see [#368](https://github.com/DaveGamble/cJSON/pull/368)
* Fix make failed in mac os. See [#405](https://github.com/DaveGamble/cJSON/pull/405)
* Fix memory leak in cJSONUtils_FindPointerFromObjectTo. Thanks @andywolk for reporting, see [#414](https://github.com/DaveGamble/cJSON/issues/414)
* Fix bug in encode_string_as_pointer. Thanks @AIChangJiang for reporting, see [#439](https://github.com/DaveGamble/cJSON/issues/439)
1.7.12 (May 17, 2019)
======
Fixes:
------
* Fix infinite loop in `cJSON_Minify` (potential Denial of Service). Thanks @Alanscut for reporting, see [#354](https://github.com/DaveGamble/cJSON/issues/354)
* Fix link error for Visual Studio. Thanks @tan-wei, see [#352](https://github.com/DaveGamble/cJSON/pull/352).
* Undefine `true` and `false` for `cJSON_Utils` before redefining them. Thanks @raiden00pl, see [#347](https://github.com/DaveGamble/cJSON/pull/347).
1.7.11 (Apr 15, 2019)
======
Fixes:
------
* Fix a bug where cJSON_Minify could overflow it's buffer, both reading and writing. This is a security issue, see [#338](https://github.com/DaveGamble/cJSON/issues/338). Big thanks @bigric3 for reporting.
* Unset `true` and `false` macros before setting them if they exist. See [#339](https://github.com/DaveGamble/cJSON/issues/339), thanks @raiden00pl for reporting
1.7.10 (Dec 21, 2018)
======
Fixes:
------
* Fix package config file for `libcjson`. Thanks @shiluotang for reporting [#321](https://github.com/DaveGamble/cJSON/issues/321)
* Correctly split lists in `cJSON_Utils`'s merge sort. Thanks @andysCaplin for the fix [#322](https://github.com/DaveGamble/cJSON/issues/322)
1.7.9 (Dec 16, 2018)
=====
Fixes:
------
* Fix a bug in the JSON Patch implementation of `cJSON Utils` (see #251), thanks @bobkocisko.
* Fix a bug where `cJSON_GetObjectItemCaseSensitive` would pass a nullpointer to `strcmp` when called on an array, see [#315](https://github.com/DaveGamble/cJSON/issues/315). Thanks @yuweol for reporting.
* Fix error in `cJSON_Utils` where the case sensitivity was not respected, see [#317](https://github.com/DaveGamble/cJSON/pull/317). Thanks @yuta-oxo for fixing.
* Fix some warnings detected by the Visual Studio Static Analyzer, see [#307](https://github.com/DaveGamble/cJSON/pull/307). Thanks @bnason-nf
1.7.4
1.7.8 (Sep 22, 2018)
======
Fixes:
------
* cJSON now works with the `__stdcall` calling convention on Windows, see [#295](https://github.com/DaveGamble/cJSON/pull/295), thanks @zhindes for contributing
1.7.7 (May 22, 2018)
=====
Fixes:
------
* Fix potential use after free if the `string` parameter to `cJSON_AddItemToObject` is an alias of the `string` property of the object that is added (#248). Thanks @hhallen for reporting.
* Fix a memory leak when realloc fails, see [#267](https://github.com/DaveGamble/cJSON/issues/267), thanks @AlfieDeng for reporting
* Fix a typo in the header file, see [#266](https://github.com/DaveGamble/cJSON/pull/266), thanks @zhaozhixu
1.7.3
1.7.6 (Apr 13, 2018)
=====
Fixes:
------
* Fix potential double free, thanks @projectgus for reporting (see #241)
* Add `SONAME` to the ELF files built by the Makefile, see [#252](https://github.com/DaveGamble/cJSON/issues/252), thanks @YanhaoMo for reporting
* Add include guards and `extern "C"` to `cJSON_Utils.h`, see [#256](https://github.com/DaveGamble/cJSON/issues/256), thanks @daschfg for reporting
1.7.2
Other changes:
* Mark the Makefile as deprecated in the README.
1.7.5 (Mar 23, 2018)
=====
Fixes:
------
* Fix the use of GNUInstallDirs variables and the pkgconfig file. Thanks @zeerd for reporting (see #240)
* Fix a bug in the JSON Patch implementation of `cJSON Utils`, see [#251](https://github.com/DaveGamble/cJSON/pull/251), thanks @bobkocisko.
1.7.1
1.7.4 (Mar 3, 2018)
=====
Fixes:
------
* Fixed an Off-By-One error that could lead to an out of bounds write. Thanks @liuyunbin for reporting (see #230)
* Fixed two errors with buffered printing. Thanks @liuyunbin for reporting (see #230)
* Fix potential use after free if the `string` parameter to `cJSON_AddItemToObject` is an alias of the `string` property of the object that is added,see [#248](https://github.com/DaveGamble/cJSON/issues/248). Thanks @hhallen for reporting.
1.7.0
1.7.3 (Feb 8, 2018)
=====
Fixes:
------
* Fix potential double free, thanks @projectgus for reporting [#241](https://github.com/DaveGamble/cJSON/issues/241)
1.7.2 (Feb 6, 2018)
=====
Fixes:
------
* Fix the use of GNUInstallDirs variables and the pkgconfig file. Thanks @zeerd for reporting [#240](https://github.com/DaveGamble/cJSON/pull/240)
1.7.1 (Jan 10, 2018)
=====
Fixes:
------
* Fixed an Off-By-One error that could lead to an out of bounds write. Thanks @liuyunbin for reporting [#230](https://github.com/DaveGamble/cJSON/issues/230)
* Fixed two errors with buffered printing. Thanks @liuyunbin for reporting [#230](https://github.com/DaveGamble/cJSON/issues/230)
1.7.0 (Dec 31, 2017)
=====
Features:
---------
* Large rewrite of the documentation, see #215
* Large rewrite of the documentation, see [#215](https://github.com/DaveGamble/cJSON/pull/215)
* Added the `cJSON_GetStringValue` function
* Added the `cJSON_CreateStringReference` function
* Added the `cJSON_CreateArrayReference` function
* Added the `cJSON_CreateObjectReference` function
* The `cJSON_Add...ToObject` macros are now functions that return a pointer to the added item, see #226
* The `cJSON_Add...ToObject` macros are now functions that return a pointer to the added item, see [#226](https://github.com/DaveGamble/cJSON/pull/226)
Fixes:
------
* Fix a problem with `GNUInstallDirs` in the CMakeLists.txt, thanks @yangfl, see #210
* Fix linking the tests when building as static library, see #213
* New overrides for the CMake option `BUILD_SHARED_LIBS`, see #207
* Fix a problem with `GNUInstallDirs` in the CMakeLists.txt, thanks @yangfl, see [#210](https://github.com/DaveGamble/cJSON/pull/210)
* Fix linking the tests when building as static library, see [#213](https://github.com/DaveGamble/cJSON/issues/213)
* New overrides for the CMake option `BUILD_SHARED_LIBS`, see [#207](https://github.com/DaveGamble/cJSON/issues/207)
Other Changes:
--------------
* Readme: Explain how to include cJSON, see #211
* Removed some trailing spaces in the code, thanks @yangfl, see#212
* Readme: Explain how to include cJSON, see [#211](https://github.com/DaveGamble/cJSON/pull/211)
* Removed some trailing spaces in the code, thanks @yangfl, see [#212](https://github.com/DaveGamble/cJSON/pull/212)
* Updated [Unity](https://github.com/ThrowTheSwitch/Unity) and [json-patch-tests](https://github.com/json-patch/json-patch-tests)
1.6.0
1.6.0 (Oct 9, 2017)
=====
Features:
---------
* You can now build cJSON as both shared and static library at once with CMake using `-DBUILD_SHARED_AND_STATIC_LIBS=On`, see #178
* UTF-8 byte order marks are now ignored, see #184
* Locales can now be disabled with the option `-DENABLE_LOCALES=Off`, see #202, thanks @Casperinous
* You can now build cJSON as both shared and static library at once with CMake using `-DBUILD_SHARED_AND_STATIC_LIBS=On`, see [#178](https://github.com/DaveGamble/cJSON/issues/178)
* UTF-8 byte order marks are now ignored, see [#184](https://github.com/DaveGamble/cJSON/issues/184)
* Locales can now be disabled with the option `-DENABLE_LOCALES=Off`, see [#202](https://github.com/DaveGamble/cJSON/issues/202), thanks @Casperinous
* Better support for MSVC and Visual Studio
Other Changes:
@@ -67,75 +192,78 @@ Other Changes:
* More number printing tests.
* Continuous integration testing with AppVeyor (semi automatic at this point), thanks @simon-p-r
1.5.9
=====
* Set the global error pointer even if `return_parse_end` is passed to `cJSON_ParseWithOpts`. See #200, thanks @rmallins
1.5.8
=====
* Fix `make test` in the Makefile, thanks @YanhaoMo for reporting this (#195)
1.5.7
1.5.9 (Sep 8, 2017)
=====
Fixes:
------
* Fix a bug where realloc failing would return a pointer to an invalid memory address. This is a security issue as it could potentially be used by an attacker to write to arbitrary memory addresses. (see #189), fixed in (954d61e5e7cb9dc6c480fc28ac1cdceca07dd5bd), big thanks @timothyjohncarney for reporting this issue
* Fix a spelling mistake in the AFL fuzzer dictionary (#185), thanks @jwilk
* Set the global error pointer even if `return_parse_end` is passed to `cJSON_ParseWithOpts`, see [#200](https://github.com/DaveGamble/cJSON/pull/200), thanks @rmallins
1.5.6
1.5.8 (Aug 21, 2017)
=====
Fixes:
------
* Make cJSON a lot more tolerant about passing NULL pointers to its functions, it should now fail safely instead of dereferencing the pointer. (#183) Thanks @msichal for reporting #182
* Fix `make test` in the Makefile, thanks @YanhaoMo for reporting this [#195](https://github.com/DaveGamble/cJSON/issues/195)
1.5.5
1.5.7 (Jul 13, 2017)
=====
Fixes:
------
* Fix pointers to nested arrays in cJSON_Utils (9abe75e072050f34732a7169740989a082b65134)
* Fix an error with case sensitivity handling in cJSON_Utils (b9cc911831b0b3e1bb72f142389428e59f882b38)
* Fix cJSON_Compare for arrays that are prefixes of the other and objects that are a subset of the other (03ba72faec115160d1f3aea5582d9b6af5d3e473) See #180, thanks @zhengqb for reporting
* Fix a bug where realloc failing would return a pointer to an invalid memory address. This is a security issue as it could potentially be used by an attacker to write to arbitrary memory addresses, see [#189](https://github.com/DaveGamble/cJSON/issues/189), fixed in [954d61e](https://github.com/DaveGamble/cJSON/commit/954d61e5e7cb9dc6c480fc28ac1cdceca07dd5bd), big thanks @timothyjohncarney for reporting this issue
* Fix a spelling mistake in the AFL fuzzer dictionary, see [#185](https://github.com/DaveGamble/cJSON/pull/185), thanks @jwilk
1.5.4
1.5.6 (Jun 28, 2017)
=====
Fixes:
------
* Fix build with GCC 7.1.1 and optimization level `-O2` (bfbd8fe0d85f1dd21e508748fc10fc4c27cc51be)
* Make cJSON a lot more tolerant about passing NULL pointers to its functions, it should now fail safely instead of dereferencing the pointer, see [#183](https://github.com/DaveGamble/cJSON/pull/183). Thanks @msichal for reporting [#182](https://github.com/DaveGamble/cJSON/issues/182)
1.5.5 (Jun 15, 2017)
=====
Fixes:
------
* Fix pointers to nested arrays in cJSON_Utils, see [9abe](https://github.com/DaveGamble/cJSON/commit/9abe75e072050f34732a7169740989a082b65134)
* Fix an error with case sensitivity handling in cJSON_Utils, see [b9cc911](https://github.com/DaveGamble/cJSON/commit/b9cc911831b0b3e1bb72f142389428e59f882b38)
* Fix cJSON_Compare for arrays that are prefixes of the other and objects that are a subset of the other, see [03ba72f](https://github.com/DaveGamble/cJSON/commit/03ba72faec115160d1f3aea5582d9b6af5d3e473) and [#180](https://github.com/DaveGamble/cJSON/issues/180), thanks @zhengqb for reporting
1.5.4 (Jun 5, 2017)
======
Fixes:
------
* Fix build with GCC 7.1.1 and optimization level `-O2`, see [bfbd8fe](https://github.com/DaveGamble/cJSON/commit/bfbd8fe0d85f1dd21e508748fc10fc4c27cc51be)
Other Changes:
--------------
* Update [Unity](https://github.com/ThrowTheSwitch/Unity) to 3b69beaa58efc41bbbef70a32a46893cae02719d
1.5.3
1.5.3 (May 23, 2017)
=====
Fixes:
------
* Fix `cJSON_ReplaceItemInObject` not keeping the name of an item (#174)
* Fix `cJSON_ReplaceItemInObject` not keeping the name of an item, see [#174](https://github.com/DaveGamble/cJSON/issues/174)
1.5.2
1.5.2 (May 10, 2017)
=====
Fixes:
------
* Fix a reading buffer overflow in `parse_string` (a167d9e381e5c84bc03de4e261757b031c0c690d)
* Fix compiling with -Wcomma (186cce3ece6ce6dfcb58ac8b2a63f7846c3493ad)
* Remove leftover attribute from tests (b537ca70a35680db66f1f5b8b437f7114daa699a)
* Fix a reading buffer overflow in `parse_string`, see [a167d9e](https://github.com/DaveGamble/cJSON/commit/a167d9e381e5c84bc03de4e261757b031c0c690d)
* Fix compiling with -Wcomma, see [186cce3](https://github.com/DaveGamble/cJSON/commit/186cce3ece6ce6dfcb58ac8b2a63f7846c3493ad)
* Remove leftover attribute from tests, see [b537ca7](https://github.com/DaveGamble/cJSON/commit/b537ca70a35680db66f1f5b8b437f7114daa699a)
1.5.1
1.5.1 (May 6, 2017)
=====
Fixes:
------
* Add gcc version guard to the Makefile (#164), thanks @juvasquezg
* Fix incorrect free in `cJSON_Utils` if custom memory allocator is used (#166), thanks @prefetchnta
* Add gcc version guard to the Makefile, see [#164](https://github.com/DaveGamble/cJSON/pull/164), thanks @juvasquezg
* Fix incorrect free in `cJSON_Utils` if custom memory allocator is used, see [#166](https://github.com/DaveGamble/cJSON/pull/166), thanks @prefetchnta
1.5.0
1.5.0 (May 2, 2017)
=====
Features:
---------
* cJSON finally prints numbers without losing precision (#153) thanks @DeboraG
* `cJSON_Compare` recursively checks if two cJSON items contain the same values (#148)
* Provide case sensitive versions of every function where it matters (#158, #159)
* cJSON finally prints numbers without losing precision, see [#153](https://github.com/DaveGamble/cJSON/pull/153), thanks @DeboraG
* `cJSON_Compare` recursively checks if two cJSON items contain the same values, see [#148](https://github.com/DaveGamble/cJSON/pull/148)
* Provide case sensitive versions of every function where it matters, see [#158](https://github.com/DaveGamble/cJSON/pull/158) and [#159](https://github.com/DaveGamble/cJSON/pull/159)
* Added `cJSON_ReplaceItemViaPointer` and `cJSON_DetachItemViaPointer`
* Added `cJSON_free` and `cJSON_malloc` that expose the internal configured memory allocators. (02a05eea4e6ba41811f130b322660bea8918e1a0)
* Added `cJSON_free` and `cJSON_malloc` that expose the internal configured memory allocators. see [02a05ee](https://github.com/DaveGamble/cJSON/commit/02a05eea4e6ba41811f130b322660bea8918e1a0)
Enhancements:
@@ -149,7 +277,7 @@ Enhancements:
Fixes:
------
* Fix some warnings with the Microsoft compiler (#139) thanks @PawelWMS
* Fix some warnings with the Microsoft compiler, see [#139](https://github.com/DaveGamble/cJSON/pull/139), thanks @PawelWMS
* Fix several bugs in cJSON_Utils, mostly found with [json-patch-tests](https://github.com/json-patch/json-patch-tests)
* Prevent a stack overflow by specifying a maximum nesting depth `CJSON_NESTING_LIMIT`
@@ -157,180 +285,180 @@ Other Changes:
--------------
* Move generated files in the `library_config` subdirectory.
1.4.7
1.4.7 (Apr 19, 2017)
=====
Fixes:
------
* Fix `cJSONUtils_ApplyPatches`, it was completely broken and apparently nobody noticed (or at least reported it) (075a06f40bdc4f836c7dd7cad690d253a57cfc50)
* Fix inconsistent prototype for `cJSON_GetObjectItemCaseSensitive` (51d3df6c9f7b56b860c8fb24abe7bab255cd4fa9) thanks @PawelWMS
* Fix `cJSONUtils_ApplyPatches`, it was completely broken and apparently nobody noticed (or at least reported it), see [075a06f](https://github.com/DaveGamble/cJSON/commit/075a06f40bdc4f836c7dd7cad690d253a57cfc50)
* Fix inconsistent prototype for `cJSON_GetObjectItemCaseSensitive`, see [51d3df6](https://github.com/DaveGamble/cJSON/commit/51d3df6c9f7b56b860c8fb24abe7bab255cd4fa9), thanks @PawelWMS
1.4.6
1.4.6 (Apr 9, 2017)
=====
Fixes:
------
* Several corrections in the README
* Making clear that `valueint` should not be written to
* Fix overflow detection in `ensure` (2683d4d9873df87c4bdccc523903ddd78d1ad250)
* Fix a potential null pointer dereference in cJSON_Utils (795c3acabed25c9672006b2c0f40be8845064827)
* Replace incorrect `sizeof('\0')` with `sizeof("")` (84237ff48e69825c94261c624eb0376d0c328139)
* Add caveats section to the README (50b3c30dfa89830f8f477ce33713500740ac3b79)
* Make cJSON locale independent (#146) Thanks @peterh for reporting
* Fix compiling without CMake with MSVC (#147) Thanks @dertuxmalwieder for reporting
* Fix overflow detection in `ensure`, see [2683d4d](https://github.com/DaveGamble/cJSON/commit/2683d4d9873df87c4bdccc523903ddd78d1ad250)
* Fix a potential null pointer dereference in cJSON_Utils, see [795c3ac](https://github.com/DaveGamble/cJSON/commit/795c3acabed25c9672006b2c0f40be8845064827)
* Replace incorrect `sizeof('\0')` with `sizeof("")`, see [84237ff](https://github.com/DaveGamble/cJSON/commit/84237ff48e69825c94261c624eb0376d0c328139)
* Add caveats section to the README, see [50b3c30](https://github.com/DaveGamble/cJSON/commit/50b3c30dfa89830f8f477ce33713500740ac3b79)
* Make cJSON locale independent, see [#146](https://github.com/DaveGamble/cJSON/pull/146), Thanks @peterh for reporting
* Fix compiling without CMake with MSVC, see [#147](https://github.com/DaveGamble/cJSON/pull/147), Thanks @dertuxmalwieder for reporting
1.4.5
1.4.5 (Mar 28, 2017)
=====
Fixes:
------
* Fix bug in `cJSON_SetNumberHelper`, thanks @mmkeeper (#138 ef34500693e8c4a2849d41a4bd66fd19c9ec46c2)
* Fix bug in `cJSON_SetNumberHelper`, thanks @mmkeeper, see [#138](https://github.com/DaveGamble/cJSON/issues/138) and [ef34500](https://github.com/DaveGamble/cJSON/commit/ef34500693e8c4a2849d41a4bd66fd19c9ec46c2)
* Workaround for internal compiler error in GCC 5.4.0 and 6.3.1 on x86 (2f65e80a3471d053fdc3f8aed23d01dd1782a5cb [GCC bugreport](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80097))
1.4.4
1.4.4 (Mar 24, 2017)
=====
Fixes:
--------
* Fix a theoretical integer overflow, (not sure if it is possible on actual hardware) e58f7ec027d00b7cdcbf63e518c1b5268b29b3da
* Fix an off by one error (cc84a446be20cc283bafdc4d94c050ba1111ac02), thanks @gatzka
* Double check the offset of the print buffer in `ensure` (1934059554b9a0971e00f79e96900f422cfdd114)
------
* Fix a theoretical integer overflow, (not sure if it is possible on actual hardware), see [e58f7ec](https://github.com/DaveGamble/cJSON/commit/e58f7ec027d00b7cdcbf63e518c1b5268b29b3da)
* Fix an off by one error, see [cc84a44](https://github.com/DaveGamble/cJSON/commit/cc84a446be20cc283bafdc4d94c050ba1111ac02), thanks @gatzka
* Double check the offset of the print buffer in `ensure`, see [1934059](https://github.com/DaveGamble/cJSON/commit/1934059554b9a0971e00f79e96900f422cfdd114)
Improvements:
-------------
* Add a note in the header about required buffer size when using `cJSON_PrintPreallocated` (4bfb88009342fb568295a7f6dc4b7fee74fbf022)
* Add a note in the header about required buffer size when using `cJSON_PrintPreallocated`, see [4bfb8800](https://github.com/DaveGamble/cJSON/commit/4bfb88009342fb568295a7f6dc4b7fee74fbf022)
1.4.3
1.4.3 (Mar 19, 2017)
=====
Fixes:
------
* Fix compilation of the tests on 32 bit PowerPC and potentially other systems (4ec6e76ea2eec16f54b58e8c95b4c734e59481e4)
* Fix compilation with old GCC compilers (4.3+ were tested) (227d3398d6b967879761ebe02c1b63dbd6ea6e0d, 466eb8e3f8a65080f2b3ca4a79ab7b72bd539dba), see also #126
* Fix compilation of the tests on 32 bit PowerPC and potentially other systems, see [4ec6e76](https://github.com/DaveGamble/cJSON/commit/4ec6e76ea2eec16f54b58e8c95b4c734e59481e4)
* Fix compilation with old GCC compilers (4.3+ were tested), see [227d33](https://github.com/DaveGamble/cJSON/commit/227d3398d6b967879761ebe02c1b63dbd6ea6e0d), [466eb8e](https://github.com/DaveGamble/cJSON/commit/466eb8e3f8a65080f2b3ca4a79ab7b72bd539dba), see also [#126](https://github.com/DaveGamble/cJSON/issues/126)
1.4.2
1.4.2 (Mar 16, 2017)
=====
Fixes:
------
* Fix minimum required cmake version (30e1e7af7c63db9b55f5a3cda977a6c032f0b132)
* Fix detection of supported compiler flags (76e5296d0d05ceb3018a9901639e0e171b44a557)
* Run `cJSON_test` and `cJSON_test_utils` along with unity tests (c597601cf151a757dcf800548f18034d4ddfe2cb)
* Fix minimum required cmake version, see [30e1e7a](https://github.com/DaveGamble/cJSON/commit/30e1e7af7c63db9b55f5a3cda977a6c032f0b132)
* Fix detection of supported compiler flags, see [76e5296](https://github.com/DaveGamble/cJSON/commit/76e5296d0d05ceb3018a9901639e0e171b44a557)
* Run `cJSON_test` and `cJSON_test_utils` along with unity tests, see [c597601](https://github.com/DaveGamble/cJSON/commit/c597601cf151a757dcf800548f18034d4ddfe2cb)
1.4.1
1.4.1 (Mar 16, 2017)
=====
Fix: Make `print_number` abort with a failure in out of memory situations (cf1842dc6f64c49451a022308b4415e4d468be0a)
Fixes:
------
* Make `print_number` abort with a failure in out of memory situations, see [cf1842](https://github.com/DaveGamble/cJSON/commit/cf1842dc6f64c49451a022308b4415e4d468be0a)
1.4.0
1.4.0 (Mar 4, 2017)
=====
Features
--------
* Functions to check the type of an item (#120)
* Use dllexport on windows and fvisibility on Unix systems for public functions (#116), thanks @mjerris
* Remove trailing zeroes from printed numbers (#123)
* Expose the internal boolean type `cJSON_bool` in the header (2d3520e0b9d0eb870e8886e8a21c571eeddbb310)
* Functions to check the type of an item, see [#120](https://github.com/DaveGamble/cJSON/pull/120)
* Use dllexport on windows and fvisibility on Unix systems for public functions, see [#116](https://github.com/DaveGamble/cJSON/pull/116), thanks @mjerris
* Remove trailing zeroes from printed numbers, see [#123](https://github.com/DaveGamble/cJSON/pull/123)
* Expose the internal boolean type `cJSON_bool` in the header, see [2d3520e](https://github.com/DaveGamble/cJSON/commit/2d3520e0b9d0eb870e8886e8a21c571eeddbb310)
Fixes
-----
* Fix handling of NULL pointers in `cJSON_ArrayForEach` (b47d0e34caaef298edfb7bd09a72cfff21d231ff)
* Make it compile with GCC 7 (fix -Wimplicit-fallthrough warning) (9d07917feb1b613544a7513d19233d4c851ad7ad)
* Fix handling of NULL pointers in `cJSON_ArrayForEach`, see [b47d0e3](https://github.com/DaveGamble/cJSON/commit/b47d0e34caaef298edfb7bd09a72cfff21d231ff)
* Make it compile with GCC 7 (fix -Wimplicit-fallthrough warning), see [9d07917](https://github.com/DaveGamble/cJSON/commit/9d07917feb1b613544a7513d19233d4c851ad7ad)
Other Improvements
------------------
* internally use realloc if available (#110)
* builtin support for fuzzing with [afl](http://lcamtuf.coredump.cx/afl/) (#111)
* unit tests for the print functions (#112)
* Always use buffered printing (#113)
* simplify the print functions (#114)
* Add the compiler flags `-Wdouble-conversion`, `-Wparentheses` and `-Wcomma` (#122)
* internally use realloc if available ([#110](https://github.com/DaveGamble/cJSON/pull/110))
* builtin support for fuzzing with [afl](http://lcamtuf.coredump.cx/afl/) ([#111](https://github.com/DaveGamble/cJSON/pull/111))
* unit tests for the print functions ([#112](https://github.com/DaveGamble/cJSON/pull/112))
* Always use buffered printing ([#113](https://github.com/DaveGamble/cJSON/pull/113))
* simplify the print functions ([#114](https://github.com/DaveGamble/cJSON/pull/114))
* Add the compiler flags `-Wdouble-conversion`, `-Wparentheses` and `-Wcomma` ([#122](https://github.com/DaveGamble/cJSON/pull/122))
1.3.2
1.3.2 (Mar 1, 2017)
=====
Fix:
----
- Don't build the unity library if testing is disabled ( #121 ). Thanks @ffontaine
Fixes:
------
* Don't build the unity library if testing is disabled, see [#121](https://github.com/DaveGamble/cJSON/pull/121). Thanks @ffontaine
1.3.1
1.3.1 (Feb 27, 2017)
=====
Bugfix release that fixes an out of bounds read #118. This shouldn't have any security implications.
Fixes:
------
* Bugfix release that fixes an out of bounds read, see [#118](https://github.com/DaveGamble/cJSON/pull/118). This shouldn't have any security implications.
1.3.0
1.3.0 (Feb 17, 2017)
=====
This release includes a lot of rework in the parser and includes the Cunity unit testing framework, as well as some fixes. I increased the minor version number because there were quite a lot of internal changes.
Features:
---------
- New type for cJSON structs: `cJSON_Invalid` (#108)
* New type for cJSON structs: `cJSON_Invalid`, see [#108](https://github.com/DaveGamble/cJSON/pull/108)
Fixes:
------
- runtime checks for a lot of potential integer overflows
- fix incorrect return in cJSON_PrintBuffered (cf9d57d56cac21fc59465b8d26cf29bf6d2a87b3)
- fix several potential issues found by [Coverity](https://scan.coverity.com/projects/cjson)
- fix potentially undefined behavior when assigning big numbers to `valueint` (41e2837df1b1091643aff073f2313f6ff3cc10f4)
- Numbers exceeding `INT_MAX` or lower than `INT_MIN` will be explicitly assigned to `valueint` as `INT_MAX` and `INT_MIN` respectively (saturation on overflow).
- fix the `cJSON_SetNumberValue` macro (87f77274de6b3af00fb9b9a7f3b900ef382296c2), this slightly changes the behavior, see commit message
* runtime checks for a lot of potential integer overflows
* fix incorrect return in cJSON_PrintBuffered [cf9d57d](https://github.com/DaveGamble/cJSON/commit/cf9d57d56cac21fc59465b8d26cf29bf6d2a87b3)
* fix several potential issues found by [Coverity](https://scan.coverity.com/projects/cjson)
* fix potentially undefined behavior when assigning big numbers to `valueint` ([41e2837](https://github.com/DaveGamble/cJSON/commit/41e2837df1b1091643aff073f2313f6ff3cc10f4))
* Numbers exceeding `INT_MAX` or lower than `INT_MIN` will be explicitly assigned to `valueint` as `INT_MAX` and `INT_MIN` respectively (saturation on overflow).
* fix the `cJSON_SetNumberValue` macro ([87f7727](https://github.com/DaveGamble/cJSON/commit/87f77274de6b3af00fb9b9a7f3b900ef382296c2)), this slightly changes the behavior, see commit message
Introduce unit tests
--------------------
Started writing unit tests with the [Cunity](https://github.com/ThrowTheSwitch/Unity) testing framework. Currently this covers the parser functions.
* Started writing unit tests with the [Cunity](https://github.com/ThrowTheSwitch/Unity) testing framework. Currently this covers the parser functions.
Also:
- Support for running the tests with [Valgrind](http://valgrind.org)
- Support for compiling the tests with [AddressSanitizer](https://github.com/google/sanitizers) and [UndefinedBehaviorSanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html).
- `travis.yml` file for running unit tests on travis. (not enabled for the repository yet though #102)
* Support for running the tests with [Valgrind](http://valgrind.org)
* Support for compiling the tests with [AddressSanitizer](https://github.com/google/sanitizers) and [UndefinedBehaviorSanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html).
* `travis.yml` file for running unit tests on travis. (not enabled for the repository yet though [#102](https://github.com/DaveGamble/cJSON/issues/102)
Simplifications
---------------
After having unit tests for the parser function in place, I started refactoring the parser functions (as well as others) and making them easier to read and maintain.
- Use `strtod` from the standard library for parsing numbers (074766997246481dfc72bfa78f07898a2716473f)
- Use goto-fail in several parser functions (#100)
- Rewrite/restructure all of the parsing functions to be easier to understand and have less code paths doing the same as another. (#109)
- Simplify the buffer allocation strategy to always doubling the needed amount (9f6fa94c91a87b71e4c6868dbf2ce431a48517b0)
- Combined `cJSON_AddItemToObject` and `cJSON_AddItemToObjectCS` to one function (cf862d0fed7f9407e4b046d78d3d8050d2080d12)
* Use `strtod` from the standard library for parsing numbers ([0747669](https://github.com/DaveGamble/cJSON/commit/074766997246481dfc72bfa78f07898a2716473f))
* Use goto-fail in several parser functions ([#100](https://github.com/DaveGamble/cJSON/pull/100))
* Rewrite/restructure all of the parsing functions to be easier to understand and have less code paths doing the same as another. ([#109](https://github.com/DaveGamble/cJSON/pull/109))
* Simplify the buffer allocation strategy to always doubling the needed amount ([9f6fa94](https://github.com/DaveGamble/cJSON/commit/9f6fa94c91a87b71e4c6868dbf2ce431a48517b0))
* Combined `cJSON_AddItemToObject` and `cJSON_AddItemToObjectCS` to one function ([cf862d](https://github.com/DaveGamble/cJSON/commit/cf862d0fed7f9407e4b046d78d3d8050d2080d12))
Other changes
-------------
- Prevent the usage of incompatible C and header versions via preprocessor directive (123bb1af7bfae41d805337fef4b41045ef6c7d25)
- Let CMake automatically detect compiler flags
- Add new compiler flags (`-Wundef`, `-Wswitch-default`, `-Wconversion`, `-fstack-protector-strong`) (#98)
- Change internal sizes from `int` to `size_t` (ecd5678527a6bc422da694e5be9e9979878fe6a0)
- Change internal strings from `char*` to `unsigned char*` (28b9ba4334e0f7309e867e874a31f395c0ac2474)
- Add `const` in more places
* Prevent the usage of incompatible C and header versions via preprocessor directive ([123bb1](https://github.com/DaveGamble/cJSON/commit/123bb1af7bfae41d805337fef4b41045ef6c7d25))
* Let CMake automatically detect compiler flags
* Add new compiler flags (`-Wundef`, `-Wswitch-default`, `-Wconversion`, `-fstack-protector-strong`) ([#98](https://github.com/DaveGamble/cJSON/pull/98))
* Change internal sizes from `int` to `size_t` ([ecd5678](https://github.com/DaveGamble/cJSON/commit/ecd5678527a6bc422da694e5be9e9979878fe6a0))
* Change internal strings from `char*` to `unsigned char*` ([28b9ba4](https://github.com/DaveGamble/cJSON/commit/28b9ba4334e0f7309e867e874a31f395c0ac2474))
* Add `const` in more places
1.2.1
1.2.1 (Jan 31, 2017)
=====
Fixes:
------
- Fixes a potential null pointer dereference in cJSON_Utils, discovered using clang's static analyzer by @bnason-nf (#96)
* Fixes a potential null pointer dereference in cJSON_Utils, discovered using clang's static analyzer by @bnason-nf, see [#96](https://github.com/DaveGamble/cJSON/issues/96)
1.2.0
1.2.0 (Jan 9, 2017)
=====
Features:
---------
- Add a new type of cJSON item for raw JSON and support printing it. Thanks @loigu (#65, #90)
* Add a new type of cJSON item for raw JSON and support printing it. Thanks @loigu, see [#65](https://github.com/DaveGamble/cJSON/pull/65), [#90](https://github.com/DaveGamble/cJSON/pull/90)
Fixes:
------
- Compiler warning if const is casted away, Thanks @gatzka (#83)
- Fix compile error with strict-overflow on PowerPC, (#85)
- Fix typo in the README, thanks @MicroJoe (#88)
- Add compile flag for compatibility with C++ compilers
* Compiler warning if const is casted away, Thanks @gatzka, see [#83](https://github.com/DaveGamble/cJSON/pull/83)
* Fix compile error with strict-overflow on PowerPC, see [#85](https://github.com/DaveGamble/cJSON/issues/85)
* Fix typo in the README, thanks @MicroJoe, see [#88](https://github.com/DaveGamble/cJSON/pull/88)
* Add compile flag for compatibility with C++ compilers
1.1.0
1.1.0 (Dec 6, 2016)
=====
- Add a function `cJSON_PrintPreallocated` to print to a preallocated buffer, thanks @ChisholmKyle (#72)
- More compiler warnings when using Clang or GCC, thanks @gatzka (#75, #78)
- fixed a memory leak in `cJSON_Duplicate`, thanks @alperakcan (#81)
- fix the `ENABLE_CUSTOM_COMPILER_FLAGS` cmake option
* Add a function `cJSON_PrintPreallocated` to print to a preallocated buffer, thanks @ChisholmKyle, see [#72](https://github.com/DaveGamble/cJSON/pull/72)
* More compiler warnings when using Clang or GCC, thanks @gatzka, see [#75](https://github.com/DaveGamble/cJSON/pull/75), [#78](https://github.com/DaveGamble/cJSON/pull/78)
* fixed a memory leak in `cJSON_Duplicate`, thanks @alperakcan, see [#81](https://github.com/DaveGamble/cJSON/pull/81)
* fix the `ENABLE_CUSTOM_COMPILER_FLAGS` cmake option
1.0.2
1.0.2 (Nov 25, 2016)
=====
Rename internal boolean type, see #71.
* Rename internal boolean type, see [#71](https://github.com/DaveGamble/cJSON/issues/71).
1.0.1
1.0.1 (Nov 20, 2016)
=====
Small bugfix release.
- Fixes a bug with the use of the cJSON structs type in cJSON_Utils, see d47339e2740360e6e0994527d5e4752007480f3a
- improve code readability
- initialize all variables
* Fixes a bug with the use of the cJSON structs type in cJSON_Utils, see [d47339e](https://github.com/DaveGamble/cJSON/commit/d47339e2740360e6e0994527d5e4752007480f3a)
* improve code readability
* initialize all variables
1.0.0
1.0.0 (Nov 17, 2016)
=====
This is the first official versioned release of cJSON. It provides an API version for the shared library and improved Makefile and CMake build files.

View File

@@ -1,17 +1,16 @@
set(CMAKE_LEGACY_CYGWIN_WIN32 0)
cmake_minimum_required(VERSION 2.8.5)
cmake_minimum_required(VERSION 3.0)
project(cJSON C)
project(cJSON
VERSION 1.7.18
LANGUAGES C)
cmake_policy(SET CMP0054 NEW) # set CMP0054 policy
include(GNUInstallDirs)
set(PROJECT_VERSION_MAJOR 1)
set(PROJECT_VERSION_MINOR 7)
set(PROJECT_VERSION_PATCH 5)
set(CJSON_VERSION_SO 1)
set(CJSON_UTILS_VERSION_SO 1)
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
set(custom_compiler_flags)
@@ -49,11 +48,15 @@ if (ENABLE_CUSTOM_COMPILER_FLAGS)
-Wswitch-enum
)
elseif("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
# Disable warning c4001 - nonstandard extension 'single line comment' was used
# Define _CRT_SECURE_NO_WARNINGS to disable deprecation warnings for "insecure" C library functions
list(APPEND custom_compiler_flags
/GS
/Za
/sdl
/W4
/wd4001
/D_CRT_SECURE_NO_WARNINGS
)
endif()
endif()
@@ -64,11 +67,9 @@ if (ENABLE_SANITIZERS)
-fno-omit-frame-pointer
-fsanitize=address
-fsanitize=undefined
-fsanitize=float-divide-by-zero
-fsanitize=float-cast-overflow
-fsanitize-address-use-after-scope
-fsanitize=integer
-01
-fno-sanitize-recover
)
endif()
@@ -100,13 +101,10 @@ foreach(compiler_flag ${custom_compiler_flags})
CHECK_C_COMPILER_FLAG(${compiler_flag} "FLAG_SUPPORTED_${current_variable}")
if (FLAG_SUPPORTED_${current_variable})
list(APPEND supported_compiler_flags)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${compiler_flag}")
endif()
endforeach()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${supported_compiler_flags}")
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
option(ENABLE_TARGET_EXPORT "Enable exporting of CMake targets. Disable when it causes problems!" ON)
@@ -119,6 +117,7 @@ set(SOURCES cJSON.c)
option(BUILD_SHARED_AND_STATIC_LIBS "Build both shared and static libraries" Off)
option(CJSON_OVERRIDE_BUILD_SHARED_LIBS "Override BUILD_SHARED_LIBS with CJSON_BUILD_SHARED_LIBS" OFF)
option(CJSON_BUILD_SHARED_LIBS "Overrides BUILD_SHARED_LIBS if CJSON_OVERRIDE_BUILD_SHARED_LIBS is enabled" ON)
option(ENABLE_CJSON_VERSION_SO "Enables cJSON so version" ON)
if ((CJSON_OVERRIDE_BUILD_SHARED_LIBS AND CJSON_BUILD_SHARED_LIBS) OR ((NOT CJSON_OVERRIDE_BUILD_SHARED_LIBS) AND BUILD_SHARED_LIBS))
set(CJSON_LIBRARY_TYPE SHARED)
@@ -145,19 +144,31 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/library_config/libcjson.pc.in"
install(FILES cJSON.h DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/cjson")
install (FILES "${CMAKE_CURRENT_BINARY_DIR}/libcjson.pc" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig")
install(TARGETS "${CJSON_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}" EXPORT "${CJSON_LIB}")
install(TARGETS "${CJSON_LIB}"
EXPORT "${CJSON_LIB}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}"
RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}"
INCLUDES DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}"
)
if (BUILD_SHARED_AND_STATIC_LIBS)
install(TARGETS "${CJSON_LIB}-static" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}")
install(TARGETS "${CJSON_LIB}-static"
EXPORT "${CJSON_LIB}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}"
INCLUDES DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}"
)
endif()
if(ENABLE_TARGET_EXPORT)
# export library information for CMake projects
install(EXPORT "${CJSON_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON")
endif()
if(ENABLE_CJSON_VERSION_SO)
set_target_properties("${CJSON_LIB}"
PROPERTIES
SOVERSION "${CJSON_VERSION_SO}"
VERSION "${PROJECT_VERSION}")
endif()
#cJSON_Utils
option(ENABLE_CJSON_UTILS "Enable building the cJSON_Utils library." OFF)
@@ -182,9 +193,19 @@ if(ENABLE_CJSON_UTILS)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/library_config/libcjson_utils.pc.in"
"${CMAKE_CURRENT_BINARY_DIR}/libcjson_utils.pc" @ONLY)
install(TARGETS "${CJSON_UTILS_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}" EXPORT "${CJSON_UTILS_LIB}")
install(TARGETS "${CJSON_UTILS_LIB}"
EXPORT "${CJSON_UTILS_LIB}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}"
RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}"
INCLUDES DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}"
)
if (BUILD_SHARED_AND_STATIC_LIBS)
install(TARGETS "${CJSON_UTILS_LIB}-static" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}")
install(TARGETS "${CJSON_UTILS_LIB}-static"
EXPORT "${CJSON_UTILS_LIB}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}"
INCLUDES DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}"
)
endif()
install(FILES cJSON_Utils.h DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/cjson")
install (FILES "${CMAKE_CURRENT_BINARY_DIR}/libcjson_utils.pc" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig")
@@ -193,11 +214,13 @@ if(ENABLE_CJSON_UTILS)
install(EXPORT "${CJSON_UTILS_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON")
endif()
if(ENABLE_CJSON_VERSION_SO)
set_target_properties("${CJSON_UTILS_LIB}"
PROPERTIES
SOVERSION "${CJSON_UTILS_VERSION_SO}"
VERSION "${PROJECT_VERSION}")
endif()
endif()
# create the other package config files
configure_file(
@@ -207,10 +230,12 @@ configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/library_config/cJSONConfigVersion.cmake.in"
${PROJECT_BINARY_DIR}/cJSONConfigVersion.cmake @ONLY)
if(ENABLE_TARGET_EXPORT)
# Install package config files
install(FILES ${PROJECT_BINARY_DIR}/cJSONConfig.cmake
${PROJECT_BINARY_DIR}/cJSONConfigVersion.cmake
DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON")
endif()
option(ENABLE_CJSON_TEST "Enable building cJSON test" ON)
if(ENABLE_CJSON_TEST)
@@ -237,6 +262,13 @@ if(ENABLE_CJSON_TEST)
DEPENDS ${TEST_CJSON})
endif()
#Create the uninstall target
option(ENABLE_CJSON_UNINSTALL "Enable creating uninstall target" ON)
if(ENABLE_CJSON_UNINSTALL)
add_custom_target(uninstall "${CMAKE_COMMAND}" -P
"${PROJECT_SOURCE_DIR}/library_config/uninstall.cmake")
endif()
# Enable the use of locales
option(ENABLE_LOCALES "Enable the use of locales" ON)
if(ENABLE_LOCALES)

View File

@@ -1,46 +1,93 @@
Contributors
============
Original Author: [Dave Gamble](https://github.com/DaveGamble)
Current Maintainer: [Max Bruckner](https://github.com/FSMaxB)
Original Author:
- [Dave Gamble](https://github.com/DaveGamble)
Current Maintainer:
- [Max Bruckner](https://github.com/FSMaxB)
- [Alan Wang](https://github.com/Alanscut)
Contributors:
* [Ajay Bhargav](https://github.com/ajaybhargav)
* [AlexanderVasiljev](https://github.com/AlexanderVasiljev)
* [Alper Akcan](https://github.com/alperakcan)
* [Andrew Tang](https://github.com/singku)
* [Andy](https://github.com/mlh0101)
* [Anton Sergeev](https://github.com/anton-sergeev)
* [Benbuck Nason](https://github.com/bnason-nf)
* [Bernt Johan Damslora](https://github.com/bjda)
* [Bob Kocisko](https://github.com/bobkocisko)
* [Christian Schulze](https://github.com/ChristianSch)
* [Casperinous](https://github.com/Casperinous)
* [ChenYuan](https://github.com/zjuchenyuan)
* [Debora Grosse](https://github.com/DeboraG)
* [dieyushi](https://github.com/dieyushi)
* [Dōngwén Huáng (黄东文)](https://github.com/DongwenHuang)
* [Donough Liu](https://github.com/ldm0)
* [Erez Oxman](https://github.com/erez-o)
* Eswar Yaganti
* [Evan Todd](https://github.com/etodd)
* [Fabrice Fontaine](https://github.com/ffontaine)
* Ian Mobley
* Irwan Djadjadi
* [hopper-vul](https://github.com/hopper-vul)
* [HuKeping](https://github.com/HuKeping)
* [IvanVoid](https://github.com/npi3pak)
* [Jakub Wilk](https://github.com/jwilk)
* [Jiri Zouhar](https://github.com/loigu)
* [Jonathan Fether](https://github.com/jfether)
* [Joshua Arulsamy](https://github.com/jarulsamy)
* [Julian Ste](https://github.com/julian-st)
* [Julián Vásquez](https://github.com/juvasquezg)
* [Junbo Zheng](https://github.com/Junbo-Zheng)
* [Kevin Branigan](https://github.com/kbranigan)
* [Kevin Sapper](https://github.com/sappo)
* [Kyle Chisholm](https://github.com/ChisholmKyle)
* [Linus Wallgren](https://github.com/ecksun)
* [Luo Jin](https://github.com/Up-wind)
* [Max](https://github.com/maebex)
* [MaxBrandtner](https://github.com/MaxBrandtner)
* [Mateusz Szafoni](https://github.com/raiden00pl)
* Mike Pontillo
* [miaoerduo](https://github.com/miaoerduo)
* [mohawk2](https://github.com/mohawk2)
* [Mike Jerris](https://github.com/mjerris)
* [Mike Robinson](https://github.com/mhrobinson)
* [Moorthy](https://github.com/moorthy-bs)
* [myd7349](https://github.com/myd7349)
* [NancyLi1013](https://github.com/NancyLi1013)
* [Orri](https://github.com/sbvoxel)
* Paulo Antonio Alvarez
* [Paweł Malowany](https://github.com/PawelMalowany)
* [Pawel Winogrodzki](https://github.com/PawelWMS)
* [prefetchnta](https://github.com/prefetchnta)
* [Rafael Leal Dias](https://github.com/rafaeldias)
* [Randy](https://github.com/randy408)
* [raiden00pl](https://github.com/raiden00pl)
* [Robin Mallinson](https://github.com/rmallins)
* [Rod Vagg](https://github.com/rvagg)
* [Roland Meertens](https://github.com/rmeertens)
* [Romain Porte](https://github.com/MicroJoe)
* [SANJEEV BA](https://github.com/basanjeev)
* [Sang-Heon Jeon](https://github.com/lntuition)
* [Sayan Bandyopadhyay](https://github.com/saynb)
* [Simon Sobisch](https://github.com/GitMensch)
* [Simon Ricaldone](https://github.com/simon-p-r)
* [Stoian Ivanov](https://github.com/sdrsdr)
* [SuperH-0630](https://github.com/SuperH-0630)
* [Square789](https://github.com/Square789)
* [Stephan Gatzka](https://github.com/gatzka)
* [Tony Langhammer](https://github.com/BigBrainAFK)
* [Vemake](https://github.com/vemakereporter)
* [Wei Tan](https://github.com/tan-wei)
* [Weston Schmidt](https://github.com/schmidtw)
* [xiaomianhehe](https://github.com/xiaomianhehe)
* [yangfl](https://github.com/yangfl)
* [yuta-oxo](https://github.com/yuta-oxo)
* [Zach Hindes](https://github.com/zhindes)
* [Zhao Zhixu](https://github.com/zhaozhixu)
* [10km](https://github.com/10km)
And probably more people on [SourceForge](https://sourceforge.net/p/cjson/bugs/search/?q=status%3Aclosed-rejected+or+status%3Aclosed-out-of-date+or+status%3Awont-fix+or+status%3Aclosed-fixed+or+status%3Aclosed&page=0)

View File

@@ -8,10 +8,13 @@ CJSON_TEST_SRC = cJSON.c test.c
LDLIBS = -lm
LIBVERSION = 1.7.5
LIBVERSION = 1.7.18
CJSON_SOVERSION = 1
UTILS_SOVERSION = 1
CJSON_SO_LDFLAG=-Wl,-soname=$(CJSON_LIBNAME).so.$(CJSON_SOVERSION)
UTILS_SO_LDFLAG=-Wl,-soname=$(UTILS_LIBNAME).so.$(UTILS_SOVERSION)
PREFIX ?= /usr/local
INCLUDE_PATH ?= include/cjson
LIBRARY_PATH ?= lib
@@ -21,9 +24,11 @@ INSTALL_LIBRARY_PATH = $(DESTDIR)$(PREFIX)/$(LIBRARY_PATH)
INSTALL ?= cp -a
CC = gcc -std=c89
# validate gcc version for use fstack-protector-strong
MIN_GCC_VERSION = "4.9"
GCC_VERSION := "`gcc -dumpversion`"
GCC_VERSION := "`$(CC) -dumpversion`"
IS_GCC_ABOVE_MIN_VERSION := $(shell expr "$(GCC_VERSION)" ">=" "$(MIN_GCC_VERSION)")
ifeq "$(IS_GCC_ABOVE_MIN_VERSION)" "1"
CFLAGS += -fstack-protector-strong
@@ -31,7 +36,8 @@ else
CFLAGS += -fstack-protector
endif
R_CFLAGS = -fPIC -std=c89 -pedantic -Wall -Werror -Wstrict-prototypes -Wwrite-strings -Wshadow -Winit-self -Wcast-align -Wformat=2 -Wmissing-prototypes -Wstrict-overflow=2 -Wcast-qual -Wc++-compat -Wundef -Wswitch-default -Wconversion $(CFLAGS)
PIC_FLAGS = -fPIC
R_CFLAGS = $(PIC_FLAGS) -pedantic -Wall -Werror -Wstrict-prototypes -Wwrite-strings -Wshadow -Winit-self -Wcast-align -Wformat=2 -Wmissing-prototypes -Wstrict-overflow=2 -Wcast-qual -Wc++-compat -Wundef -Wswitch-default -Wconversion $(CFLAGS)
uname := $(shell sh -c 'uname -s 2>/dev/null || echo false')
@@ -42,6 +48,8 @@ STATIC = a
## create dynamic (shared) library on Darwin (base OS for MacOSX and IOS)
ifeq (Darwin, $(uname))
SHARED = dylib
CJSON_SO_LDFLAG = ""
UTILS_SO_LDFLAG = ""
endif
#cJSON library names
@@ -90,16 +98,16 @@ $(UTILS_STATIC): $(UTILS_OBJ)
#shared libraries .so.1.0.0
#cJSON
$(CJSON_SHARED_VERSION): $(CJSON_OBJ)
$(CC) -shared -o $@ $< $(LDFLAGS)
$(CC) -shared -o $@ $< $(CJSON_SO_LDFLAG) $(LDFLAGS)
#cJSON_Utils
$(UTILS_SHARED_VERSION): $(UTILS_OBJ)
$(CC) -shared -o $@ $< $(LDFLAGS)
$(CC) -shared -o $@ $< $(CJSON_OBJ) $(UTILS_SO_LDFLAG) $(LDFLAGS)
#objects
#cJSON
$(CJSON_OBJ): cJSON.c cJSON.h
#cJSON_Utils
$(UTILS_OBJ): cJSON_Utils.c cJSON_Utils.h
$(UTILS_OBJ): cJSON_Utils.c cJSON_Utils.h cJSON.h
#links .so -> .so.1 -> .so.1.0.0
@@ -133,9 +141,8 @@ uninstall-cjson: uninstall-utils
$(RM) $(INSTALL_LIBRARY_PATH)/$(CJSON_SHARED)
$(RM) $(INSTALL_LIBRARY_PATH)/$(CJSON_SHARED_VERSION)
$(RM) $(INSTALL_LIBRARY_PATH)/$(CJSON_SHARED_SO)
rmdir $(INSTALL_LIBRARY_PATH)
$(RM) $(INSTALL_INCLUDE_PATH)/cJSON.h
rmdir $(INSTALL_INCLUDE_PATH)
#cJSON_Utils
uninstall-utils:
$(RM) $(INSTALL_LIBRARY_PATH)/$(UTILS_SHARED)
@@ -143,7 +150,11 @@ uninstall-utils:
$(RM) $(INSTALL_LIBRARY_PATH)/$(UTILS_SHARED_SO)
$(RM) $(INSTALL_INCLUDE_PATH)/cJSON_Utils.h
uninstall: uninstall-utils uninstall-cjson
remove-dir:
$(if $(wildcard $(INSTALL_LIBRARY_PATH)/*.*),,rmdir $(INSTALL_LIBRARY_PATH))
$(if $(wildcard $(INSTALL_INCLUDE_PATH)/*.*),,rmdir $(INSTALL_INCLUDE_PATH))
uninstall: uninstall-utils uninstall-cjson remove-dir
clean:
$(RM) $(CJSON_OBJ) $(UTILS_OBJ) #delete object files

View File

@@ -10,6 +10,8 @@ Ultralightweight JSON parser in ANSI C.
* [Copying the source](#copying-the-source)
* [CMake](#cmake)
* [Makefile](#makefile)
* [Meson](#meson)
* [Vcpkg](#Vcpkg)
* [Including cJSON](#including-cjson)
* [Data Structure](#data-structure)
* [Working with the data structure](#working-with-the-data-structure)
@@ -80,11 +82,13 @@ philosophy as JSON itself. Simple, dumb, out of the way.
There are several ways to incorporate cJSON into your project.
#### copying the source
Because the entire library is only one C file and one header file, you can just copy `cJSON.h` and `cJSON.c` to your projects source and start using it.
cJSON is written in ANSI C (C89) in order to support as many platforms and compilers as possible.
#### CMake
With CMake, cJSON supports a full blown build system. This way you get the most features. CMake with an equal or higher version than 2.8.5 is supported. With CMake it is recommended to do an out of tree build, meaning the compiled files are put in a directory separate from the source files. So in order to build cJSON with CMake on a Unix platform, make a `build` directory and run CMake inside it.
```
@@ -102,6 +106,7 @@ make
And install it with `make install` if you want. By default it installs the headers `/usr/local/include/cjson` and the libraries to `/usr/local/lib`. It also installs files for pkg-config to make it easier to detect and use an existing installation of CMake. And it installs CMake config files, that can be used by other CMake based projects to discover the library.
You can change the build process with a list of different options that you can pass to CMake. Turn them on with `On` and off with `Off`:
* `-DENABLE_CJSON_TEST=On`: Enable building the tests. (on by default)
* `-DENABLE_CJSON_UTILS=On`: Enable building cJSON_Utils. (off by default)
* `-DENABLE_TARGET_EXPORT=On`: Enable the export of CMake targets. Turn off if it makes problems. (on by default)
@@ -114,6 +119,7 @@ You can change the build process with a list of different options that you can p
* `-DCMAKE_INSTALL_PREFIX=/usr`: Set a prefix for the installation.
* `-DENABLE_LOCALES=On`: Enable the usage of localeconv method. ( on by default )
* `-DCJSON_OVERRIDE_BUILD_SHARED_LIBS=On`: Enable overriding the value of `BUILD_SHARED_LIBS` with `-DCJSON_BUILD_SHARED_LIBS`.
* `-DENABLE_CJSON_VERSION_SO`: Enable cJSON so version. ( on by default )
If you are packaging cJSON for a distribution of Linux, you would probably take these steps for example:
```
@@ -127,17 +133,51 @@ make DESTDIR=$pkgdir install
On Windows CMake is usually used to create a Visual Studio solution file by running it inside the Developer Command Prompt for Visual Studio, for exact steps follow the official documentation from CMake and Microsoft and use the online search engine of your choice. The descriptions of the the options above still generally apply, although not all of them work on Windows.
#### Makefile
**NOTE:** This Method is deprecated. Use CMake if at all possible. Makefile support is limited to fixing bugs.
If you don't have CMake available, but still have GNU make. You can use the makefile to build cJSON:
Run this command in the directory with the source code and it will automatically compile static and shared libraries and a little test program.
Run this command in the directory with the source code and it will automatically compile static and shared libraries and a little test program (not the full test suite).
```
make all
```
If you want, you can install the compiled library to your system using `make install`. By default it will install the headers in `/usr/local/include/cjson` and the libraries in `/usr/local/lib`. But you can change this behavior by setting the `PREFIX` and `DESTDIR` variables: `make PREFIX=/usr DESTDIR=temp install`.
If you want, you can install the compiled library to your system using `make install`. By default it will install the headers in `/usr/local/include/cjson` and the libraries in `/usr/local/lib`. But you can change this behavior by setting the `PREFIX` and `DESTDIR` variables: `make PREFIX=/usr DESTDIR=temp install`. And uninstall them with: `make PREFIX=/usr DESTDIR=temp uninstall`.
#### Meson
To make cjson work in a project using meson, the libcjson dependency has to be included:
```meson
project('c-json-example', 'c')
cjson = dependency('libcjson')
example = executable(
'example',
'example.c',
dependencies: [cjson],
)
```
#### Vcpkg
You can download and install cJSON using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
```
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
vcpkg install cjson
```
The cJSON 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.
### Including cJSON
If you installed it via CMake or the Makefile, you can include cJSON like this:
```c
@@ -169,18 +209,20 @@ An item of this type represents a JSON value. The type is stored in `type` as a
To check the type of an item, use the corresponding `cJSON_Is...` function. It does a `NULL` check followed by a type check and returns a boolean value if the item is of this type.
The type can be one of the following:
* `cJSON_Invalid` (check with `cJSON_IsInvalid`): Represents an invalid item that doesn't contain any value. You automatically have this type if you set the item to all zero bytes.
* `cJSON_False` (check with `cJSON_IsFalse`): Represents a `false` boolean value. You can also check for boolean values in general with `cJSON_IsBool`.
* `cJSON_True` (check with `cJSON_IsTrue`): Represents a `true` boolean value. You can also check for boolean values in general with `cJSON_IsBool`.
* `cJSON_NULL` (check with `cJSON_IsNull`): Represents a `null` value.
* `cJSON_Number` (check with `cJSON_IsNumber`): Represents a number value. The value is stored as a double in `valuedouble` and also in `valueint`. If the number is outside of the range of an integer, `INT_MAX` or `INT_MIN` are used for `valueint`.
* `cJSON_String` (check with `cJSON_IsString`): Represents a string value. It is stored in the form of a zero terminated string in `valuestring`.
* `cJSON_Array` (check with `cJSON_IsArray`): Represent an array value. This is implemented by pointing `child` to a linked list of `cJSON` items that represent the values in the array. The elements are linked together using `next` and `prev`, where the first element has `prev == NULL` and the last element `next == NULL`.
* `cJSON_Array` (check with `cJSON_IsArray`): Represent an array value. This is implemented by pointing `child` to a linked list of `cJSON` items that represent the values in the array. The elements are linked together using `next` and `prev`, where the first element has `prev.next == NULL` and the last element `next == NULL`.
* `cJSON_Object` (check with `cJSON_IsObject`): Represents an object value. Objects are stored same way as an array, the only difference is that the items in the object store their keys in `string`.
* `cJSON_Raw` (check with `cJSON_IsRaw`): Represents any kind of JSON that is stored as a zero terminated array of characters in `valuestring`. This can be used, for example, to avoid printing the same static JSON over and over again to save performance. cJSON will never create this type when parsing. Also note that cJSON doesn't check if it is valid JSON.
Additionally there are the following two flags:
* `cJSON_IsReference`: Specifies that the item that `child` points to and/or `valuestring` is not owned by this item, it is only a reference. So `cJSON_Delete` and other functions will only deallocate this item, not it's children/valuestring.
* `cJSON_IsReference`: Specifies that the item that `child` points to and/or `valuestring` is not owned by this item, it is only a reference. So `cJSON_Delete` and other functions will only deallocate this item, not its `child`/`valuestring`.
* `cJSON_StringIsConst`: This means that `string` points to a constant string. This means that `cJSON_Delete` and other functions will not try to deallocate `string`.
### Working with the data structure
@@ -188,20 +230,22 @@ Additionally there are the following two flags:
For every value type there is a `cJSON_Create...` function that can be used to create an item of that type.
All of these will allocate a `cJSON` struct that can later be deleted with `cJSON_Delete`.
Note that you have to delete them at some point, otherwise you will get a memory leak.
**Important**: If you have added an item to an array or an object already, you **mustn't** delete it with `cJSON_Delete`. Adding it to an array or object transfers its ownership so that when that array or object is deleted, it gets deleted as well.
**Important**: If you have added an item to an array or an object already, you **mustn't** delete it with `cJSON_Delete`. Adding it to an array or object transfers its ownership so that when that array or object is deleted,
it gets deleted as well. You also could use `cJSON_SetValuestring` to change a `cJSON_String`'s `valuestring`, and you needn't to free the previous `valuestring` manually.
#### Basic types
* **null** is created with `cJSON_CreateNull`
* **booleans** are created with `cJSON_CreateTrue`, `cJSON_CreateFalse` or `cJSON_CreateBool`
* **numbers** are created with `cJSON_CreateNumber`. This will set both `valuedouble` and `valueint`. If the number is outside of the range of an integer, `INT_MAX` or `INT_MIN` are used for `valueint`
* **strings** are created with `cJSON_CreateString` (copies the string) or with `cJSON_CreateStringReference` (directly points to the string. This means that `valuestring` won't be deleted by `cJSON_Delete` and you are responsible for it's lifetime, useful for constants)
* **strings** are created with `cJSON_CreateString` (copies the string) or with `cJSON_CreateStringReference` (directly points to the string. This means that `valuestring` won't be deleted by `cJSON_Delete` and you are responsible for its lifetime, useful for constants)
#### Arrays
You can create an empty array with `cJSON_CreateArray`. `cJSON_CreateArrayReference` can be used to create an array that doesn't "own" its content, so its content doesn't get deleted by `cJSON_Delete`.
To add items to an array, use `cJSON_AddItemToArray` to append items to the end.
Using `cJSON_AddItemReferenceToArray` an element can be added as a reference to another item, array or string. This means that `cJSON_Delete` will not delete that items `child` or `valuestring` properties, so no double frees are occuring if they are already used elsewhere.
Using `cJSON_AddItemReferenceToArray` an element can be added as a reference to another item, array or string. This means that `cJSON_Delete` will not delete that items `child` or `valuestring` properties, so no double frees are occurring if they are already used elsewhere.
To insert items in the middle, use `cJSON_InsertItemInArray`. It will insert an item at the given 0 based index and shift all the existing items to the right.
If you want to take an item out of an array at a given index and continue using it, use `cJSON_DetachItemFromArray`, it will return the detached item, so be sure to assign it to a pointer, otherwise you will have a memory leak.
@@ -219,7 +263,7 @@ Because an array is stored as a linked list, iterating it via index is inefficie
You can create an empty object with `cJSON_CreateObject`. `cJSON_CreateObjectReference` can be used to create an object that doesn't "own" its content, so its content doesn't get deleted by `cJSON_Delete`.
To add items to an object, use `cJSON_AddItemToObject`. Use `cJSON_AddItemToObjectCS` to add an item to an object with a name that is a constant or reference (key of the item, `string` in the `cJSON` struct), so that it doesn't get freed by `cJSON_Delete`.
Using `cJSON_AddItemReferenceToArray` an element can be added as a reference to another object, array or string. This means that `cJSON_Delete` will not delete that items `child` or `valuestring` properties, so no double frees are occuring if they are already used elsewhere.
Using `cJSON_AddItemReferenceToArray` an element can be added as a reference to another object, array or string. This means that `cJSON_Delete` will not delete that items `child` or `valuestring` properties, so no double frees are occurring if they are already used elsewhere.
If you want to take an item out of an object, use `cJSON_DetachItemFromObjectCaseSensitive`, it will return the detached item, so be sure to assign it to a pointer, otherwise you will have a memory leak.
@@ -243,6 +287,12 @@ Given some JSON in a zero terminated string, you can parse it with `cJSON_Parse`
cJSON *json = cJSON_Parse(string);
```
Given some JSON in a string (whether zero terminated or not), you can parse it with `cJSON_ParseWithLength`.
```c
cJSON *json = cJSON_ParseWithLength(string, buffer_length);
```
It will parse the JSON and allocate a tree of `cJSON` items that represents it. Once it returns, you are fully responsible for deallocating it after use with `cJSON_Delete`.
The allocator used by `cJSON_Parse` is `malloc` and `free` by default but can be changed (globally) with `cJSON_InitHooks`.
@@ -253,6 +303,8 @@ By default, characters in the input string that follow the parsed JSON will not
If you want more options, use `cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)`.
`return_parse_end` returns a pointer to the end of the JSON in the input string or the position that an error occurs at (thereby replacing `cJSON_GetErrorPtr` in a thread safe way). `require_null_terminated`, if set to `1` will make it an error if the input string contains data after the JSON.
If you want more options giving buffer length, use `cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated)`.
### Printing JSON
Given a tree of `cJSON` items, you can print them as a string using `cJSON_Print`.
@@ -265,11 +317,12 @@ It will allocate a string and print a JSON representation of the tree into it. O
`cJSON_Print` will print with whitespace for formatting. If you want to print without formatting, use `cJSON_PrintUnformatted`.
If you have a rough idea of how big your resulting string will be, you can use `cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)`. `fmt` is a boolean to turn formatting with whitespace on and off. `prebuffer` specifies the first buffer size to use for printing. `cJSON_Print` currently uses 256 bytes for it's first buffer size. Once printing runs out of space, a new buffer is allocated and the old gets copied over before printing is continued.
If you have a rough idea of how big your resulting string will be, you can use `cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)`. `fmt` is a boolean to turn formatting with whitespace on and off. `prebuffer` specifies the first buffer size to use for printing. `cJSON_Print` currently uses 256 bytes for its first buffer size. Once printing runs out of space, a new buffer is allocated and the old gets copied over before printing is continued.
These dynamic buffer allocations can be completely avoided by using `cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)`. It takes a buffer to a pointer to print to and it's length. If the length is reached, printing will fail and it returns `0`. In case of success, `1` is returned. Note that you should provide 5 bytes more than is actually needed, because cJSON is not 100% accurate in estimating if the provided memory is enough.
These dynamic buffer allocations can be completely avoided by using `cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)`. It takes a buffer to a pointer to print to and its length. If the length is reached, printing will fail and it returns `0`. In case of success, `1` is returned. Note that you should provide 5 bytes more than is actually needed, because cJSON is not 100% accurate in estimating if the provided memory is enough.
### Example
In this example we want to build and parse the following JSON:
```json
@@ -293,9 +346,12 @@ In this example we want to build and parse the following JSON:
```
#### Printing
Let's build the above JSON and print it to a string:
```c
//create a monitor with a list of supported resolutions
//NOTE: Returns a heap allocated string, you are required to free it after use.
char *create_monitor(void)
{
const unsigned int resolution_numbers[3][2] = {
@@ -323,7 +379,7 @@ char* create_monitor(void)
goto end;
}
/* after creation was successful, immediately add it to the monitor,
* thereby transfering ownership of the pointer to it */
* thereby transferring ownership of the pointer to it */
cJSON_AddItemToObject(monitor, "name", name);
resolutions = cJSON_CreateArray();
@@ -369,8 +425,10 @@ end:
}
```
Alternatively we can use the `cJSON_Add...ToObject` helper functions to make our lifes a little easier:
Alternatively we can use the `cJSON_Add...ToObject` helper functions to make our lives a little easier:
```c
//NOTE: Returns a heap allocated string, you are required to free it after use.
char *create_monitor_with_helpers(void)
{
const unsigned int resolution_numbers[3][2] = {
@@ -413,7 +471,8 @@ char *create_monitor_with_helpers(void)
}
string = cJSON_Print(monitor);
if (string == NULL) {
if (string == NULL)
{
fprintf(stderr, "Failed to print monitor.\n");
}
@@ -424,6 +483,7 @@ end:
```
#### Parsing
In this example we will parse a JSON in the above format and check if the monitor supports a Full HD resolution while printing some diagnostic output:
```c
@@ -510,6 +570,7 @@ cJSON doesn't support arrays and objects that are nested too deeply because this
In general cJSON is **not thread safe**.
However it is thread safe under the following conditions:
* `cJSON_GetErrorPtr` is never used (the `return_parse_end` parameter of `cJSON_ParseWithOpts` can be used instead)
* `cJSON_InitHooks` is only ever called before using cJSON in any threads.
* `setlocale` is never called before all calls to cJSON functions have returned.
@@ -525,5 +586,5 @@ cJSON supports parsing and printing JSON that contains objects that have multipl
# Enjoy cJSON!
- Dave Gamble (original author)
- Max Bruckner (current maintainer)
- Max Bruckner and Alan Wang (current maintainer)
- and the other [cJSON contributors](CONTRIBUTORS.md)

11
SECURITY.md Normal file
View File

@@ -0,0 +1,11 @@
# Security Policy
## Supported Versions
Security is of the highest importance and all security vulnerabilities or suspected security vulnerabilities should be reported to cjson team privately, to minimize attacks against current users of cjson before they are fixed. Vulnerabilities will be investigated and patched on the next patch (or minor) release as soon as possible. This information could be kept entirely internal to the project.
## Reporting a Vulnerability
If you know of a publicly disclosed security vulnerability for cjson, please IMMEDIATELY contact wp_scut@163.com and peterlee@apache.org to inform the cjson Team.
IMPORTANT: Do not file public issues on GitHub for security vulnerabilities.

489
cJSON.c
View File

@@ -41,9 +41,9 @@
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <float.h>
#include <limits.h>
#include <ctype.h>
#include <float.h>
#ifdef ENABLE_LOCALES
#include <locale.h>
@@ -59,9 +59,32 @@
#include "cJSON.h"
/* define our own boolean type */
#ifdef true
#undef true
#endif
#define true ((cJSON_bool)1)
#ifdef false
#undef false
#endif
#define false ((cJSON_bool)0)
/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */
#ifndef isinf
#define isinf(d) (isnan((d - d)) && !isnan(d))
#endif
#ifndef isnan
#define isnan(d) (d != d)
#endif
#ifndef NAN
#ifdef _WIN32
#define NAN sqrt(-1.0)
#else
#define NAN 0.0/0.0
#endif
#endif
typedef struct {
const unsigned char *json;
size_t position;
@@ -73,16 +96,28 @@ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
return (const char*) (global_error.json + global_error.position);
}
CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item) {
if (!cJSON_IsString(item)) {
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
{
if (!cJSON_IsString(item))
{
return NULL;
}
return item->valuestring;
}
CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item)
{
if (!cJSON_IsNumber(item))
{
return (double) NAN;
}
return item->valuedouble;
}
/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 5)
#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 18)
#error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
#endif
@@ -120,22 +155,22 @@ static int case_insensitive_strcmp(const unsigned char *string1, const unsigned
typedef struct internal_hooks
{
void *(*allocate)(size_t size);
void (*deallocate)(void *pointer);
void *(*reallocate)(void *pointer, size_t size);
void *(CJSON_CDECL *allocate)(size_t size);
void (CJSON_CDECL *deallocate)(void *pointer);
void *(CJSON_CDECL *reallocate)(void *pointer, size_t size);
} internal_hooks;
#if defined(_MSC_VER)
/* work around MSVC error C2322: '...' address of dillimport '...' is not static */
static void *internal_malloc(size_t size)
/* work around MSVC error C2322: '...' address of dllimport '...' is not static */
static void * CJSON_CDECL internal_malloc(size_t size)
{
return malloc(size);
}
static void internal_free(void *pointer)
static void CJSON_CDECL internal_free(void *pointer)
{
free(pointer);
}
static void *internal_realloc(void *pointer, size_t size)
static void * CJSON_CDECL internal_realloc(void *pointer, size_t size)
{
return realloc(pointer, size);
}
@@ -145,6 +180,9 @@ static void *internal_realloc(void *pointer, size_t size)
#define internal_realloc realloc
#endif
/* strlen of character literals resolved at compile time */
#define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc };
static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks)
@@ -225,10 +263,12 @@ CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL))
{
global_hooks.deallocate(item->valuestring);
item->valuestring = NULL;
}
if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
{
global_hooks.deallocate(item->string);
item->string = NULL;
}
global_hooks.deallocate(item);
item = next;
@@ -325,7 +365,7 @@ loop_end:
{
item->valueint = INT_MAX;
}
else if (number <= INT_MIN)
else if (number <= (double)INT_MIN)
{
item->valueint = INT_MIN;
}
@@ -347,7 +387,7 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
{
object->valueint = INT_MAX;
}
else if (number <= INT_MIN)
else if (number <= (double)INT_MIN)
{
object->valueint = INT_MIN;
}
@@ -359,6 +399,50 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
return object->valuedouble = number;
}
/* Note: when passing a NULL valuestring, cJSON_SetValuestring treats this as an error and return NULL */
CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring)
{
char *copy = NULL;
size_t v1_len;
size_t v2_len;
/* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */
if ((object == NULL) || !(object->type & cJSON_String) || (object->type & cJSON_IsReference))
{
return NULL;
}
/* return NULL if the object is corrupted or valuestring is NULL */
if (object->valuestring == NULL || valuestring == NULL)
{
return NULL;
}
v1_len = strlen(valuestring);
v2_len = strlen(object->valuestring);
if (v1_len <= v2_len)
{
/* strcpy does not handle overlapping string: [X1, X2] [Y1, Y2] => X2 < Y1 or Y2 < X1 */
if (!( valuestring + v1_len < object->valuestring || object->valuestring + v2_len < valuestring ))
{
return NULL;
}
strcpy(object->valuestring, valuestring);
return object->valuestring;
}
copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks);
if (copy == NULL)
{
return NULL;
}
if (object->valuestring != NULL)
{
cJSON_free(object->valuestring);
}
object->valuestring = copy;
return copy;
}
typedef struct
{
unsigned char *buffer;
@@ -446,10 +530,8 @@ static unsigned char* ensure(printbuffer * const p, size_t needed)
return NULL;
}
if (newbuffer)
{
memcpy(newbuffer, p->buffer, p->offset + 1);
}
p->hooks.deallocate(p->buffer);
}
p->length = newsize;
@@ -471,6 +553,13 @@ static void update_offset(printbuffer * const buffer)
buffer->offset += strlen((const char*)buffer_pointer);
}
/* securely comparison of floating-point variables */
static cJSON_bool compare_double(double a, double b)
{
double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
return (fabs(a - b) <= maxVal * DBL_EPSILON);
}
/* Render the number nicely from the given item into a string. */
static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer)
{
@@ -478,9 +567,9 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out
double d = item->valuedouble;
int length = 0;
size_t i = 0;
unsigned char number_buffer[26]; /* temporary buffer to print the number into */
unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
unsigned char decimal_point = get_decimal_point();
double test;
double test = 0.0;
if (output_buffer == NULL)
{
@@ -488,24 +577,28 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out
}
/* This checks for NaN and Infinity */
if ((d * 0) != 0)
if (isnan(d) || isinf(d))
{
length = sprintf((char*)number_buffer, "null");
}
else if(d == (double)item->valueint)
{
length = sprintf((char*)number_buffer, "%d", item->valueint);
}
else
{
/* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
length = sprintf((char*)number_buffer, "%1.15g", d);
/* Check whether the original double can be recovered */
if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || ((double)test != d))
if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d))
{
/* If not, print with 17 decimal places of precision */
length = sprintf((char*)number_buffer, "%1.17g", d);
}
}
/* sprintf failed or buffer overrun occured */
/* sprintf failed or buffer overrun occurred */
if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
{
return false;
@@ -814,6 +907,7 @@ fail:
if (output != NULL)
{
input_buffer->hooks.deallocate(output);
output = NULL;
}
if (input_pointer != NULL)
@@ -968,6 +1062,11 @@ static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
return NULL;
}
if (cannot_access_at_index(buffer, 0))
{
return buffer;
}
while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))
{
buffer->offset++;
@@ -997,8 +1096,23 @@ static parse_buffer *skip_utf8_bom(parse_buffer * const buffer)
return buffer;
}
/* Parse an object - create a new root, and populate. */
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
{
size_t buffer_length;
if (NULL == value)
{
return NULL;
}
/* Adding null character size due to require_null_terminated. */
buffer_length = strlen(value) + sizeof("");
return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated);
}
/* Parse an object - create a new root, and populate. */
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated)
{
parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
cJSON *item = NULL;
@@ -1007,13 +1121,13 @@ CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return
global_error.json = NULL;
global_error.position = 0;
if (value == NULL)
if (value == NULL || 0 == buffer_length)
{
goto fail;
}
buffer.content = (const unsigned char*)value;
buffer.length = strlen((const char*)value) + sizeof("");
buffer.length = buffer_length;
buffer.offset = 0;
buffer.hooks = global_hooks;
@@ -1083,7 +1197,12 @@ CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
return cJSON_ParseWithOpts(value, 0, 0);
}
#define cjson_min(a, b) ((a < b) ? a : b)
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length)
{
return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0);
}
#define cjson_min(a, b) (((a) < (b)) ? (a) : (b))
static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)
{
@@ -1114,10 +1233,10 @@ static unsigned char *print(const cJSON * const item, cJSON_bool format, const i
if (hooks->reallocate != NULL)
{
printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1);
buffer->buffer = NULL;
if (printed == NULL) {
goto fail;
}
buffer->buffer = NULL;
}
else /* otherwise copy the JSON over to a new buffer */
{
@@ -1131,6 +1250,7 @@ static unsigned char *print(const cJSON * const item, cJSON_bool format, const i
/* free the buffer */
hooks->deallocate(buffer->buffer);
buffer->buffer = NULL;
}
return printed;
@@ -1139,11 +1259,13 @@ fail:
if (buffer->buffer != NULL)
{
hooks->deallocate(buffer->buffer);
buffer->buffer = NULL;
}
if (printed != NULL)
{
hooks->deallocate(printed);
printed = NULL;
}
return NULL;
@@ -1184,26 +1306,27 @@ CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON
if (!print_value(item, &p))
{
global_hooks.deallocate(p.buffer);
p.buffer = NULL;
return NULL;
}
return (char*)p.buffer;
}
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const cJSON_bool fmt)
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)
{
printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
if ((len < 0) || (buf == NULL))
if ((length < 0) || (buffer == NULL))
{
return false;
}
p.buffer = (unsigned char*)buf;
p.length = (size_t)len;
p.buffer = (unsigned char*)buffer;
p.length = (size_t)length;
p.offset = 0;
p.noalloc = true;
p.format = fmt;
p.format = format;
p.hooks = global_hooks;
return print_value(item, &p);
@@ -1416,6 +1539,10 @@ static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buf
success:
input_buffer->depth--;
if (head != NULL) {
head->prev = current_item;
}
item->type = cJSON_Array;
item->child = head;
@@ -1551,12 +1678,17 @@ static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_bu
current_item = new_item;
}
if (cannot_access_at_index(input_buffer, 1))
{
goto fail; /* nothing comes after the comma */
}
/* parse the name of the child */
input_buffer->offset++;
buffer_skip_whitespace(input_buffer);
if (!parse_string(current_item, input_buffer))
{
goto fail; /* faile to parse name */
goto fail; /* failed to parse name */
}
buffer_skip_whitespace(input_buffer);
@@ -1588,6 +1720,10 @@ static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_bu
success:
input_buffer->depth--;
if (head != NULL) {
head->prev = current_item;
}
item->type = cJSON_Object;
item->child = head;
@@ -1676,7 +1812,7 @@ static cJSON_bool print_object(const cJSON * const item, printbuffer * const out
update_offset(output_buffer);
/* print comma if not last */
length = (size_t) ((output_buffer->format ? 1 : 0) + (current_item->next ? 1 : 0));
length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
output_pointer = ensure(output_buffer, length + 1);
if (output_pointer == NULL)
{
@@ -1782,7 +1918,7 @@ static cJSON *get_object_item(const cJSON * const object, const char * const nam
current_element = object->child;
if (case_sensitive)
{
while ((current_element != NULL) && (strcmp(name, current_element->string) != 0))
while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0))
{
current_element = current_element->next;
}
@@ -1795,6 +1931,10 @@ static cJSON *get_object_item(const cJSON * const object, const char * const nam
}
}
if ((current_element == NULL) || (current_element->string == NULL)) {
return NULL;
}
return current_element;
}
@@ -1846,35 +1986,39 @@ static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
{
cJSON *child = NULL;
if ((item == NULL) || (array == NULL))
if ((item == NULL) || (array == NULL) || (array == item))
{
return false;
}
child = array->child;
/*
* To find the last item in array quickly, we use prev in array
*/
if (child == NULL)
{
/* list is empty, start new one */
array->child = item;
item->prev = item;
item->next = NULL;
}
else
{
/* append to the end */
while (child->next)
if (child->prev)
{
child = child->next;
suffix_object(child->prev, item);
array->child->prev = item;
}
suffix_object(child, item);
}
return true;
}
/* Add item to array/object. */
CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item)
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item)
{
add_item_to_array(array, item);
return add_item_to_array(array, item);
}
#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
@@ -1898,7 +2042,7 @@ static cJSON_bool add_item_to_object(cJSON * const object, const char * const st
char *new_key = NULL;
int new_type = cJSON_Invalid;
if ((object == NULL) || (string == NULL) || (item == NULL))
if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item))
{
return false;
}
@@ -1930,35 +2074,35 @@ static cJSON_bool add_item_to_object(cJSON * const object, const char * const st
return add_item_to_array(object, item);
}
CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
{
add_item_to_object(object, string, item, &global_hooks, false);
return add_item_to_object(object, string, item, &global_hooks, false);
}
/* Add an item to an object with constant string as key */
CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
{
add_item_to_object(object, string, item, &global_hooks, true);
return add_item_to_object(object, string, item, &global_hooks, true);
}
CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
{
if (array == NULL)
{
return;
return false;
}
add_item_to_array(array, create_reference(item, &global_hooks));
return add_item_to_array(array, create_reference(item, &global_hooks));
}
CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
{
if ((object == NULL) || (string == NULL))
{
return;
return false;
}
add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
}
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)
@@ -2071,12 +2215,12 @@ CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * c
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
{
if ((parent == NULL) || (item == NULL))
if ((parent == NULL) || (item == NULL) || (item != parent->child && item->prev == NULL))
{
return NULL;
}
if (item->prev != NULL)
if (item != parent->child)
{
/* not the first element */
item->prev->next = item->next;
@@ -2092,6 +2236,12 @@ CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const it
/* first element */
parent->child = item->next;
}
else if (item->next == NULL)
{
/* last element */
parent->child->prev = item->prev;
}
/* make sure the detached item doesn't point anywhere anymore */
item->prev = NULL;
item->next = NULL;
@@ -2139,20 +2289,24 @@ CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const
}
/* Replace array/object items with new ones. */
CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
{
cJSON *after_inserted = NULL;
if (which < 0)
if (which < 0 || newitem == NULL)
{
return;
return false;
}
after_inserted = get_array_item(array, (size_t)which);
if (after_inserted == NULL)
{
add_item_to_array(array, newitem);
return;
return add_item_to_array(array, newitem);
}
if (after_inserted != array->child && after_inserted->prev == NULL) {
/* return false if after_inserted is a corrupted array item */
return false;
}
newitem->next = after_inserted;
@@ -2166,11 +2320,12 @@ CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newit
{
newitem->prev->next = newitem;
}
return true;
}
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
{
if ((parent == NULL) || (replacement == NULL) || (item == NULL))
if ((parent == NULL) || (parent->child == NULL) || (replacement == NULL) || (item == NULL))
{
return false;
}
@@ -2187,13 +2342,27 @@ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON
{
replacement->next->prev = replacement;
}
if (parent->child == item)
{
if (parent->child->prev == parent->child)
{
replacement->prev = replacement;
}
parent->child = replacement;
}
else
{ /*
* To find the last item in array quickly, we use prev in array.
* We can't modify the last item's next pointer where this item was the parent's child
*/
if (replacement->prev != NULL)
{
replacement->prev->next = replacement;
}
if (parent->child == item)
if (replacement->next == NULL)
{
parent->child = replacement;
parent->child->prev = replacement;
}
}
item->next = NULL;
@@ -2203,14 +2372,14 @@ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON
return true;
}
CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
{
if (which < 0)
{
return;
return false;
}
cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
}
static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)
@@ -2226,21 +2395,24 @@ static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSO
cJSON_free(replacement->string);
}
replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
if (replacement->string == NULL)
{
return false;
}
replacement->type &= ~cJSON_StringIsConst;
cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
return true;
return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
}
CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
{
replace_item_in_object(object, string, newitem, false);
return replace_item_in_object(object, string, newitem, false);
}
CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
{
replace_item_in_object(object, string, newitem, true);
return replace_item_in_object(object, string, newitem, true);
}
/* Create basic types: */
@@ -2277,12 +2449,12 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
return item;
}
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b)
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean)
{
cJSON *item = cJSON_New_Item(&global_hooks);
if(item)
{
item->type = b ? cJSON_True : cJSON_False;
item->type = boolean ? cJSON_True : cJSON_False;
}
return item;
@@ -2301,7 +2473,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
{
item->valueint = INT_MAX;
}
else if (num <= INT_MIN)
else if (num <= (double)INT_MIN)
{
item->valueint = INT_MIN;
}
@@ -2417,6 +2589,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
}
a = cJSON_CreateArray();
for(i = 0; a && (i < (size_t)count); i++)
{
n = cJSON_CreateNumber(numbers[i]);
@@ -2436,6 +2609,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
p = n;
}
if (a && a->child) {
a->child->prev = n;
}
return a;
}
@@ -2472,6 +2649,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
p = n;
}
if (a && a->child) {
a->child->prev = n;
}
return a;
}
@@ -2508,10 +2689,14 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
p = n;
}
if (a && a->child) {
a->child->prev = n;
}
return a;
}
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count)
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count)
{
size_t i = 0;
cJSON *n = NULL;
@@ -2544,11 +2729,22 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count)
p = n;
}
if (a && a->child) {
a->child->prev = n;
}
return a;
}
/* Duplication */
cJSON * cJSON_Duplicate_rec(const cJSON *item, size_t depth, cJSON_bool recurse);
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
{
return cJSON_Duplicate_rec(item, 0, recurse );
}
cJSON * cJSON_Duplicate_rec(const cJSON *item, size_t depth, cJSON_bool recurse)
{
cJSON *newitem = NULL;
cJSON *child = NULL;
@@ -2595,7 +2791,10 @@ CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
child = item->child;
while (child != NULL)
{
newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */
if(depth >= CJSON_CIRCULAR_LIMIT) {
goto fail;
}
newchild = cJSON_Duplicate_rec(child, depth + 1, true); /* Duplicate (with recurse) each item in the ->next chain */
if (!newchild)
{
goto fail;
@@ -2615,6 +2814,10 @@ CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
}
child = child->next;
}
if (newitem && newitem->child)
{
newitem->child->prev = newchild;
}
return newitem;
@@ -2627,69 +2830,96 @@ fail:
return NULL;
}
static void skip_oneline_comment(char **input)
{
*input += static_strlen("//");
for (; (*input)[0] != '\0'; ++(*input))
{
if ((*input)[0] == '\n') {
*input += static_strlen("\n");
return;
}
}
}
static void skip_multiline_comment(char **input)
{
*input += static_strlen("/*");
for (; (*input)[0] != '\0'; ++(*input))
{
if (((*input)[0] == '*') && ((*input)[1] == '/'))
{
*input += static_strlen("*/");
return;
}
}
}
static void minify_string(char **input, char **output) {
(*output)[0] = (*input)[0];
*input += static_strlen("\"");
*output += static_strlen("\"");
for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {
(*output)[0] = (*input)[0];
if ((*input)[0] == '\"') {
(*output)[0] = '\"';
*input += static_strlen("\"");
*output += static_strlen("\"");
return;
} else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
(*output)[1] = (*input)[1];
*input += static_strlen("\"");
*output += static_strlen("\"");
}
}
}
CJSON_PUBLIC(void) cJSON_Minify(char *json)
{
unsigned char *into = (unsigned char*)json;
char *into = json;
if (json == NULL)
{
return;
}
while (*json)
while (json[0] != '\0')
{
if (*json == ' ')
switch (json[0])
{
case ' ':
case '\t':
case '\r':
case '\n':
json++;
break;
case '/':
if (json[1] == '/')
{
skip_oneline_comment(&json);
}
else if (json[1] == '*')
{
skip_multiline_comment(&json);
} else {
json++;
}
else if (*json == '\t')
{
/* Whitespace characters. */
break;
case '\"':
minify_string(&json, (char**)&into);
break;
default:
into[0] = json[0];
json++;
}
else if (*json == '\r')
{
json++;
}
else if (*json=='\n')
{
json++;
}
else if ((*json == '/') && (json[1] == '/'))
{
/* double-slash comments, to end of line. */
while (*json && (*json != '\n'))
{
json++;
}
}
else if ((*json == '/') && (json[1] == '*'))
{
/* multiline comments. */
while (*json && !((*json == '*') && (json[1] == '/')))
{
json++;
}
json += 2;
}
else if (*json == '\"')
{
/* string literals, which are \" sensitive. */
*into++ = (unsigned char)*json++;
while (*json && (*json != '\"'))
{
if (*json == '\\')
{
*into++ = (unsigned char)*json++;
}
*into++ = (unsigned char)*json++;
}
*into++ = (unsigned char)*json++;
}
else
{
/* All other characters. */
*into++ = (unsigned char)*json++;
into++;
}
}
@@ -2799,7 +3029,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive)
{
if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || cJSON_IsInvalid(a))
if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)))
{
return false;
}
@@ -2836,7 +3066,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * cons
return true;
case cJSON_Number:
if (a->valuedouble == b->valuedouble)
if (compare_double(a->valuedouble, b->valuedouble))
{
return true;
}
@@ -2930,4 +3160,5 @@ CJSON_PUBLIC(void *) cJSON_malloc(size_t size)
CJSON_PUBLIC(void) cJSON_free(void *object)
{
global_hooks.deallocate(object);
object = NULL;
}

161
cJSON.h
View File

@@ -28,10 +28,60 @@ extern "C"
{
#endif
#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
#define __WINDOWS__
#endif
#ifdef __WINDOWS__
/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options:
CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
For *nix builds that support visibility attribute, you can define similar behavior by
setting default visibility to hidden by adding
-fvisibility=hidden (for gcc)
or
-xldscope=hidden (for sun cc)
to CFLAGS
then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
*/
#define CJSON_CDECL __cdecl
#define CJSON_STDCALL __stdcall
/* export symbols by default, this is necessary for copy pasting the C and header file */
#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_EXPORT_SYMBOLS
#endif
#if defined(CJSON_HIDE_SYMBOLS)
#define CJSON_PUBLIC(type) type CJSON_STDCALL
#elif defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL
#elif defined(CJSON_IMPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL
#endif
#else /* !__WINDOWS__ */
#define CJSON_CDECL
#define CJSON_STDCALL
#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
#else
#define CJSON_PUBLIC(type) type
#endif
#endif
/* project version */
#define CJSON_VERSION_MAJOR 1
#define CJSON_VERSION_MINOR 7
#define CJSON_VERSION_PATCH 5
#define CJSON_VERSION_PATCH 18
#include <stddef.h>
@@ -74,61 +124,25 @@ typedef struct cJSON
typedef struct cJSON_Hooks
{
void *(*malloc_fn)(size_t sz);
void (*free_fn)(void *ptr);
/* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
void *(CJSON_CDECL *malloc_fn)(size_t sz);
void (CJSON_CDECL *free_fn)(void *ptr);
} cJSON_Hooks;
typedef int cJSON_bool;
#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
#define __WINDOWS__
#endif
#ifdef __WINDOWS__
/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 2 define options:
CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
For *nix builds that support visibility attribute, you can define similar behavior by
setting default visibility to hidden by adding
-fvisibility=hidden (for gcc)
or
-xldscope=hidden (for sun cc)
to CFLAGS
then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
*/
/* export symbols by default, this is necessary for copy pasting the C and header file */
#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_EXPORT_SYMBOLS
#endif
#if defined(CJSON_HIDE_SYMBOLS)
#define CJSON_PUBLIC(type) type __stdcall
#elif defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllexport) type __stdcall
#elif defined(CJSON_IMPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllimport) type __stdcall
#endif
#else /* !WIN32 */
#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
#else
#define CJSON_PUBLIC(type) type
#endif
#endif
/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
* This is to prevent stack overflows. */
#ifndef CJSON_NESTING_LIMIT
#define CJSON_NESTING_LIMIT 1000
#endif
/* Limits the length of circular references can be before cJSON rejects to parse them.
* This is to prevent stack overflows. */
#ifndef CJSON_CIRCULAR_LIMIT
#define CJSON_CIRCULAR_LIMIT 10000
#endif
/* returns the version of cJSON as a string */
CJSON_PUBLIC(const char*) cJSON_Version(void);
@@ -138,9 +152,11 @@ CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length);
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated);
/* Render a cJSON entity to text for transfer/storage. */
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
@@ -152,11 +168,11 @@ CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON
/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
/* Delete a cJSON entity and all subentities. */
CJSON_PUBLIC(void) cJSON_Delete(cJSON *c);
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);
/* Returns the number of items in an array (or object). */
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
/* Get item "string" from object. Case insensitive. */
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
@@ -165,8 +181,9 @@ CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *st
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
/* Check if the item is a string and return its valuestring */
CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item);
/* Check item type and return its value */
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item);
CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item);
/* These functions check the type of an item */
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
@@ -195,29 +212,30 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
/* Create a string where valuestring references a string so
* it will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
/* Create an object/arrray that only references it's elements so
/* Create an object/array that only references it's elements so
* they will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
/* These utilities create an Array of count items. */
/* These utilities create an Array of count items.
* The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count);
/* Append item to the specified array/object. */
CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
* WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
* writing to `item->string` */
CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
/* Remove/Detatch items from Arrays/Objects. */
/* Remove/Detach items from Arrays/Objects. */
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
@@ -227,22 +245,24 @@ CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
/* Update array items. */
CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
/* Duplicate a cJSON item */
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
need to be released. With recurse!=0, it will duplicate any children connected to the item.
The item->next and ->prev pointers are always zero on return from Duplicate. */
* need to be released. With recurse!=0, it will duplicate any children connected to the item.
* The item->next and ->prev pointers are always zero on return from Duplicate. */
/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
* case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings.
* The input pointer json cannot point to a read-only address area, such as a string constant,
* but should point to a readable and writable address area. */
CJSON_PUBLIC(void) cJSON_Minify(char *json);
/* Helper functions for creating and adding items to an object at the same time.
@@ -262,6 +282,15 @@ CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * c
/* helper for the cJSON_SetNumberValue macro */
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */
CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring);
/* If the object is not a boolean type this does nothing and returns cJSON_Invalid else it returns the new type*/
#define cJSON_SetBoolValue(object, boolValue) ( \
(object != NULL && ((object)->type & (cJSON_False|cJSON_True))) ? \
(object)->type=((object)->type &(~(cJSON_False|cJSON_True)))|((boolValue)?cJSON_True:cJSON_False) : \
cJSON_Invalid\
)
/* Macro for iterating over an array or object */
#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)

View File

@@ -39,6 +39,9 @@
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <math.h>
#include <float.h>
#include <math.h>
#if defined(_MSC_VER)
#pragma warning (pop)
@@ -50,7 +53,14 @@
#include "cJSON_Utils.h"
/* define our own boolean type */
#ifdef true
#undef true
#endif
#define true ((cJSON_bool)1)
#ifdef false
#undef false
#endif
#define false ((cJSON_bool)0)
static unsigned char* cJSONUtils_strdup(const unsigned char* const string)
@@ -98,6 +108,14 @@ static int compare_strings(const unsigned char *string1, const unsigned char *st
return tolower(*string1) - tolower(*string2);
}
/* securely comparison of floating-point variables */
static cJSON_bool compare_double(double a, double b)
{
double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
return (fabs(a - b) <= maxVal * DBL_EPSILON);
}
/* Compare the next path element of two JSON pointers, two NULL pointers are considered unequal: */
static cJSON_bool compare_pointers(const unsigned char *name, const unsigned char *pointer, const cJSON_bool case_sensitive)
{
@@ -158,13 +176,14 @@ static void encode_string_as_pointer(unsigned char *destination, const unsigned
{
if (source[0] == '/')
{
destination[0] = '~';
destination[1] = '1';
destination++;
}
else if (source[0] == '~')
{
destination[0] = '~';
destination[1] = '1';
destination[1] = '0';
destination++;
}
else
@@ -209,6 +228,7 @@ CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(const cJSON * const obje
if (child_index > ULONG_MAX)
{
cJSON_free(target_pointer);
cJSON_free(full_pointer);
return NULL;
}
sprintf((char*)full_pointer, "/%lu%s", (unsigned long)child_index, target_pointer); /* /<array_index><path> */
@@ -383,7 +403,7 @@ static cJSON *detach_item_from_array(cJSON *array, size_t which)
/* item doesn't exist */
return NULL;
}
if (c->prev)
if (c != array->child)
{
/* not the first element */
c->prev->next = c->next;
@@ -396,6 +416,10 @@ static cJSON *detach_item_from_array(cJSON *array, size_t which)
{
array->child = c->next;
}
else if (c->next == NULL)
{
array->child->prev = c->prev;
}
/* make sure the detached item doesn't point anywhere anymore */
c->prev = c->next = NULL;
@@ -499,6 +523,7 @@ static cJSON *sort_list(cJSON *list, const cJSON_bool case_sensitive)
{
/* Split the lists */
second->prev->next = NULL;
second->prev = NULL;
}
/* Recursively sort the sub-lists. */
@@ -510,7 +535,7 @@ static cJSON *sort_list(cJSON *list, const cJSON_bool case_sensitive)
while ((first != NULL) && (second != NULL))
{
cJSON *smaller = NULL;
if (compare_strings((unsigned char*)first->string, (unsigned char*)second->string, false) < 0)
if (compare_strings((unsigned char*)first->string, (unsigned char*)second->string, case_sensitive) < 0)
{
smaller = first;
}
@@ -587,7 +612,7 @@ static cJSON_bool compare_json(cJSON *a, cJSON *b, const cJSON_bool case_sensiti
{
case cJSON_Number:
/* numeric mismatch. */
if ((a->valueint != b->valueint) || (a->valuedouble != b->valuedouble))
if ((a->valueint != b->valueint) || (!compare_double(a->valuedouble, b->valuedouble)))
{
return false;
}
@@ -935,7 +960,9 @@ static int apply_patch(cJSON *object, const cJSON *patch, const cJSON_bool case_
/* split pointer in parent and child */
parent_pointer = cJSONUtils_strdup((unsigned char*)path->valuestring);
if (parent_pointer) {
child_pointer = (unsigned char*)strrchr((char*)parent_pointer, '/');
}
if (child_pointer != NULL)
{
child_pointer[0] = '\0';
@@ -1127,7 +1154,7 @@ static void create_patches(cJSON * const patches, const unsigned char * const pa
switch (from->type & 0xFF)
{
case cJSON_Number:
if ((from->valueint != to->valueint) || (from->valuedouble != to->valuedouble))
if ((from->valueint != to->valueint) || !compare_double(from->valuedouble, to->valuedouble))
{
compose_patch(patches, (const unsigned char*)"replace", path, NULL, to);
}
@@ -1340,6 +1367,7 @@ static cJSON *merge_patch(cJSON *target, const cJSON * const patch, const cJSON_
replacement = merge_patch(replace_me, patch_child, case_sensitive);
if (replacement == NULL)
{
cJSON_Delete(target);
return NULL;
}
@@ -1381,6 +1409,10 @@ static cJSON *generate_merge_patch(cJSON * const from, cJSON * const to, const c
from_child = from->child;
to_child = to->child;
patch = cJSON_CreateObject();
if (patch == NULL)
{
return NULL;
}
while (from_child || to_child)
{
int diff;

View File

@@ -20,6 +20,14 @@
THE SOFTWARE.
*/
#ifndef cJSON_Utils__h
#define cJSON_Utils__h
#ifdef __cplusplus
extern "C"
{
#endif
#include "cJSON.h"
/* Implement RFC6901 (https://tools.ietf.org/html/rfc6901) JSON Pointer spec. */
@@ -72,3 +80,9 @@ CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(const cJSON * const obje
/* Sorts the members of the object into alphabetical order. */
CJSON_PUBLIC(void) cJSONUtils_SortObject(cJSON * const object);
CJSON_PUBLIC(void) cJSONUtils_SortObjectCaseSensitive(cJSON * const object);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -26,3 +26,9 @@ if (ENABLE_FUZZING)
endif()
if(ENABLE_CJSON_TEST)
ADD_EXECUTABLE(fuzz_main fuzz_main.c cjson_read_fuzzer.c)
TARGET_LINK_LIBRARIES(fuzz_main cjson)
endif()

View File

@@ -0,0 +1,77 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "../cJSON.h"
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size); /* required by C89 */
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{
cJSON *json;
size_t offset = 4;
unsigned char *copied;
char *printed_json = NULL;
int minify, require_termination, formatted, buffered;
if(size <= offset) return 0;
if(data[size-1] != '\0') return 0;
if(data[0] != '1' && data[0] != '0') return 0;
if(data[1] != '1' && data[1] != '0') return 0;
if(data[2] != '1' && data[2] != '0') return 0;
if(data[3] != '1' && data[3] != '0') return 0;
minify = data[0] == '1' ? 1 : 0;
require_termination = data[1] == '1' ? 1 : 0;
formatted = data[2] == '1' ? 1 : 0;
buffered = data[3] == '1' ? 1 : 0;
json = cJSON_ParseWithOpts((const char*)data + offset, NULL, require_termination);
if(json == NULL) return 0;
if(buffered)
{
printed_json = cJSON_PrintBuffered(json, 1, formatted);
}
else
{
/* unbuffered printing */
if(formatted)
{
printed_json = cJSON_Print(json);
}
else
{
printed_json = cJSON_PrintUnformatted(json);
}
}
if(printed_json != NULL) free(printed_json);
if(minify)
{
copied = (unsigned char*)malloc(size);
if(copied == NULL) return 0;
memcpy(copied, data, size);
cJSON_Minify((char*)copied + offset);
free(copied);
}
cJSON_Delete(json);
return 0;
}
#ifdef __cplusplus
}
#endif

54
fuzzing/fuzz_main.c Normal file
View File

@@ -0,0 +1,54 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size); /* required by C89 */
/* fuzz target entry point, works without libFuzzer */
int main(int argc, char **argv)
{
FILE *f;
char *buf = NULL;
long siz_buf;
if(argc < 2)
{
fprintf(stderr, "no input file\n");
goto err;
}
f = fopen(argv[1], "rb");
if(f == NULL)
{
fprintf(stderr, "error opening input file %s\n", argv[1]);
goto err;
}
fseek(f, 0, SEEK_END);
siz_buf = ftell(f);
rewind(f);
if(siz_buf < 1) goto err;
buf = (char*)malloc((size_t)siz_buf);
if(buf == NULL)
{
fprintf(stderr, "malloc() failed\n");
goto err;
}
if(fread(buf, (size_t)siz_buf, 1, f) != 1)
{
fprintf(stderr, "fread() failed\n");
goto err;
}
(void)LLVMFuzzerTestOneInput((uint8_t*)buf, (size_t)siz_buf);
err:
free(buf);
return 0;
}

18
fuzzing/ossfuzz.sh Executable file
View File

@@ -0,0 +1,18 @@
#!/bin/bash -eu
# This script is meant to be run by
# https://github.com/google/oss-fuzz/blob/master/projects/cjson/Dockerfile
mkdir build
cd build
cmake -DBUILD_SHARED_LIBS=OFF -DENABLE_CJSON_TEST=OFF ..
make -j$(nproc)
$CXX $CXXFLAGS $SRC/cjson/fuzzing/cjson_read_fuzzer.c -I. \
-o $OUT/cjson_read_fuzzer \
$LIB_FUZZING_ENGINE $SRC/cjson/build/libcjson.a
find $SRC/cjson/fuzzing/inputs -name "*" | \
xargs zip $OUT/cjson_read_fuzzer_seed_corpus.zip
cp $SRC/cjson/fuzzing/json.dict $OUT/cjson_read_fuzzer.dict

View File

@@ -6,5 +6,5 @@ Version: @PROJECT_VERSION@
Description: Ultralightweight JSON parser in ANSI C
URL: https://github.com/DaveGamble/cJSON
Libs: -L${libdir} -lcjson
Libs.Private: -lm
Cflags: -I${includedir}
Libs.private: -lm
Cflags: -I${includedir} -I${includedir}/cjson

View File

@@ -6,5 +6,5 @@ Version: @PROJECT_VERSION@
Description: An implementation of JSON Pointer, Patch and Merge Patch based on cJSON.
URL: https://github.com/DaveGamble/cJSON
Libs: -L${libdir} -lcjson_utils
Cflags: -I${includedir}
Cflags: -I${includedir} -I${includedir}/cjson
Requires: libcjson

View File

@@ -0,0 +1,27 @@
cmake_minimum_required(VERSION 2.8.5)
set(MANIFEST "${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt")
if(NOT EXISTS ${MANIFEST})
message(FATAL_ERROR "Cannot find install mainfest: ${MANIFEST}")
endif()
file(STRINGS ${MANIFEST} files)
foreach(file ${files})
if(EXISTS ${file} OR IS_SYMLINK ${file})
message(STATUS "Removing: ${file}")
execute_process(COMMAND rm -f ${file}
RESULT_VARIABLE result
OUTPUT_QUIET
ERROR_VARIABLE stderr
ERROR_STRIP_TRAILING_WHITESPACE
)
if(NOT ${result} EQUAL 0)
message(FATAL_ERROR "${stderr}")
endif()
else()
message(STATUS "Does-not-exist: ${file}")
endif()
endforeach(file)

2
test.c
View File

@@ -256,7 +256,7 @@ static void create_objects(void)
cJSON_Delete(root);
}
int main(void)
int CJSON_CDECL main(void)
{
/* print the version */
printf("Version: %s\n", cJSON_Version());

View File

@@ -1,5 +1,5 @@
if(ENABLE_CJSON_TEST)
add_library(unity "${CJSON_LIBRARY_TYPE}" unity/src/unity.c)
add_library(unity STATIC unity/src/unity.c)
# Disable -Werror for Unity
if (FLAG_SUPPORTED_Werror)
@@ -57,6 +57,7 @@ if(ENABLE_CJSON_TEST)
compare_tests
cjson_add
readme_examples
minify_tests
)
option(ENABLE_VALGRIND OFF "Enable the valgrind memory checker for the tests.")
@@ -72,6 +73,9 @@ if(ENABLE_CJSON_TEST)
foreach(unity_test ${unity_tests})
add_executable("${unity_test}" "${unity_test}.c")
if("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
target_sources(${unity_test} PRIVATE unity_setup.c)
endif()
target_link_libraries("${unity_test}" "${CJSON_LIB}" unity)
if(MEMORYCHECK_COMMAND)
add_test(NAME "${unity_test}"
@@ -98,6 +102,9 @@ if(ENABLE_CJSON_TEST)
foreach (cjson_utils_test ${cjson_utils_tests})
add_executable("${cjson_utils_test}" "${cjson_utils_test}.c")
target_link_libraries("${cjson_utils_test}" "${CJSON_LIB}" "${CJSON_UTILS_LIB}" unity)
if("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
target_sources(${cjson_utils_test} PRIVATE unity_setup.c)
endif()
if(MEMORYCHECK_COMMAND)
add_test(NAME "${cjson_utils_test}"
COMMAND "${MEMORYCHECK_COMMAND}" ${MEMORYCHECK_COMMAND_OPTIONS} "${CMAKE_CURRENT_BINARY_DIR}/${cjson_utils_test}")

View File

@@ -28,15 +28,21 @@
#include "unity/src/unity.h"
#include "common.h"
static void *failing_malloc(size_t size)
static void * CJSON_CDECL failing_malloc(size_t size)
{
(void)size;
return NULL;
}
/* work around MSVC error C2322: '...' address of dllimport '...' is not static */
static void CJSON_CDECL normal_free(void *pointer)
{
free(pointer);
}
static cJSON_Hooks failing_hooks = {
failing_malloc,
free
normal_free
};
static void cjson_add_null_should_add_null(void)
@@ -111,6 +117,50 @@ static void cjson_add_true_should_fail_on_allocation_failure(void)
cJSON_Delete(root);
}
static void cjson_create_int_array_should_fail_on_allocation_failure(void)
{
int numbers[] = {1, 2, 3};
cJSON_InitHooks(&failing_hooks);
TEST_ASSERT_NULL(cJSON_CreateIntArray(numbers, 3));
cJSON_InitHooks(NULL);
}
static void cjson_create_float_array_should_fail_on_allocation_failure(void)
{
float numbers[] = {1.0f, 2.0f, 3.0f};
cJSON_InitHooks(&failing_hooks);
TEST_ASSERT_NULL(cJSON_CreateFloatArray(numbers, 3));
cJSON_InitHooks(NULL);
}
static void cjson_create_double_array_should_fail_on_allocation_failure(void)
{
double numbers[] = {1.0, 2.0, 3.0};
cJSON_InitHooks(&failing_hooks);
TEST_ASSERT_NULL(cJSON_CreateDoubleArray(numbers, 3));
cJSON_InitHooks(NULL);
}
static void cjson_create_string_array_should_fail_on_allocation_failure(void)
{
const char* strings[] = {"1", "2", "3"};
cJSON_InitHooks(&failing_hooks);
TEST_ASSERT_NULL(cJSON_CreateStringArray(strings, 3));
cJSON_InitHooks(NULL);
}
static void cjson_add_false_should_add_false(void)
{
cJSON *root = cJSON_CreateObject();
@@ -372,7 +422,7 @@ static void cjson_add_array_should_fail_on_allocation_failure(void)
cJSON_Delete(root);
}
int main(void)
int CJSON_CDECL main(void)
{
UNITY_BEGIN();
@@ -384,6 +434,11 @@ int main(void)
RUN_TEST(cjson_add_true_should_fail_with_null_pointers);
RUN_TEST(cjson_add_true_should_fail_on_allocation_failure);
RUN_TEST(cjson_create_int_array_should_fail_on_allocation_failure);
RUN_TEST(cjson_create_float_array_should_fail_on_allocation_failure);
RUN_TEST(cjson_create_double_array_should_fail_on_allocation_failure);
RUN_TEST(cjson_create_string_array_should_fail_on_allocation_failure);
RUN_TEST(cjson_add_false_should_add_false);
RUN_TEST(cjson_add_false_should_fail_with_null_pointers);
RUN_TEST(cjson_add_false_should_fail_on_allocation_failure);

View File

@@ -64,6 +64,9 @@ static void cjson_compare_should_compare_numbers(void)
TEST_ASSERT_TRUE(compare_from_string("1", "1", false));
TEST_ASSERT_TRUE(compare_from_string("0.0001", "0.0001", true));
TEST_ASSERT_TRUE(compare_from_string("0.0001", "0.0001", false));
TEST_ASSERT_TRUE(compare_from_string("1E100", "10E99", false));
TEST_ASSERT_FALSE(compare_from_string("0.5E-100", "0.5E-101", false));
TEST_ASSERT_FALSE(compare_from_string("1", "2", true));
TEST_ASSERT_FALSE(compare_from_string("1", "2", false));
@@ -186,7 +189,7 @@ static void cjson_compare_should_compare_objects(void)
false))
}
int main(void)
int CJSON_CDECL main(void)
{
UNITY_BEGIN();

View File

@@ -214,6 +214,7 @@
{ "doc": {"foo": null},
"patch": [{"op": "test", "path": "/foo", "value": null}],
"expected": {"foo": null},
"comment": "null value should be valid obj property" },
{ "doc": {"foo": null},
@@ -243,14 +244,17 @@
{ "doc": {"foo": {"foo": 1, "bar": 2}},
"patch": [{"op": "test", "path": "/foo", "value": {"bar": 2, "foo": 1}}],
"expected": {"foo": {"foo": 1, "bar": 2}},
"comment": "test should pass despite rearrangement" },
{ "doc": {"foo": [{"foo": 1, "bar": 2}]},
"patch": [{"op": "test", "path": "/foo", "value": [{"bar": 2, "foo": 1}]}],
"expected": {"foo": [{"foo": 1, "bar": 2}]},
"comment": "test should pass despite (nested) rearrangement" },
{ "doc": {"foo": {"bar": [1, 2, 5, 4]}},
"patch": [{"op": "test", "path": "/foo", "value": {"bar": [1, 2, 5, 4]}}],
"expected": {"foo": {"bar": [1, 2, 5, 4]}},
"comment": "test should pass - no error" },
{ "doc": {"foo": {"bar": [1, 2, 5, 4]}},
@@ -264,7 +268,8 @@
{ "comment": "Empty-string element",
"doc": { "": 1 },
"patch": [{"op": "test", "path": "/", "value": 1}] },
"patch": [{"op": "test", "path": "/", "value": 1}],
"expected": { "": 1 } },
{ "doc": {
"foo": ["bar", "baz"],
@@ -288,8 +293,23 @@
{"op": "test", "path": "/i\\j", "value": 5},
{"op": "test", "path": "/k\"l", "value": 6},
{"op": "test", "path": "/ ", "value": 7},
{"op": "test", "path": "/m~0n", "value": 8}] },
{"op": "test", "path": "/m~0n", "value": 8}],
"expected": {
"": 0,
" ": 7,
"a/b": 1,
"c%d": 2,
"e^f": 3,
"foo": [
"bar",
"baz"
],
"g|h": 4,
"i\\j": 5,
"k\"l": 6,
"m~n": 8
}
},
{ "comment": "Move to same location has no effect",
"doc": {"foo": 1},
"patch": [{"op": "move", "from": "/foo", "path": "/foo"}],
@@ -388,11 +408,21 @@
"patch": [ { "op": "copy", "path": "/-" } ],
"error": "missing 'from' parameter" },
{ "comment": "missing from location to copy",
"doc": { "foo": 1 },
"patch": [ { "op": "copy", "from": "/bar", "path": "/foo" } ],
"error": "missing 'from' location" },
{ "comment": "missing from parameter to move",
"doc": { "foo": 1 },
"patch": [ { "op": "move", "path": "" } ],
"error": "missing 'from' parameter" },
{ "comment": "missing from location to move",
"doc": { "foo": 1 },
"patch": [ { "op": "move", "from": "/bar", "path": "/foo" } ],
"error": "missing 'from' location" },
{ "comment": "duplicate ops",
"doc": { "foo": "bar" },
"patch": [ { "op": "add", "path": "/baz", "value": "qux",

View File

@@ -66,7 +66,7 @@ static cJSON_bool test_apply_patch(const cJSON * const test)
}
else
{
printf("Testing unkown\n");
printf("Testing unknown\n");
}
disabled = cJSON_GetObjectItemCaseSensitive(test, "disabled");

174
tests/minify_tests.c Normal file
View File

@@ -0,0 +1,174 @@
/*
Copyright (c) 2009-2019 Dave Gamble and cJSON contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "unity/examples/unity_config.h"
#include "unity/src/unity.h"
#include "common.h"
static void cjson_minify_should_not_overflow_buffer(void)
{
char unclosed_multiline_comment[] = "/* bla";
char pending_escape[] = "\"\\";
cJSON_Minify(unclosed_multiline_comment);
TEST_ASSERT_EQUAL_STRING("", unclosed_multiline_comment);
cJSON_Minify(pending_escape);
TEST_ASSERT_EQUAL_STRING("\"\\", pending_escape);
}
static void cjson_minify_should_remove_single_line_comments(void)
{
const char to_minify[] = "{// this is {} \"some kind\" of [] comment /*, don't you see\n}";
char* minified = (char*) malloc(sizeof(to_minify));
TEST_ASSERT_NOT_NULL(minified);
strcpy(minified, to_minify);
cJSON_Minify(minified);
TEST_ASSERT_EQUAL_STRING("{}", minified);
free(minified);
}
static void cjson_minify_should_remove_spaces(void)
{
const char to_minify[] = "{ \"key\":\ttrue\r\n }";
char* minified = (char*) malloc(sizeof(to_minify));
TEST_ASSERT_NOT_NULL(minified);
strcpy(minified, to_minify);
cJSON_Minify(minified);
TEST_ASSERT_EQUAL_STRING("{\"key\":true}", minified);
free(minified);
}
static void cjson_minify_should_remove_multiline_comments(void)
{
const char to_minify[] = "{/* this is\n a /* multi\n //line \n {comment \"\\\" */}";
char* minified = (char*) malloc(sizeof(to_minify));
TEST_ASSERT_NOT_NULL(minified);
strcpy(minified, to_minify);
cJSON_Minify(minified);
TEST_ASSERT_EQUAL_STRING("{}", minified);
free(minified);
}
static void cjson_minify_should_not_modify_strings(void)
{
const char to_minify[] = "\"this is a string \\\" \\t bla\"";
char* minified = (char*) malloc(sizeof(to_minify));
TEST_ASSERT_NOT_NULL(minified);
strcpy(minified, to_minify);
cJSON_Minify(minified);
TEST_ASSERT_EQUAL_STRING(to_minify, minified);
free(minified);
}
static void cjson_minify_should_minify_json(void) {
const char to_minify[] =
"{\n"
" \"glossary\": { // comment\n"
" \"title\": \"example glossary\",\n"
" /* multi\n"
" line */\n"
" \"GlossDiv\": {\n"
" \"title\": \"S\",\n"
" \"GlossList\": {\n"
" \"GlossEntry\": {\n"
" \"ID\": \"SGML\",\n"
" \"SortAs\": \"SGML\",\n"
" \"Acronym\": \"SGML\",\n"
" \"Abbrev\": \"ISO 8879:1986\",\n"
" \"GlossDef\": {\n"
" \"GlossSeeAlso\": [\"GML\", \"XML\"]\n"
" },\n"
" \"GlossSee\": \"markup\"\n"
" }\n"
" }\n"
" }\n"
" }\n"
"}";
const char* minified =
"{"
"\"glossary\":{"
"\"title\":\"example glossary\","
"\"GlossDiv\":{"
"\"title\":\"S\","
"\"GlossList\":{"
"\"GlossEntry\":{"
"\"ID\":\"SGML\","
"\"SortAs\":\"SGML\","
"\"Acronym\":\"SGML\","
"\"Abbrev\":\"ISO 8879:1986\","
"\"GlossDef\":{"
"\"GlossSeeAlso\":[\"GML\",\"XML\"]"
"},"
"\"GlossSee\":\"markup\""
"}"
"}"
"}"
"}"
"}";
char *buffer = (char*) malloc(sizeof(to_minify));
strcpy(buffer, to_minify);
cJSON_Minify(buffer);
TEST_ASSERT_EQUAL_STRING(minified, buffer);
free(buffer);
}
static void cjson_minify_should_not_loop_infinitely(void) {
char string[] = { '8', ' ', '/', ' ', '5', '\n', '\0' };
/* this should not be an infinite loop */
cJSON_Minify(string);
}
int CJSON_CDECL main(void)
{
UNITY_BEGIN();
RUN_TEST(cjson_minify_should_not_overflow_buffer);
RUN_TEST(cjson_minify_should_minify_json);
RUN_TEST(cjson_minify_should_remove_single_line_comments);
RUN_TEST(cjson_minify_should_remove_multiline_comments);
RUN_TEST(cjson_minify_should_remove_spaces);
RUN_TEST(cjson_minify_should_not_modify_strings);
RUN_TEST(cjson_minify_should_not_loop_infinitely);
return UNITY_END();
}

View File

@@ -28,7 +28,6 @@
#include "unity/src/unity.h"
#include "common.h"
static void cjson_array_foreach_should_loop_over_arrays(void)
{
cJSON array[1];
@@ -77,7 +76,6 @@ static void cjson_get_object_item_should_get_object_items(void)
found = cJSON_GetObjectItem(item, NULL);
TEST_ASSERT_NULL_MESSAGE(found, "Failed to fail on NULL string.");
found = cJSON_GetObjectItem(item, "one");
TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find first item.");
TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 1);
@@ -127,6 +125,30 @@ static void cjson_get_object_item_case_sensitive_should_get_object_items(void)
cJSON_Delete(item);
}
static void cjson_get_object_item_should_not_crash_with_array(void)
{
cJSON *array = NULL;
cJSON *found = NULL;
array = cJSON_Parse("[1]");
found = cJSON_GetObjectItem(array, "name");
TEST_ASSERT_NULL(found);
cJSON_Delete(array);
}
static void cjson_get_object_item_case_sensitive_should_not_crash_with_array(void)
{
cJSON *array = NULL;
cJSON *found = NULL;
array = cJSON_Parse("[1]");
found = cJSON_GetObjectItemCaseSensitive(array, "name");
TEST_ASSERT_NULL(found);
cJSON_Delete(array);
}
static void typecheck_functions_should_check_type(void)
{
cJSON invalid[1];
@@ -197,6 +219,23 @@ static void cjson_should_not_parse_to_deeply_nested_jsons(void)
TEST_ASSERT_NULL_MESSAGE(cJSON_Parse(deep_json), "To deep JSONs should not be parsed.");
}
static void cjson_should_not_follow_too_deep_circular_references(void)
{
cJSON *o = cJSON_CreateArray();
cJSON *a = cJSON_CreateArray();
cJSON *b = cJSON_CreateArray();
cJSON *x;
cJSON_AddItemToArray(o, a);
cJSON_AddItemToArray(a, b);
cJSON_AddItemToArray(b, o);
x = cJSON_Duplicate(o, 1);
TEST_ASSERT_NULL(x);
cJSON_DetachItemFromArray(b, 0);
cJSON_Delete(o);
}
static void cjson_set_number_value_should_set_numbers(void)
{
cJSON number[1] = {{NULL, NULL, NULL, cJSON_Number, NULL, 0, 0, NULL}};
@@ -233,6 +272,7 @@ static void cjson_detach_item_via_pointer_should_detach_items(void)
list[3].prev = &(list[2]);
list[2].prev = &(list[1]);
list[1].prev = &(list[0]);
list[0].prev = &(list[3]);
parent->child = &list[0];
@@ -244,7 +284,7 @@ static void cjson_detach_item_via_pointer_should_detach_items(void)
/* detach beginning (list[0]) */
TEST_ASSERT_TRUE_MESSAGE(cJSON_DetachItemViaPointer(parent, &(list[0])) == &(list[0]), "Failed to detach beginning.");
TEST_ASSERT_TRUE_MESSAGE((list[0].prev == NULL) && (list[0].next == NULL), "Didn't set pointers of detached item to NULL.");
TEST_ASSERT_TRUE_MESSAGE((list[2].prev == NULL) && (parent->child == &(list[2])), "Didn't set the new beginning.");
TEST_ASSERT_TRUE_MESSAGE((list[2].prev == &(list[3])) && (parent->child == &(list[2])), "Didn't set the new beginning.");
/* detach end (list[3])*/
TEST_ASSERT_TRUE_MESSAGE(cJSON_DetachItemViaPointer(parent, &(list[3])) == &(list[3]), "Failed to detach end.");
@@ -257,6 +297,21 @@ static void cjson_detach_item_via_pointer_should_detach_items(void)
TEST_ASSERT_NULL_MESSAGE(parent->child, "Child of the parent wasn't set to NULL.");
}
static void cjson_detach_item_via_pointer_should_return_null_if_item_prev_is_null(void)
{
cJSON list[2];
cJSON parent[1];
memset(list, '\0', sizeof(list));
/* link the list */
list[0].next = &(list[1]);
parent->child = &list[0];
TEST_ASSERT_NULL_MESSAGE(cJSON_DetachItemViaPointer(parent, &(list[1])), "Failed to detach in the middle.");
TEST_ASSERT_TRUE_MESSAGE(cJSON_DetachItemViaPointer(parent, &(list[0])) == &(list[0]), "Failed to detach in the middle.");
}
static void cjson_replace_item_via_pointer_should_replace_items(void)
{
cJSON replacements[3];
@@ -279,12 +334,11 @@ static void cjson_replace_item_via_pointer_should_replace_items(void)
cJSON_AddItemToArray(array, middle);
cJSON_AddItemToArray(array, end);
memset(replacements, '\0', sizeof(replacements));
/* replace beginning */
TEST_ASSERT_TRUE(cJSON_ReplaceItemViaPointer(array, beginning, &(replacements[0])));
TEST_ASSERT_NULL(replacements[0].prev);
TEST_ASSERT_TRUE(replacements[0].prev == end);
TEST_ASSERT_TRUE(replacements[0].next == middle);
TEST_ASSERT_TRUE(middle->prev == &(replacements[0]));
TEST_ASSERT_TRUE(array->child == &(replacements[0]));
@@ -309,13 +363,15 @@ static void cjson_replace_item_in_object_should_preserve_name(void)
cJSON root[1] = {{NULL, NULL, NULL, 0, NULL, 0, 0, NULL}};
cJSON *child = NULL;
cJSON *replacement = NULL;
cJSON_bool flag = false;
child = cJSON_CreateNumber(1);
TEST_ASSERT_NOT_NULL(child);
replacement = cJSON_CreateNumber(2);
TEST_ASSERT_NOT_NULL(replacement);
cJSON_AddItemToObject(root, "child", child);
flag = cJSON_AddItemToObject(root, "child", child);
TEST_ASSERT_TRUE_MESSAGE(flag, "add item to object failed");
cJSON_ReplaceItemInObject(root, "child", replacement);
TEST_ASSERT_TRUE(root->child == replacement);
@@ -324,10 +380,23 @@ static void cjson_replace_item_in_object_should_preserve_name(void)
cJSON_Delete(replacement);
}
static void cjson_functions_shouldnt_crash_with_null_pointers(void)
static void cjson_functions_should_not_crash_with_null_pointers(void)
{
char buffer[10];
cJSON *item = cJSON_CreateString("item");
cJSON *array = cJSON_CreateArray();
cJSON *item1 = cJSON_CreateString("item1");
cJSON *item2 = cJSON_CreateString("corrupted array item3");
cJSON *corruptedString = cJSON_CreateString("corrupted");
struct cJSON *originalPrev;
add_item_to_array(array, item1);
add_item_to_array(array, item2);
originalPrev = item2->prev;
item2->prev = NULL;
free(corruptedString->valuestring);
corruptedString->valuestring = NULL;
cJSON_InitHooks(NULL);
TEST_ASSERT_NULL(cJSON_Parse(NULL));
@@ -387,30 +456,57 @@ static void cjson_functions_shouldnt_crash_with_null_pointers(void)
cJSON_DeleteItemFromObject(item, NULL);
cJSON_DeleteItemFromObjectCaseSensitive(NULL, "item");
cJSON_DeleteItemFromObjectCaseSensitive(item, NULL);
cJSON_InsertItemInArray(NULL, 0, item);
cJSON_InsertItemInArray(item, 0, NULL);
TEST_ASSERT_FALSE(cJSON_InsertItemInArray(array, 0, NULL));
TEST_ASSERT_FALSE(cJSON_InsertItemInArray(array, 1, item));
TEST_ASSERT_FALSE(cJSON_InsertItemInArray(NULL, 0, item));
TEST_ASSERT_FALSE(cJSON_InsertItemInArray(item, 0, NULL));
TEST_ASSERT_FALSE(cJSON_ReplaceItemViaPointer(NULL, item, item));
TEST_ASSERT_FALSE(cJSON_ReplaceItemViaPointer(item, NULL, item));
TEST_ASSERT_FALSE(cJSON_ReplaceItemViaPointer(item, item, NULL));
cJSON_ReplaceItemInArray(item, 0, NULL);
cJSON_ReplaceItemInArray(NULL, 0, item);
cJSON_ReplaceItemInObject(NULL, "item", item);
cJSON_ReplaceItemInObject(item, NULL, item);
cJSON_ReplaceItemInObject(item, "item", NULL);
cJSON_ReplaceItemInObjectCaseSensitive(NULL, "item", item);
cJSON_ReplaceItemInObjectCaseSensitive(item, NULL, item);
cJSON_ReplaceItemInObjectCaseSensitive(item, "item", NULL);
TEST_ASSERT_FALSE(cJSON_ReplaceItemInArray(item, 0, NULL));
TEST_ASSERT_FALSE(cJSON_ReplaceItemInArray(NULL, 0, item));
TEST_ASSERT_FALSE(cJSON_ReplaceItemInObject(NULL, "item", item));
TEST_ASSERT_FALSE(cJSON_ReplaceItemInObject(item, NULL, item));
TEST_ASSERT_FALSE(cJSON_ReplaceItemInObject(item, "item", NULL));
TEST_ASSERT_FALSE(cJSON_ReplaceItemInObjectCaseSensitive(NULL, "item", item));
TEST_ASSERT_FALSE(cJSON_ReplaceItemInObjectCaseSensitive(item, NULL, item));
TEST_ASSERT_FALSE(cJSON_ReplaceItemInObjectCaseSensitive(item, "item", NULL));
TEST_ASSERT_NULL(cJSON_Duplicate(NULL, true));
TEST_ASSERT_FALSE(cJSON_Compare(item, NULL, false));
TEST_ASSERT_FALSE(cJSON_Compare(NULL, item, false));
TEST_ASSERT_NULL(cJSON_SetValuestring(NULL, "test"));
TEST_ASSERT_NULL(cJSON_SetValuestring(corruptedString, "test"));
TEST_ASSERT_NULL(cJSON_SetValuestring(item, NULL));
cJSON_Minify(NULL);
/* skipped because it is only used via a macro that checks for NULL */
/* cJSON_SetNumberHelper(NULL, 0); */
/* restore corrupted item2 to delete it */
item2->prev = originalPrev;
cJSON_Delete(corruptedString);
cJSON_Delete(array);
cJSON_Delete(item);
}
static void *failing_realloc(void *pointer, size_t size)
static void cjson_set_valuestring_should_return_null_if_strings_overlap(void)
{
cJSON *obj;
char* str;
char* str2;
obj = cJSON_Parse("\"foo0z\"");
str = cJSON_SetValuestring(obj, "abcde");
str += 1;
/* The string passed to strcpy overlap which is not allowed.*/
str2 = cJSON_SetValuestring(obj, str);
/* If it overlaps, the string will be messed up.*/
TEST_ASSERT_TRUE(strcmp(str, "bcde") == 0);
TEST_ASSERT_NULL(str2);
cJSON_Delete(obj);
}
static void *CJSON_CDECL failing_realloc(void *pointer, size_t size)
{
(void)size;
(void)pointer;
@@ -463,7 +559,21 @@ static void cjson_get_string_value_should_get_a_string(void)
cJSON_Delete(string);
}
static void cjson_create_string_reference_should_create_a_string_reference(void) {
static void cjson_get_number_value_should_get_a_number(void)
{
cJSON *string = cJSON_CreateString("test");
cJSON *number = cJSON_CreateNumber(1);
TEST_ASSERT_EQUAL_DOUBLE(cJSON_GetNumberValue(number), number->valuedouble);
TEST_ASSERT_DOUBLE_IS_NAN(cJSON_GetNumberValue(string));
TEST_ASSERT_DOUBLE_IS_NAN(cJSON_GetNumberValue(NULL));
cJSON_Delete(number);
cJSON_Delete(string);
}
static void cjson_create_string_reference_should_create_a_string_reference(void)
{
const char *string = "I am a string!";
cJSON *string_reference = cJSON_CreateStringReference(string);
@@ -473,7 +583,8 @@ static void cjson_create_string_reference_should_create_a_string_reference(void)
cJSON_Delete(string_reference);
}
static void cjson_create_object_reference_should_create_an_object_reference(void) {
static void cjson_create_object_reference_should_create_an_object_reference(void)
{
cJSON *number_reference = NULL;
cJSON *number_object = cJSON_CreateObject();
cJSON *number = cJSON_CreateNumber(42);
@@ -491,7 +602,8 @@ static void cjson_create_object_reference_should_create_an_object_reference(void
cJSON_Delete(number_reference);
}
static void cjson_create_array_reference_should_create_an_array_reference(void) {
static void cjson_create_array_reference_should_create_an_array_reference(void)
{
cJSON *number_reference = NULL;
cJSON *number_array = cJSON_CreateArray();
cJSON *number = cJSON_CreateNumber(42);
@@ -508,6 +620,22 @@ static void cjson_create_array_reference_should_create_an_array_reference(void)
cJSON_Delete(number_reference);
}
static void cjson_add_item_to_object_or_array_should_not_add_itself(void)
{
cJSON *object = cJSON_CreateObject();
cJSON *array = cJSON_CreateArray();
cJSON_bool flag = false;
flag = cJSON_AddItemToObject(object, "key", object);
TEST_ASSERT_FALSE_MESSAGE(flag, "add an object to itself should fail");
flag = cJSON_AddItemToArray(array, array);
TEST_ASSERT_FALSE_MESSAGE(flag, "add an array to itself should fail");
cJSON_Delete(object);
cJSON_Delete(array);
}
static void cjson_add_item_to_object_should_not_use_after_free_when_string_is_aliased(void)
{
cJSON *object = cJSON_CreateObject();
@@ -527,7 +655,134 @@ static void cjson_add_item_to_object_should_not_use_after_free_when_string_is_al
cJSON_Delete(object);
}
int main(void)
static void cjson_delete_item_from_array_should_not_broken_list_structure(void)
{
const char expected_json1[] = "{\"rd\":[{\"a\":\"123\"}]}";
const char expected_json2[] = "{\"rd\":[{\"a\":\"123\"},{\"b\":\"456\"}]}";
const char expected_json3[] = "{\"rd\":[{\"b\":\"456\"}]}";
char *str1 = NULL;
char *str2 = NULL;
char *str3 = NULL;
cJSON *root = cJSON_Parse("{}");
cJSON *array = cJSON_AddArrayToObject(root, "rd");
cJSON *item1 = cJSON_Parse("{\"a\":\"123\"}");
cJSON *item2 = cJSON_Parse("{\"b\":\"456\"}");
cJSON_AddItemToArray(array, item1);
str1 = cJSON_PrintUnformatted(root);
TEST_ASSERT_EQUAL_STRING(expected_json1, str1);
free(str1);
cJSON_AddItemToArray(array, item2);
str2 = cJSON_PrintUnformatted(root);
TEST_ASSERT_EQUAL_STRING(expected_json2, str2);
free(str2);
/* this should not broken list structure */
cJSON_DeleteItemFromArray(array, 0);
str3 = cJSON_PrintUnformatted(root);
TEST_ASSERT_EQUAL_STRING(expected_json3, str3);
free(str3);
cJSON_Delete(root);
}
static void cjson_set_valuestring_to_object_should_not_leak_memory(void)
{
cJSON *root = cJSON_Parse("{}");
const char *stringvalue = "valuestring could be changed safely";
const char *reference_valuestring = "reference item should be freed by yourself";
const char *short_valuestring = "shorter valuestring";
const char *long_valuestring = "new valuestring which much longer than previous should be changed safely";
cJSON *item1 = cJSON_CreateString(stringvalue);
cJSON *item2 = cJSON_CreateStringReference(reference_valuestring);
char *ptr1 = NULL;
char *return_value = NULL;
cJSON_AddItemToObject(root, "one", item1);
cJSON_AddItemToObject(root, "two", item2);
ptr1 = item1->valuestring;
return_value = cJSON_SetValuestring(cJSON_GetObjectItem(root, "one"), short_valuestring);
TEST_ASSERT_NOT_NULL(return_value);
TEST_ASSERT_EQUAL_PTR_MESSAGE(ptr1, return_value, "new valuestring shorter than old should not reallocate memory");
TEST_ASSERT_EQUAL_STRING(short_valuestring, cJSON_GetObjectItem(root, "one")->valuestring);
/* we needn't to free the original valuestring manually */
ptr1 = item1->valuestring;
return_value = cJSON_SetValuestring(cJSON_GetObjectItem(root, "one"), long_valuestring);
TEST_ASSERT_NOT_NULL(return_value);
TEST_ASSERT_NOT_EQUAL_MESSAGE(ptr1, return_value, "new valuestring longer than old should reallocate memory")
TEST_ASSERT_EQUAL_STRING(long_valuestring, cJSON_GetObjectItem(root, "one")->valuestring);
return_value = cJSON_SetValuestring(cJSON_GetObjectItem(root, "two"), long_valuestring);
TEST_ASSERT_NULL_MESSAGE(return_value, "valuestring of reference object should not be changed");
TEST_ASSERT_EQUAL_STRING(reference_valuestring, cJSON_GetObjectItem(root, "two")->valuestring);
cJSON_Delete(root);
}
static void cjson_set_bool_value_must_not_break_objects(void)
{
cJSON *bobj, *sobj, *oobj, *refobj = NULL;
TEST_ASSERT_TRUE((cJSON_SetBoolValue(refobj, 1) == cJSON_Invalid));
bobj = cJSON_CreateFalse();
TEST_ASSERT_TRUE(cJSON_IsFalse(bobj));
TEST_ASSERT_TRUE((cJSON_SetBoolValue(bobj, 1) == cJSON_True));
TEST_ASSERT_TRUE(cJSON_IsTrue(bobj));
cJSON_SetBoolValue(bobj, 1);
TEST_ASSERT_TRUE(cJSON_IsTrue(bobj));
TEST_ASSERT_TRUE((cJSON_SetBoolValue(bobj, 0) == cJSON_False));
TEST_ASSERT_TRUE(cJSON_IsFalse(bobj));
cJSON_SetBoolValue(bobj, 0);
TEST_ASSERT_TRUE(cJSON_IsFalse(bobj));
sobj = cJSON_CreateString("test");
TEST_ASSERT_TRUE(cJSON_IsString(sobj));
cJSON_SetBoolValue(sobj, 1);
TEST_ASSERT_TRUE(cJSON_IsString(sobj));
cJSON_SetBoolValue(sobj, 0);
TEST_ASSERT_TRUE(cJSON_IsString(sobj));
oobj = cJSON_CreateObject();
TEST_ASSERT_TRUE(cJSON_IsObject(oobj));
cJSON_SetBoolValue(oobj, 1);
TEST_ASSERT_TRUE(cJSON_IsObject(oobj));
cJSON_SetBoolValue(oobj, 0);
TEST_ASSERT_TRUE(cJSON_IsObject(oobj));
refobj = cJSON_CreateStringReference("conststring");
TEST_ASSERT_TRUE(cJSON_IsString(refobj));
TEST_ASSERT_TRUE(refobj->type & cJSON_IsReference);
cJSON_SetBoolValue(refobj, 1);
TEST_ASSERT_TRUE(cJSON_IsString(refobj));
TEST_ASSERT_TRUE(refobj->type & cJSON_IsReference);
cJSON_SetBoolValue(refobj, 0);
TEST_ASSERT_TRUE(cJSON_IsString(refobj));
TEST_ASSERT_TRUE(refobj->type & cJSON_IsReference);
cJSON_Delete(refobj);
refobj = cJSON_CreateObjectReference(oobj);
TEST_ASSERT_TRUE(cJSON_IsObject(refobj));
TEST_ASSERT_TRUE(refobj->type & cJSON_IsReference);
cJSON_SetBoolValue(refobj, 1);
TEST_ASSERT_TRUE(cJSON_IsObject(refobj));
TEST_ASSERT_TRUE(refobj->type & cJSON_IsReference);
cJSON_SetBoolValue(refobj, 0);
TEST_ASSERT_TRUE(cJSON_IsObject(refobj));
TEST_ASSERT_TRUE(refobj->type & cJSON_IsReference);
cJSON_Delete(refobj);
cJSON_Delete(oobj);
cJSON_Delete(bobj);
cJSON_Delete(sobj);
}
int CJSON_CDECL main(void)
{
UNITY_BEGIN();
@@ -535,21 +790,31 @@ int main(void)
RUN_TEST(cjson_array_foreach_should_not_dereference_null_pointer);
RUN_TEST(cjson_get_object_item_should_get_object_items);
RUN_TEST(cjson_get_object_item_case_sensitive_should_get_object_items);
RUN_TEST(cjson_get_object_item_should_not_crash_with_array);
RUN_TEST(cjson_get_object_item_case_sensitive_should_not_crash_with_array);
RUN_TEST(typecheck_functions_should_check_type);
RUN_TEST(cjson_should_not_parse_to_deeply_nested_jsons);
RUN_TEST(cjson_should_not_follow_too_deep_circular_references);
RUN_TEST(cjson_set_number_value_should_set_numbers);
RUN_TEST(cjson_detach_item_via_pointer_should_detach_items);
RUN_TEST(cjson_detach_item_via_pointer_should_return_null_if_item_prev_is_null);
RUN_TEST(cjson_replace_item_via_pointer_should_replace_items);
RUN_TEST(cjson_replace_item_in_object_should_preserve_name);
RUN_TEST(cjson_functions_shouldnt_crash_with_null_pointers);
RUN_TEST(cjson_functions_should_not_crash_with_null_pointers);
RUN_TEST(cjson_set_valuestring_should_return_null_if_strings_overlap);
RUN_TEST(ensure_should_fail_on_failed_realloc);
RUN_TEST(skip_utf8_bom_should_skip_bom);
RUN_TEST(skip_utf8_bom_should_not_skip_bom_if_not_at_beginning);
RUN_TEST(cjson_get_string_value_should_get_a_string);
RUN_TEST(cjson_get_number_value_should_get_a_number);
RUN_TEST(cjson_create_string_reference_should_create_a_string_reference);
RUN_TEST(cjson_create_object_reference_should_create_an_object_reference);
RUN_TEST(cjson_create_array_reference_should_create_an_array_reference);
RUN_TEST(cjson_add_item_to_object_or_array_should_not_add_itself);
RUN_TEST(cjson_add_item_to_object_should_not_use_after_free_when_string_is_aliased);
RUN_TEST(cjson_delete_item_from_array_should_not_broken_list_structure);
RUN_TEST(cjson_set_valuestring_to_object_should_not_leak_memory);
RUN_TEST(cjson_set_bool_value_must_not_break_objects);
return UNITY_END();
}

View File

@@ -90,6 +90,10 @@ static void misc_tests(void)
/* Misc tests */
int numbers[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
cJSON *object = NULL;
cJSON *object1 = NULL;
cJSON *object2 = NULL;
cJSON *object3 = NULL;
cJSON *object4 = NULL;
cJSON *nums = NULL;
cJSON *num6 = NULL;
char *pointer = NULL;
@@ -112,7 +116,23 @@ static void misc_tests(void)
TEST_ASSERT_EQUAL_STRING("", pointer);
free(pointer);
object1 = cJSON_CreateObject();
object2 = cJSON_CreateString("m~n");
cJSON_AddItemToObject(object1, "m~n", object2);
pointer = cJSONUtils_FindPointerFromObjectTo(object1, object2);
TEST_ASSERT_EQUAL_STRING("/m~0n",pointer);
free(pointer);
object3 = cJSON_CreateObject();
object4 = cJSON_CreateString("m/n");
cJSON_AddItemToObject(object3, "m/n", object4);
pointer = cJSONUtils_FindPointerFromObjectTo(object3, object4);
TEST_ASSERT_EQUAL_STRING("/m~1n",pointer);
free(pointer);
cJSON_Delete(object);
cJSON_Delete(object1);
cJSON_Delete(object3);
}
static void sort_tests(void)

View File

@@ -90,7 +90,8 @@ static void parse_array_should_parse_arrays_with_one_element(void)
assert_parse_array("[[]]");
assert_has_child(item);
assert_is_array(item->child);
TEST_ASSERT_NOT_NULL(item->child);
assert_has_type(item->child, cJSON_Array);
assert_has_no_child(item->child);
reset(item);
@@ -152,7 +153,7 @@ static void parse_array_should_not_parse_non_arrays(void)
assert_not_array("\"[]hello world!\n\"");
}
int main(void)
int CJSON_CDECL main(void)
{
/* initialize cJSON item */
memset(item, 0, sizeof(cJSON));

View File

@@ -195,7 +195,89 @@ static void test12_should_not_be_parsed(void)
}
}
int main(void)
static void test13_should_be_parsed_without_null_termination(void)
{
cJSON *tree = NULL;
const char test_13[] = "{" \
"\"Image\":{" \
"\"Width\":800," \
"\"Height\":600," \
"\"Title\":\"Viewfrom15thFloor\"," \
"\"Thumbnail\":{" \
"\"Url\":\"http:/*www.example.com/image/481989943\"," \
"\"Height\":125," \
"\"Width\":\"100\"" \
"}," \
"\"IDs\":[116,943,234,38793]" \
"}" \
"}";
char test_13_wo_null[sizeof(test_13) - 1];
memcpy(test_13_wo_null, test_13, sizeof(test_13) - 1);
tree = cJSON_ParseWithLength(test_13_wo_null, sizeof(test_13) - 1);
TEST_ASSERT_NOT_NULL_MESSAGE(tree, "Failed to parse valid json.");
if (tree != NULL)
{
cJSON_Delete(tree);
}
}
static void test14_should_not_be_parsed(void)
{
cJSON *tree = NULL;
const char test_14[] = "{" \
"\"Image\":{" \
"\"Width\":800," \
"\"Height\":600," \
"\"Title\":\"Viewfrom15thFloor\"," \
"\"Thumbnail\":{" \
"\"Url\":\"http:/*www.example.com/image/481989943\"," \
"\"Height\":125," \
"\"Width\":\"100\"" \
"}," \
"\"IDs\":[116,943,234,38793]" \
"}" \
"}";
tree = cJSON_ParseWithLength(test_14, sizeof(test_14) - 2);
TEST_ASSERT_NULL_MESSAGE(tree, "Should not continue after buffer_length is reached.");
if (tree != NULL)
{
cJSON_Delete(tree);
}
}
/* Address Sanitizer */
static void test15_should_not_heap_buffer_overflow(void)
{
const char *strings[] = {
"{\"1\":1,",
"{\"1\":1, ",
};
size_t i;
for (i = 0; i < sizeof(strings) / sizeof(strings[0]); i+=1)
{
const char *json_string = strings[i];
size_t len = strlen(json_string);
cJSON *json = NULL;
char *exact_size_heap = (char*)malloc(len);
TEST_ASSERT_NOT_NULL(exact_size_heap);
memcpy(exact_size_heap, json_string, len);
json = cJSON_ParseWithLength(exact_size_heap, len);
cJSON_Delete(json);
free(exact_size_heap);
}
}
int CJSON_CDECL main(void)
{
UNITY_BEGIN();
RUN_TEST(file_test1_should_be_parsed_and_printed);
@@ -210,5 +292,8 @@ int main(void)
RUN_TEST(file_test10_should_be_parsed_and_printed);
RUN_TEST(file_test11_should_be_parsed_and_printed);
RUN_TEST(test12_should_not_be_parsed);
RUN_TEST(test13_should_be_parsed_without_null_termination);
RUN_TEST(test14_should_not_be_parsed);
RUN_TEST(test15_should_not_heap_buffer_overflow);
return UNITY_END();
}

View File

@@ -64,7 +64,7 @@ static void parse_hex4_should_parse_mixed_case(void)
TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"BEEF"));
}
int main(void)
int CJSON_CDECL main(void)
{
UNITY_BEGIN();
RUN_TEST(parse_hex4_should_parse_all_combinations);

View File

@@ -96,7 +96,7 @@ static void parse_number_should_parse_negative_reals(void)
assert_parse_number("-123e-128", 0, -123e-128);
}
int main(void)
int CJSON_CDECL main(void)
{
/* initialize cJSON item */
memset(item, 0, sizeof(cJSON));

View File

@@ -162,7 +162,7 @@ static void parse_object_should_not_parse_non_objects(void)
assert_not_object("\"{}hello world!\n\"");
}
int main(void)
int CJSON_CDECL main(void)
{
/* initialize cJSON item */
memset(item, 0, sizeof(cJSON));

View File

@@ -119,7 +119,7 @@ static void parse_string_should_parse_bug_94(void)
reset(item);
}
int main(void)
int CJSON_CDECL main(void)
{
/* initialize cJSON item and error pointer */
memset(item, 0, sizeof(cJSON));

View File

@@ -96,7 +96,7 @@ static void parse_value_should_parse_object(void)
reset(item);
}
int main(void)
int CJSON_CDECL main(void)
{
/* initialize cJSON item */
memset(item, 0, sizeof(cJSON));

View File

@@ -97,7 +97,7 @@ static void parse_with_opts_should_parse_utf8_bom(void)
cJSON_Delete(without_bom);
}
int main(void)
int CJSON_CDECL main(void)
{
UNITY_BEGIN();

View File

@@ -87,7 +87,7 @@ static void print_array_should_print_arrays_with_multiple_elements(void)
assert_print_array("[1, null, true, false, [], \"hello\", {\n\t}]", "[1,null,true,false,[],\"hello\",{}]");
}
int main(void)
int CJSON_CDECL main(void)
{
/* initialize cJSON item */
UNITY_BEGIN();

View File

@@ -27,6 +27,8 @@
static void assert_print_number(const char *expected, double input)
{
unsigned char printed[1024];
unsigned char new_buffer[26];
unsigned int i = 0;
cJSON item[1];
printbuffer buffer = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
buffer.buffer = printed;
@@ -34,11 +36,29 @@ static void assert_print_number(const char *expected, double input)
buffer.offset = 0;
buffer.noalloc = true;
buffer.hooks = global_hooks;
buffer.buffer = new_buffer;
memset(item, 0, sizeof(item));
memset(new_buffer, 0, sizeof(new_buffer));
cJSON_SetNumberValue(item, input);
TEST_ASSERT_TRUE_MESSAGE(print_number(item, &buffer), "Failed to print number.");
/* In MinGW or visual studio(before 2015),the exponten is represented using three digits,like:"1e-009","1e+017"
* remove extra "0" to output "1e-09" or "1e+17",which makes testcase PASS */
for(i = 0;i <sizeof(new_buffer);i++)
{
if(i >3 && new_buffer[i] =='0')
{
if((new_buffer[i-3] =='e' && new_buffer[i-2] == '-' && new_buffer[i] =='0') ||(new_buffer[i-2] =='e' && new_buffer[i-1] =='+'))
{
while(new_buffer[i] !='\0')
{
new_buffer[i] = new_buffer[i+1];
i++;
}
}
}
}
TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, buffer.buffer, "Printed number is not as expected.");
}
@@ -89,7 +109,7 @@ static void print_number_should_print_non_number(void)
/* assert_print_number("null", -INFTY); */
}
int main(void)
int CJSON_CDECL main(void)
{
/* initialize cJSON item */
UNITY_BEGIN();

View File

@@ -63,7 +63,7 @@ static void assert_print_object(const char * const expected, const char * const
formatted_buffer.format = true;
TEST_ASSERT_TRUE_MESSAGE(print_object(item, &formatted_buffer), "Failed to print formatted string.");
TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, printed_formatted, "Formatted ojbect is not correct.");
TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, printed_formatted, "Formatted object is not correct.");
reset(item);
}
@@ -88,7 +88,7 @@ static void print_object_should_print_objects_with_multiple_elements(void)
assert_print_object("{\n\t\"one\":\t1,\n\t\"NULL\":\tnull,\n\t\"TRUE\":\ttrue,\n\t\"FALSE\":\tfalse,\n\t\"array\":\t[],\n\t\"world\":\t\"hello\",\n\t\"object\":\t{\n\t}\n}", "{\"one\":1,\"NULL\":null,\"TRUE\":true,\"FALSE\":false,\"array\":[],\"world\":\"hello\",\"object\":{}}");
}
int main(void)
int CJSON_CDECL main(void)
{
/* initialize cJSON item */
UNITY_BEGIN();

View File

@@ -65,7 +65,7 @@ static void print_string_should_print_utf8(void)
assert_print_string("\"ü猫慕\"", "ü猫慕");
}
int main(void)
int CJSON_CDECL main(void)
{
/* initialize cJSON item */
UNITY_BEGIN();

View File

@@ -90,7 +90,7 @@ static void print_value_should_print_object(void)
assert_print_value("{}");
}
int main(void)
int CJSON_CDECL main(void)
{
/* initialize cJSON item */
UNITY_BEGIN();

View File

@@ -69,7 +69,7 @@ static char* create_monitor(void)
goto end;
}
/* after creation was successful, immediately add it to the monitor,
* thereby transfering ownership of the pointer to it */
* thereby transferring ownership of the pointer to it */
cJSON_AddItemToObject(monitor, "name", name);
resolutions = cJSON_CreateArray();
@@ -202,7 +202,7 @@ static int supports_full_hd(const char * const monitor)
goto end;
}
if ((width->valuedouble == 1920) && (height->valuedouble == 1080))
if (compare_double(width->valuedouble, 1920) && compare_double(height->valuedouble, 1080))
{
status = 1;
goto end;
@@ -246,7 +246,7 @@ static void supports_full_hd_should_check_for_full_hd_support(void)
TEST_ASSERT_FALSE(supports_full_hd(monitor_without_hd));
}
int main(void)
int CJSON_CDECL main(void)
{
UNITY_BEGIN();

View File

@@ -78,7 +78,7 @@ class ParseOutput
@array_list.push ' <testcase classname="' + test_suite + '" name="' + test_name + '"/>'
end
# Test was flagged as being ingored so format the output
# Test was flagged as being ignored so format the output
def test_ignored(array)
last_item = array.length - 1
test_name = array[last_item - 2]

View File

@@ -2,7 +2,7 @@ Eclipse error parsers
=====================
These are a godsend for extracting & quickly navigating to
warnings & error messages from console output. Unforunately
warnings & error messages from console output. Unfortunately
I don't know how to write an Eclipse plugin so you'll have
to add them manually.

View File

@@ -8,7 +8,7 @@
#include "unity.h"
#include <stddef.h>
/* If omitted from header, declare overrideable prototypes here so they're ready for use */
/* If omitted from header, declare overridable prototypes here so they're ready for use */
#ifdef UNITY_OMIT_OUTPUT_CHAR_HEADER_DECLARATION
void UNITY_OUTPUT_CHAR(int);
#endif
@@ -268,14 +268,14 @@ void UnityPrintFloat(const UNITY_DOUBLE input_number)
UNITY_DOUBLE number = input_number;
/* print minus sign (including for negative zero) */
if (number < 0.0f || (number == 0.0f && 1.0f / number < 0.0f))
if (number < (double)0.0f || (number == (double)0.0f && (double)1.0f / number < (double)0.0f))
{
UNITY_OUTPUT_CHAR('-');
number = -number;
}
/* handle zero, NaN, and +/- infinity */
if (number == 0.0f) UnityPrint("0");
if (number == (double)0.0f) UnityPrint("0");
else if (isnan(number)) UnityPrint("nan");
else if (isinf(number)) UnityPrint("inf");
else
@@ -286,10 +286,10 @@ void UnityPrintFloat(const UNITY_DOUBLE input_number)
char buf[16];
/* scale up or down by powers of 10 */
while (number < 100000.0f / 1e6f) { number *= 1e6f; exponent -= 6; }
while (number < 100000.0f) { number *= 10.0f; exponent--; }
while (number > 1000000.0f * 1e6f) { number /= 1e6f; exponent += 6; }
while (number > 1000000.0f) { number /= 10.0f; exponent++; }
while (number < (double)(100000.0f / 1e6f)) { number *= (double)1e6f; exponent -= 6; }
while (number < (double)100000.0f) { number *= (double)10.0f; exponent--; }
while (number > (double)(1000000.0f * 1e6f)) { number /= (double)1e6f; exponent += 6; }
while (number > (double)1000000.0f) { number /= (double)10.0f; exponent++; }
/* round to nearest integer */
n = ((UNITY_INT32)(number + number) + 1) / 2;

View File

@@ -26,7 +26,7 @@ task :prepare_for_tests => TEMP_DIRS
include RakefileHelpers
# Load proper GCC as defult configuration
# Load proper GCC as default configuration
DEFAULT_CONFIG_FILE = 'gcc_auto_stdint.yml'
configure_toolchain(DEFAULT_CONFIG_FILE)

3
tests/unity_setup.c Normal file
View File

@@ -0,0 +1,3 @@
// msvc doesn't support weak-linking, so we need to define these functions.
void setUp(void) { }
void tearDown(void) { }