Compare commits

...

57 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
24 changed files with 510 additions and 77 deletions

3
.gitattributes vendored
View File

@@ -6,3 +6,6 @@
.github export-ignore .github export-ignore
.editorconfig export-ignore .editorconfig export-ignore
.travis.yml export-ignore .travis.yml export-ignore
# Linguist incorrectly identified the headers as C++, manually override this.
*.h linguist-language=C

View File

@@ -31,7 +31,7 @@ jobs:
- name: install build dependencies - name: install build dependencies
run: | run: |
sudo apt-get update sudo apt-get update
sudo apt-get install clang-8 valgrind sudo apt-get install clang-14 valgrind
- name: build and test - name: build and test
shell: bash shell: bash
run: | run: |

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

4
.gitignore vendored
View File

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

View File

@@ -1,3 +1,49 @@
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) 1.7.14 (Sep 3, 2020)
====== ======
Fixes: Fixes:

View File

@@ -1,17 +1,16 @@
set(CMAKE_LEGACY_CYGWIN_WIN32 0) 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) include(GNUInstallDirs)
set(PROJECT_VERSION_MAJOR 1)
set(PROJECT_VERSION_MINOR 7)
set(PROJECT_VERSION_PATCH 14)
set(CJSON_VERSION_SO 1) set(CJSON_VERSION_SO 1)
set(CJSON_UTILS_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) set(custom_compiler_flags)
@@ -71,7 +70,6 @@ if (ENABLE_SANITIZERS)
-fsanitize=float-cast-overflow -fsanitize=float-cast-overflow
-fsanitize-address-use-after-scope -fsanitize-address-use-after-scope
-fsanitize=integer -fsanitize=integer
-01
-fno-sanitize-recover -fno-sanitize-recover
) )
endif() endif()
@@ -103,13 +101,10 @@ foreach(compiler_flag ${custom_compiler_flags})
CHECK_C_COMPILER_FLAG(${compiler_flag} "FLAG_SUPPORTED_${current_variable}") CHECK_C_COMPILER_FLAG(${compiler_flag} "FLAG_SUPPORTED_${current_variable}")
if (FLAG_SUPPORTED_${current_variable}) if (FLAG_SUPPORTED_${current_variable})
list(APPEND supported_compiler_flags)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${compiler_flag}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${compiler_flag}")
endif() endif()
endforeach() endforeach()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${supported_compiler_flags}")
option(BUILD_SHARED_LIBS "Build shared libraries" ON) option(BUILD_SHARED_LIBS "Build shared libraries" ON)
option(ENABLE_TARGET_EXPORT "Enable exporting of CMake targets. Disable when it causes problems!" ON) option(ENABLE_TARGET_EXPORT "Enable exporting of CMake targets. Disable when it causes problems!" ON)
@@ -122,6 +117,7 @@ set(SOURCES cJSON.c)
option(BUILD_SHARED_AND_STATIC_LIBS "Build both shared and static libraries" Off) 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_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(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)) 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) set(CJSON_LIBRARY_TYPE SHARED)
@@ -156,17 +152,23 @@ install(TARGETS "${CJSON_LIB}"
INCLUDES DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}" INCLUDES DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}"
) )
if (BUILD_SHARED_AND_STATIC_LIBS) 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() endif()
if(ENABLE_TARGET_EXPORT) if(ENABLE_TARGET_EXPORT)
# export library information for CMake projects # export library information for CMake projects
install(EXPORT "${CJSON_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON") install(EXPORT "${CJSON_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON")
endif() endif()
set_target_properties("${CJSON_LIB}" if(ENABLE_CJSON_VERSION_SO)
PROPERTIES set_target_properties("${CJSON_LIB}"
SOVERSION "${CJSON_VERSION_SO}" PROPERTIES
VERSION "${PROJECT_VERSION}") SOVERSION "${CJSON_VERSION_SO}"
VERSION "${PROJECT_VERSION}")
endif()
#cJSON_Utils #cJSON_Utils
option(ENABLE_CJSON_UTILS "Enable building the cJSON_Utils library." OFF) option(ENABLE_CJSON_UTILS "Enable building the cJSON_Utils library." OFF)
@@ -199,7 +201,11 @@ if(ENABLE_CJSON_UTILS)
INCLUDES DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}" INCLUDES DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}"
) )
if (BUILD_SHARED_AND_STATIC_LIBS) 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() endif()
install(FILES cJSON_Utils.h DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/cjson") 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") install (FILES "${CMAKE_CURRENT_BINARY_DIR}/libcjson_utils.pc" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig")
@@ -208,10 +214,12 @@ if(ENABLE_CJSON_UTILS)
install(EXPORT "${CJSON_UTILS_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON") install(EXPORT "${CJSON_UTILS_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON")
endif() endif()
set_target_properties("${CJSON_UTILS_LIB}" if(ENABLE_CJSON_VERSION_SO)
PROPERTIES set_target_properties("${CJSON_UTILS_LIB}"
SOVERSION "${CJSON_UTILS_VERSION_SO}" PROPERTIES
VERSION "${PROJECT_VERSION}") SOVERSION "${CJSON_UTILS_VERSION_SO}"
VERSION "${PROJECT_VERSION}")
endif()
endif() endif()
# create the other package config files # create the other package config files
@@ -255,7 +263,11 @@ if(ENABLE_CJSON_TEST)
endif() endif()
#Create the uninstall target #Create the uninstall target
add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${PROJECT_SOURCE_DIR}/library_config/uninstall.cmake") 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 # Enable the use of locales
option(ENABLE_LOCALES "Enable the use of locales" ON) option(ENABLE_LOCALES "Enable the use of locales" ON)

View File

@@ -10,8 +10,10 @@ Current Maintainer:
Contributors: Contributors:
* [Ajay Bhargav](https://github.com/ajaybhargav) * [Ajay Bhargav](https://github.com/ajaybhargav)
* [AlexanderVasiljev](https://github.com/AlexanderVasiljev)
* [Alper Akcan](https://github.com/alperakcan) * [Alper Akcan](https://github.com/alperakcan)
* [Andrew Tang](https://github.com/singku) * [Andrew Tang](https://github.com/singku)
* [Andy](https://github.com/mlh0101)
* [Anton Sergeev](https://github.com/anton-sergeev) * [Anton Sergeev](https://github.com/anton-sergeev)
* [Benbuck Nason](https://github.com/bnason-nf) * [Benbuck Nason](https://github.com/bnason-nf)
* [Bernt Johan Damslora](https://github.com/bjda) * [Bernt Johan Damslora](https://github.com/bjda)
@@ -29,25 +31,33 @@ Contributors:
* [Fabrice Fontaine](https://github.com/ffontaine) * [Fabrice Fontaine](https://github.com/ffontaine)
* Ian Mobley * Ian Mobley
* Irwan Djadjadi * Irwan Djadjadi
* [hopper-vul](https://github.com/hopper-vul)
* [HuKeping](https://github.com/HuKeping) * [HuKeping](https://github.com/HuKeping)
* [IvanVoid](https://github.com/npi3pak) * [IvanVoid](https://github.com/npi3pak)
* [Jakub Wilk](https://github.com/jwilk) * [Jakub Wilk](https://github.com/jwilk)
* [Jiri Zouhar](https://github.com/loigu) * [Jiri Zouhar](https://github.com/loigu)
* [Jonathan Fether](https://github.com/jfether) * [Jonathan Fether](https://github.com/jfether)
* [Joshua Arulsamy](https://github.com/jarulsamy)
* [Julian Ste](https://github.com/julian-st) * [Julian Ste](https://github.com/julian-st)
* [Julián Vásquez](https://github.com/juvasquezg) * [Julián Vásquez](https://github.com/juvasquezg)
* [Junbo Zheng](https://github.com/Junbo-Zheng)
* [Kevin Branigan](https://github.com/kbranigan) * [Kevin Branigan](https://github.com/kbranigan)
* [Kevin Sapper](https://github.com/sappo) * [Kevin Sapper](https://github.com/sappo)
* [Kyle Chisholm](https://github.com/ChisholmKyle) * [Kyle Chisholm](https://github.com/ChisholmKyle)
* [Linus Wallgren](https://github.com/ecksun) * [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) * [Mateusz Szafoni](https://github.com/raiden00pl)
* Mike Pontillo * Mike Pontillo
* [miaoerduo](https://github.com/miaoerduo) * [miaoerduo](https://github.com/miaoerduo)
* [mohawk2](https://github.com/mohawk2)
* [Mike Jerris](https://github.com/mjerris) * [Mike Jerris](https://github.com/mjerris)
* [Mike Robinson](https://github.com/mhrobinson) * [Mike Robinson](https://github.com/mhrobinson)
* [Moorthy](https://github.com/moorthy-bs) * [Moorthy](https://github.com/moorthy-bs)
* [myd7349](https://github.com/myd7349) * [myd7349](https://github.com/myd7349)
* [NancyLi1013](https://github.com/NancyLi1013) * [NancyLi1013](https://github.com/NancyLi1013)
* [Orri](https://github.com/sbvoxel)
* Paulo Antonio Alvarez * Paulo Antonio Alvarez
* [Paweł Malowany](https://github.com/PawelMalowany) * [Paweł Malowany](https://github.com/PawelMalowany)
* [Pawel Winogrodzki](https://github.com/PawelWMS) * [Pawel Winogrodzki](https://github.com/PawelWMS)
@@ -61,10 +71,14 @@ Contributors:
* [Romain Porte](https://github.com/MicroJoe) * [Romain Porte](https://github.com/MicroJoe)
* [SANJEEV BA](https://github.com/basanjeev) * [SANJEEV BA](https://github.com/basanjeev)
* [Sang-Heon Jeon](https://github.com/lntuition) * [Sang-Heon Jeon](https://github.com/lntuition)
* [Sayan Bandyopadhyay](https://github.com/saynb)
* [Simon Sobisch](https://github.com/GitMensch) * [Simon Sobisch](https://github.com/GitMensch)
* [Simon Ricaldone](https://github.com/simon-p-r) * [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) * [Square789](https://github.com/Square789)
* [Stephan Gatzka](https://github.com/gatzka) * [Stephan Gatzka](https://github.com/gatzka)
* [Tony Langhammer](https://github.com/BigBrainAFK)
* [Vemake](https://github.com/vemakereporter) * [Vemake](https://github.com/vemakereporter)
* [Wei Tan](https://github.com/tan-wei) * [Wei Tan](https://github.com/tan-wei)
* [Weston Schmidt](https://github.com/schmidtw) * [Weston Schmidt](https://github.com/schmidtw)
@@ -73,6 +87,7 @@ Contributors:
* [yuta-oxo](https://github.com/yuta-oxo) * [yuta-oxo](https://github.com/yuta-oxo)
* [Zach Hindes](https://github.com/zhindes) * [Zach Hindes](https://github.com/zhindes)
* [Zhao Zhixu](https://github.com/zhaozhixu) * [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) 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,7 +8,7 @@ CJSON_TEST_SRC = cJSON.c test.c
LDLIBS = -lm LDLIBS = -lm
LIBVERSION = 1.7.14 LIBVERSION = 1.7.18
CJSON_SOVERSION = 1 CJSON_SOVERSION = 1
UTILS_SOVERSION = 1 UTILS_SOVERSION = 1

View File

@@ -10,6 +10,7 @@ Ultralightweight JSON parser in ANSI C.
* [Copying the source](#copying-the-source) * [Copying the source](#copying-the-source)
* [CMake](#cmake) * [CMake](#cmake)
* [Makefile](#makefile) * [Makefile](#makefile)
* [Meson](#meson)
* [Vcpkg](#Vcpkg) * [Vcpkg](#Vcpkg)
* [Including cJSON](#including-cjson) * [Including cJSON](#including-cjson)
* [Data Structure](#data-structure) * [Data Structure](#data-structure)
@@ -118,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. * `-DCMAKE_INSTALL_PREFIX=/usr`: Set a prefix for the installation.
* `-DENABLE_LOCALES=On`: Enable the usage of localeconv method. ( on by default ) * `-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`. * `-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: If you are packaging cJSON for a distribution of Linux, you would probably take these steps for example:
``` ```
@@ -144,6 +146,23 @@ 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`. And uninstall them with: `make PREFIX=/usr DESTDIR=temp uninstall`. 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 #### Vcpkg
You can download and install cJSON using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager: You can download and install cJSON using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
@@ -406,7 +425,7 @@ 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 ```c
//NOTE: Returns a heap allocated string, you are required to free it after use. //NOTE: Returns a heap allocated string, you are required to free it after use.

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.

113
cJSON.c
View File

@@ -78,8 +78,12 @@
#endif #endif
#ifndef NAN #ifndef NAN
#ifdef _WIN32
#define NAN sqrt(-1.0)
#else
#define NAN 0.0/0.0 #define NAN 0.0/0.0
#endif #endif
#endif
typedef struct { typedef struct {
const unsigned char *json; const unsigned char *json;
@@ -92,9 +96,9 @@ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
return (const char*) (global_error.json + global_error.position); return (const char*) (global_error.json + global_error.position);
} }
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item) CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
{ {
if (!cJSON_IsString(item)) if (!cJSON_IsString(item))
{ {
return NULL; return NULL;
} }
@@ -102,9 +106,9 @@ CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
return item->valuestring; return item->valuestring;
} }
CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item) CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item)
{ {
if (!cJSON_IsNumber(item)) if (!cJSON_IsNumber(item))
{ {
return (double) NAN; return (double) NAN;
} }
@@ -113,7 +117,7 @@ CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item)
} }
/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */ /* 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 != 14) #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. #error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
#endif #endif
@@ -259,10 +263,12 @@ CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL))
{ {
global_hooks.deallocate(item->valuestring); global_hooks.deallocate(item->valuestring);
item->valuestring = NULL;
} }
if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
{ {
global_hooks.deallocate(item->string); global_hooks.deallocate(item->string);
item->string = NULL;
} }
global_hooks.deallocate(item); global_hooks.deallocate(item);
item = next; item = next;
@@ -393,16 +399,33 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
return object->valuedouble = 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) CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring)
{ {
char *copy = NULL; 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's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */
if (!(object->type & cJSON_String) || (object->type & cJSON_IsReference)) if ((object == NULL) || !(object->type & cJSON_String) || (object->type & cJSON_IsReference))
{ {
return NULL; return NULL;
} }
if (strlen(valuestring) <= strlen(object->valuestring)) /* 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); strcpy(object->valuestring, valuestring);
return object->valuestring; return object->valuestring;
} }
@@ -507,10 +530,8 @@ static unsigned char* ensure(printbuffer * const p, size_t needed)
return NULL; return NULL;
} }
if (newbuffer)
{ memcpy(newbuffer, p->buffer, p->offset + 1);
memcpy(newbuffer, p->buffer, p->offset + 1);
}
p->hooks.deallocate(p->buffer); p->hooks.deallocate(p->buffer);
} }
p->length = newsize; p->length = newsize;
@@ -560,6 +581,10 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out
{ {
length = sprintf((char*)number_buffer, "null"); length = sprintf((char*)number_buffer, "null");
} }
else if(d == (double)item->valueint)
{
length = sprintf((char*)number_buffer, "%d", item->valueint);
}
else else
{ {
/* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
@@ -882,6 +907,7 @@ fail:
if (output != NULL) if (output != NULL)
{ {
input_buffer->hooks.deallocate(output); input_buffer->hooks.deallocate(output);
output = NULL;
} }
if (input_pointer != NULL) if (input_pointer != NULL)
@@ -1101,7 +1127,7 @@ CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer
} }
buffer.content = (const unsigned char*)value; buffer.content = (const unsigned char*)value;
buffer.length = buffer_length; buffer.length = buffer_length;
buffer.offset = 0; buffer.offset = 0;
buffer.hooks = global_hooks; buffer.hooks = global_hooks;
@@ -1224,6 +1250,7 @@ static unsigned char *print(const cJSON * const item, cJSON_bool format, const i
/* free the buffer */ /* free the buffer */
hooks->deallocate(buffer->buffer); hooks->deallocate(buffer->buffer);
buffer->buffer = NULL;
} }
return printed; return printed;
@@ -1232,11 +1259,13 @@ fail:
if (buffer->buffer != NULL) if (buffer->buffer != NULL)
{ {
hooks->deallocate(buffer->buffer); hooks->deallocate(buffer->buffer);
buffer->buffer = NULL;
} }
if (printed != NULL) if (printed != NULL)
{ {
hooks->deallocate(printed); hooks->deallocate(printed);
printed = NULL;
} }
return NULL; return NULL;
@@ -1277,6 +1306,7 @@ CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON
if (!print_value(item, &p)) if (!print_value(item, &p))
{ {
global_hooks.deallocate(p.buffer); global_hooks.deallocate(p.buffer);
p.buffer = NULL;
return NULL; return NULL;
} }
@@ -1648,6 +1678,11 @@ static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_bu
current_item = new_item; 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 */ /* parse the name of the child */
input_buffer->offset++; input_buffer->offset++;
buffer_skip_whitespace(input_buffer); buffer_skip_whitespace(input_buffer);
@@ -2180,7 +2215,7 @@ CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * c
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item) 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; return NULL;
} }
@@ -2258,7 +2293,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON
{ {
cJSON *after_inserted = NULL; cJSON *after_inserted = NULL;
if (which < 0) if (which < 0 || newitem == NULL)
{ {
return false; return false;
} }
@@ -2269,6 +2304,11 @@ CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON
return add_item_to_array(array, newitem); 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; newitem->next = after_inserted;
newitem->prev = after_inserted->prev; newitem->prev = after_inserted->prev;
after_inserted->prev = newitem; after_inserted->prev = newitem;
@@ -2285,7 +2325,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement) 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; return false;
} }
@@ -2355,6 +2395,11 @@ static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSO
cJSON_free(replacement->string); cJSON_free(replacement->string);
} }
replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
if (replacement->string == NULL)
{
return false;
}
replacement->type &= ~cJSON_StringIsConst; replacement->type &= ~cJSON_StringIsConst;
return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement); return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
@@ -2544,6 +2589,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
} }
a = cJSON_CreateArray(); a = cJSON_CreateArray();
for(i = 0; a && (i < (size_t)count); i++) for(i = 0; a && (i < (size_t)count); i++)
{ {
n = cJSON_CreateNumber(numbers[i]); n = cJSON_CreateNumber(numbers[i]);
@@ -2562,7 +2608,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
} }
p = n; p = n;
} }
a->child->prev = n;
if (a && a->child) {
a->child->prev = n;
}
return a; return a;
} }
@@ -2599,7 +2648,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
} }
p = n; p = n;
} }
a->child->prev = n;
if (a && a->child) {
a->child->prev = n;
}
return a; return a;
} }
@@ -2618,7 +2670,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
a = cJSON_CreateArray(); a = cJSON_CreateArray();
for(i = 0;a && (i < (size_t)count); i++) for(i = 0; a && (i < (size_t)count); i++)
{ {
n = cJSON_CreateNumber(numbers[i]); n = cJSON_CreateNumber(numbers[i]);
if(!n) if(!n)
@@ -2636,7 +2688,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
} }
p = n; p = n;
} }
a->child->prev = n;
if (a && a->child) {
a->child->prev = n;
}
return a; return a;
} }
@@ -2673,13 +2728,23 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int co
} }
p = n; p = n;
} }
a->child->prev = n;
if (a && a->child) {
a->child->prev = n;
}
return a; return a;
} }
/* Duplication */ /* 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) 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 *newitem = NULL;
cJSON *child = NULL; cJSON *child = NULL;
@@ -2726,7 +2791,10 @@ CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
child = item->child; child = item->child;
while (child != NULL) 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) if (!newchild)
{ {
goto fail; goto fail;
@@ -2961,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) 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; return false;
} }
@@ -3092,4 +3160,5 @@ CJSON_PUBLIC(void *) cJSON_malloc(size_t size)
CJSON_PUBLIC(void) cJSON_free(void *object) CJSON_PUBLIC(void) cJSON_free(void *object)
{ {
global_hooks.deallocate(object); global_hooks.deallocate(object);
object = NULL;
} }

17
cJSON.h
View File

@@ -81,7 +81,7 @@ then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJ
/* project version */ /* project version */
#define CJSON_VERSION_MAJOR 1 #define CJSON_VERSION_MAJOR 1
#define CJSON_VERSION_MINOR 7 #define CJSON_VERSION_MINOR 7
#define CJSON_VERSION_PATCH 14 #define CJSON_VERSION_PATCH 18
#include <stddef.h> #include <stddef.h>
@@ -137,6 +137,12 @@ typedef int cJSON_bool;
#define CJSON_NESTING_LIMIT 1000 #define CJSON_NESTING_LIMIT 1000
#endif #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 */ /* returns the version of cJSON as a string */
CJSON_PUBLIC(const char*) cJSON_Version(void); CJSON_PUBLIC(const char*) cJSON_Version(void);
@@ -256,7 +262,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * cons
/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings. /* 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, * 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 adress area. */ * but should point to a readable and writable address area. */
CJSON_PUBLIC(void) cJSON_Minify(char *json); CJSON_PUBLIC(void) cJSON_Minify(char *json);
/* Helper functions for creating and adding items to an object at the same time. /* Helper functions for creating and adding items to an object at the same time.
@@ -279,6 +285,13 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */ /* 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); 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 */ /* 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) #define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)

View File

@@ -960,7 +960,9 @@ static int apply_patch(cJSON *object, const cJSON *patch, const cJSON_bool case_
/* split pointer in parent and child */ /* split pointer in parent and child */
parent_pointer = cJSONUtils_strdup((unsigned char*)path->valuestring); parent_pointer = cJSONUtils_strdup((unsigned char*)path->valuestring);
child_pointer = (unsigned char*)strrchr((char*)parent_pointer, '/'); if (parent_pointer) {
child_pointer = (unsigned char*)strrchr((char*)parent_pointer, '/');
}
if (child_pointer != NULL) if (child_pointer != NULL)
{ {
child_pointer[0] = '\0'; child_pointer[0] = '\0';
@@ -1365,6 +1367,7 @@ static cJSON *merge_patch(cJSON *target, const cJSON * const patch, const cJSON_
replacement = merge_patch(replace_me, patch_child, case_sensitive); replacement = merge_patch(replace_me, patch_child, case_sensitive);
if (replacement == NULL) if (replacement == NULL)
{ {
cJSON_Delete(target);
return NULL; return NULL;
} }
@@ -1406,6 +1409,10 @@ static cJSON *generate_merge_patch(cJSON * const from, cJSON * const to, const c
from_child = from->child; from_child = from->child;
to_child = to->child; to_child = to->child;
patch = cJSON_CreateObject(); patch = cJSON_CreateObject();
if (patch == NULL)
{
return NULL;
}
while (from_child || to_child) while (from_child || to_child)
{ {
int diff; int diff;

View File

@@ -34,7 +34,7 @@ static void * CJSON_CDECL failing_malloc(size_t size)
return NULL; return NULL;
} }
/* work around MSVC error C2322: '...' address of dillimport '...' is not static */ /* work around MSVC error C2322: '...' address of dllimport '...' is not static */
static void CJSON_CDECL normal_free(void *pointer) static void CJSON_CDECL normal_free(void *pointer)
{ {
free(pointer); free(pointer);
@@ -117,6 +117,50 @@ static void cjson_add_true_should_fail_on_allocation_failure(void)
cJSON_Delete(root); 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) static void cjson_add_false_should_add_false(void)
{ {
cJSON *root = cJSON_CreateObject(); cJSON *root = cJSON_CreateObject();
@@ -390,6 +434,11 @@ int CJSON_CDECL main(void)
RUN_TEST(cjson_add_true_should_fail_with_null_pointers); RUN_TEST(cjson_add_true_should_fail_with_null_pointers);
RUN_TEST(cjson_add_true_should_fail_on_allocation_failure); 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_add_false);
RUN_TEST(cjson_add_false_should_fail_with_null_pointers); RUN_TEST(cjson_add_false_should_fail_with_null_pointers);
RUN_TEST(cjson_add_false_should_fail_on_allocation_failure); RUN_TEST(cjson_add_false_should_fail_on_allocation_failure);

View File

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

View File

@@ -28,7 +28,6 @@
#include "unity/src/unity.h" #include "unity/src/unity.h"
#include "common.h" #include "common.h"
static void cjson_array_foreach_should_loop_over_arrays(void) static void cjson_array_foreach_should_loop_over_arrays(void)
{ {
cJSON array[1]; cJSON array[1];
@@ -77,7 +76,6 @@ static void cjson_get_object_item_should_get_object_items(void)
found = cJSON_GetObjectItem(item, NULL); found = cJSON_GetObjectItem(item, NULL);
TEST_ASSERT_NULL_MESSAGE(found, "Failed to fail on NULL string."); TEST_ASSERT_NULL_MESSAGE(found, "Failed to fail on NULL string.");
found = cJSON_GetObjectItem(item, "one"); found = cJSON_GetObjectItem(item, "one");
TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find first item."); TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find first item.");
TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 1); TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 1);
@@ -127,7 +125,8 @@ static void cjson_get_object_item_case_sensitive_should_get_object_items(void)
cJSON_Delete(item); cJSON_Delete(item);
} }
static void cjson_get_object_item_should_not_crash_with_array(void) { static void cjson_get_object_item_should_not_crash_with_array(void)
{
cJSON *array = NULL; cJSON *array = NULL;
cJSON *found = NULL; cJSON *found = NULL;
array = cJSON_Parse("[1]"); array = cJSON_Parse("[1]");
@@ -138,7 +137,8 @@ static void cjson_get_object_item_should_not_crash_with_array(void) {
cJSON_Delete(array); cJSON_Delete(array);
} }
static void cjson_get_object_item_case_sensitive_should_not_crash_with_array(void) { static void cjson_get_object_item_case_sensitive_should_not_crash_with_array(void)
{
cJSON *array = NULL; cJSON *array = NULL;
cJSON *found = NULL; cJSON *found = NULL;
array = cJSON_Parse("[1]"); array = cJSON_Parse("[1]");
@@ -219,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."); 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) static void cjson_set_number_value_should_set_numbers(void)
{ {
cJSON number[1] = {{NULL, NULL, NULL, cJSON_Number, NULL, 0, 0, NULL}}; cJSON number[1] = {{NULL, NULL, NULL, cJSON_Number, NULL, 0, 0, NULL}};
@@ -280,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."); 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) static void cjson_replace_item_via_pointer_should_replace_items(void)
{ {
cJSON replacements[3]; cJSON replacements[3];
@@ -302,7 +334,6 @@ static void cjson_replace_item_via_pointer_should_replace_items(void)
cJSON_AddItemToArray(array, middle); cJSON_AddItemToArray(array, middle);
cJSON_AddItemToArray(array, end); cJSON_AddItemToArray(array, end);
memset(replacements, '\0', sizeof(replacements)); memset(replacements, '\0', sizeof(replacements));
/* replace beginning */ /* replace beginning */
@@ -329,7 +360,7 @@ static void cjson_replace_item_via_pointer_should_replace_items(void)
static void cjson_replace_item_in_object_should_preserve_name(void) static void cjson_replace_item_in_object_should_preserve_name(void)
{ {
cJSON root[1] = {{ NULL, NULL, NULL, 0, NULL, 0, 0, NULL }}; cJSON root[1] = {{NULL, NULL, NULL, 0, NULL, 0, 0, NULL}};
cJSON *child = NULL; cJSON *child = NULL;
cJSON *replacement = NULL; cJSON *replacement = NULL;
cJSON_bool flag = false; cJSON_bool flag = false;
@@ -339,7 +370,7 @@ static void cjson_replace_item_in_object_should_preserve_name(void)
replacement = cJSON_CreateNumber(2); replacement = cJSON_CreateNumber(2);
TEST_ASSERT_NOT_NULL(replacement); TEST_ASSERT_NOT_NULL(replacement);
flag = cJSON_AddItemToObject(root, "child", child); flag = cJSON_AddItemToObject(root, "child", child);
TEST_ASSERT_TRUE_MESSAGE(flag, "add item to object failed"); TEST_ASSERT_TRUE_MESSAGE(flag, "add item to object failed");
cJSON_ReplaceItemInObject(root, "child", replacement); cJSON_ReplaceItemInObject(root, "child", replacement);
@@ -353,6 +384,19 @@ static void cjson_functions_should_not_crash_with_null_pointers(void)
{ {
char buffer[10]; char buffer[10];
cJSON *item = cJSON_CreateString("item"); 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); cJSON_InitHooks(NULL);
TEST_ASSERT_NULL(cJSON_Parse(NULL)); TEST_ASSERT_NULL(cJSON_Parse(NULL));
@@ -412,6 +456,8 @@ static void cjson_functions_should_not_crash_with_null_pointers(void)
cJSON_DeleteItemFromObject(item, NULL); cJSON_DeleteItemFromObject(item, NULL);
cJSON_DeleteItemFromObjectCaseSensitive(NULL, "item"); cJSON_DeleteItemFromObjectCaseSensitive(NULL, "item");
cJSON_DeleteItemFromObjectCaseSensitive(item, NULL); cJSON_DeleteItemFromObjectCaseSensitive(item, 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(NULL, 0, item));
TEST_ASSERT_FALSE(cJSON_InsertItemInArray(item, 0, NULL)); TEST_ASSERT_FALSE(cJSON_InsertItemInArray(item, 0, NULL));
TEST_ASSERT_FALSE(cJSON_ReplaceItemViaPointer(NULL, item, item)); TEST_ASSERT_FALSE(cJSON_ReplaceItemViaPointer(NULL, item, item));
@@ -428,14 +474,39 @@ static void cjson_functions_should_not_crash_with_null_pointers(void)
TEST_ASSERT_NULL(cJSON_Duplicate(NULL, true)); TEST_ASSERT_NULL(cJSON_Duplicate(NULL, true));
TEST_ASSERT_FALSE(cJSON_Compare(item, NULL, false)); TEST_ASSERT_FALSE(cJSON_Compare(item, NULL, false));
TEST_ASSERT_FALSE(cJSON_Compare(NULL, item, 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); cJSON_Minify(NULL);
/* skipped because it is only used via a macro that checks for NULL */ /* skipped because it is only used via a macro that checks for NULL */
/* cJSON_SetNumberHelper(NULL, 0); */ /* cJSON_SetNumberHelper(NULL, 0); */
/* restore corrupted item2 to delete it */
item2->prev = originalPrev;
cJSON_Delete(corruptedString);
cJSON_Delete(array);
cJSON_Delete(item); cJSON_Delete(item);
} }
static void * CJSON_CDECL 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)size;
(void)pointer; (void)pointer;
@@ -445,7 +516,7 @@ static void * CJSON_CDECL failing_realloc(void *pointer, size_t size)
static void ensure_should_fail_on_failed_realloc(void) static void ensure_should_fail_on_failed_realloc(void)
{ {
printbuffer buffer = {NULL, 10, 0, 0, false, false, {&malloc, &free, &failing_realloc}}; printbuffer buffer = {NULL, 10, 0, 0, false, false, {&malloc, &free, &failing_realloc}};
buffer.buffer = (unsigned char*)malloc(100); buffer.buffer = (unsigned char *)malloc(100);
TEST_ASSERT_NOT_NULL(buffer.buffer); TEST_ASSERT_NOT_NULL(buffer.buffer);
TEST_ASSERT_NULL_MESSAGE(ensure(&buffer, 200), "Ensure didn't fail with failing realloc."); TEST_ASSERT_NULL_MESSAGE(ensure(&buffer, 200), "Ensure didn't fail with failing realloc.");
@@ -454,7 +525,7 @@ static void ensure_should_fail_on_failed_realloc(void)
static void skip_utf8_bom_should_skip_bom(void) static void skip_utf8_bom_should_skip_bom(void)
{ {
const unsigned char string[] = "\xEF\xBB\xBF{}"; const unsigned char string[] = "\xEF\xBB\xBF{}";
parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; parse_buffer buffer = {0, 0, 0, 0, {0, 0, 0}};
buffer.content = string; buffer.content = string;
buffer.length = sizeof(string); buffer.length = sizeof(string);
buffer.hooks = global_hooks; buffer.hooks = global_hooks;
@@ -466,7 +537,7 @@ static void skip_utf8_bom_should_skip_bom(void)
static void skip_utf8_bom_should_not_skip_bom_if_not_at_beginning(void) static void skip_utf8_bom_should_not_skip_bom_if_not_at_beginning(void)
{ {
const unsigned char string[] = " \xEF\xBB\xBF{}"; const unsigned char string[] = " \xEF\xBB\xBF{}";
parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; parse_buffer buffer = {0, 0, 0, 0, {0, 0, 0}};
buffer.content = string; buffer.content = string;
buffer.length = sizeof(string); buffer.length = sizeof(string);
buffer.hooks = global_hooks; buffer.hooks = global_hooks;
@@ -496,12 +567,13 @@ static void cjson_get_number_value_should_get_a_number(void)
TEST_ASSERT_EQUAL_DOUBLE(cJSON_GetNumberValue(number), number->valuedouble); TEST_ASSERT_EQUAL_DOUBLE(cJSON_GetNumberValue(number), number->valuedouble);
TEST_ASSERT_DOUBLE_IS_NAN(cJSON_GetNumberValue(string)); TEST_ASSERT_DOUBLE_IS_NAN(cJSON_GetNumberValue(string));
TEST_ASSERT_DOUBLE_IS_NAN(cJSON_GetNumberValue(NULL)); TEST_ASSERT_DOUBLE_IS_NAN(cJSON_GetNumberValue(NULL));
cJSON_Delete(number); cJSON_Delete(number);
cJSON_Delete(string); cJSON_Delete(string);
} }
static void cjson_create_string_reference_should_create_a_string_reference(void) { static void cjson_create_string_reference_should_create_a_string_reference(void)
{
const char *string = "I am a string!"; const char *string = "I am a string!";
cJSON *string_reference = cJSON_CreateStringReference(string); cJSON *string_reference = cJSON_CreateStringReference(string);
@@ -511,7 +583,8 @@ static void cjson_create_string_reference_should_create_a_string_reference(void)
cJSON_Delete(string_reference); 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_reference = NULL;
cJSON *number_object = cJSON_CreateObject(); cJSON *number_object = cJSON_CreateObject();
cJSON *number = cJSON_CreateNumber(42); cJSON *number = cJSON_CreateNumber(42);
@@ -529,7 +602,8 @@ static void cjson_create_object_reference_should_create_an_object_reference(void
cJSON_Delete(number_reference); 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_reference = NULL;
cJSON *number_array = cJSON_CreateArray(); cJSON *number_array = cJSON_CreateArray();
cJSON *number = cJSON_CreateNumber(42); cJSON *number = cJSON_CreateNumber(42);
@@ -566,7 +640,7 @@ static void cjson_add_item_to_object_should_not_use_after_free_when_string_is_al
{ {
cJSON *object = cJSON_CreateObject(); cJSON *object = cJSON_CreateObject();
cJSON *number = cJSON_CreateNumber(42); cJSON *number = cJSON_CreateNumber(42);
char *name = (char*)cJSON_strdup((const unsigned char*)"number", &global_hooks); char *name = (char *)cJSON_strdup((const unsigned char *)"number", &global_hooks);
TEST_ASSERT_NOT_NULL(object); TEST_ASSERT_NOT_NULL(object);
TEST_ASSERT_NOT_NULL(number); TEST_ASSERT_NOT_NULL(number);
@@ -626,7 +700,7 @@ static void cjson_set_valuestring_to_object_should_not_leak_memory(void)
cJSON *item2 = cJSON_CreateStringReference(reference_valuestring); cJSON *item2 = cJSON_CreateStringReference(reference_valuestring);
char *ptr1 = NULL; char *ptr1 = NULL;
char *return_value = NULL; char *return_value = NULL;
cJSON_AddItemToObject(root, "one", item1); cJSON_AddItemToObject(root, "one", item1);
cJSON_AddItemToObject(root, "two", item2); cJSON_AddItemToObject(root, "two", item2);
@@ -650,6 +724,64 @@ static void cjson_set_valuestring_to_object_should_not_leak_memory(void)
cJSON_Delete(root); 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) int CJSON_CDECL main(void)
{ {
UNITY_BEGIN(); UNITY_BEGIN();
@@ -662,11 +794,14 @@ int CJSON_CDECL main(void)
RUN_TEST(cjson_get_object_item_case_sensitive_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(typecheck_functions_should_check_type);
RUN_TEST(cjson_should_not_parse_to_deeply_nested_jsons); 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_set_number_value_should_set_numbers);
RUN_TEST(cjson_detach_item_via_pointer_should_detach_items); 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_via_pointer_should_replace_items);
RUN_TEST(cjson_replace_item_in_object_should_preserve_name); RUN_TEST(cjson_replace_item_in_object_should_preserve_name);
RUN_TEST(cjson_functions_should_not_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(ensure_should_fail_on_failed_realloc);
RUN_TEST(skip_utf8_bom_should_skip_bom); RUN_TEST(skip_utf8_bom_should_skip_bom);
RUN_TEST(skip_utf8_bom_should_not_skip_bom_if_not_at_beginning); RUN_TEST(skip_utf8_bom_should_not_skip_bom_if_not_at_beginning);
@@ -679,6 +814,7 @@ int CJSON_CDECL main(void)
RUN_TEST(cjson_add_item_to_object_should_not_use_after_free_when_string_is_aliased); 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_delete_item_from_array_should_not_broken_list_structure);
RUN_TEST(cjson_set_valuestring_to_object_should_not_leak_memory); RUN_TEST(cjson_set_valuestring_to_object_should_not_leak_memory);
RUN_TEST(cjson_set_bool_value_must_not_break_objects);
return UNITY_END(); return UNITY_END();
} }

View File

@@ -250,6 +250,33 @@ static void test14_should_not_be_parsed(void)
} }
} }
/* 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) int CJSON_CDECL main(void)
{ {
UNITY_BEGIN(); UNITY_BEGIN();
@@ -267,5 +294,6 @@ int CJSON_CDECL main(void)
RUN_TEST(test12_should_not_be_parsed); RUN_TEST(test12_should_not_be_parsed);
RUN_TEST(test13_should_be_parsed_without_null_termination); RUN_TEST(test13_should_be_parsed_without_null_termination);
RUN_TEST(test14_should_not_be_parsed); RUN_TEST(test14_should_not_be_parsed);
RUN_TEST(test15_should_not_heap_buffer_overflow);
return UNITY_END(); return UNITY_END();
} }

View File

@@ -63,7 +63,7 @@ static void assert_print_object(const char * const expected, const char * const
formatted_buffer.format = true; formatted_buffer.format = true;
TEST_ASSERT_TRUE_MESSAGE(print_object(item, &formatted_buffer), "Failed to print formatted string."); 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); reset(item);
} }

View File

@@ -69,7 +69,7 @@ static char* create_monitor(void)
goto end; goto end;
} }
/* after creation was successful, immediately add it to the monitor, /* 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); cJSON_AddItemToObject(monitor, "name", name);
resolutions = cJSON_CreateArray(); resolutions = cJSON_CreateArray();

View File

@@ -78,7 +78,7 @@ class ParseOutput
@array_list.push ' <testcase classname="' + test_suite + '" name="' + test_name + '"/>' @array_list.push ' <testcase classname="' + test_suite + '" name="' + test_name + '"/>'
end 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) def test_ignored(array)
last_item = array.length - 1 last_item = array.length - 1
test_name = array[last_item - 2] test_name = array[last_item - 2]

View File

@@ -72,7 +72,7 @@ header files. These three files _are_ Unity.
into this folder already. This is where all the handy documentation can be into this folder already. This is where all the handy documentation can be
found. found.
- `examples` - This contains a few examples of using Unity. - `examples` - This contains a few examples of using Unity.
- `extras` - These are optional add ons to Unity that are not part of the core - `extras` - These are optional addons to Unity that are not part of the core
project. If you've reached us through James Grenning's book, you're going to project. If you've reached us through James Grenning's book, you're going to
want to look here. want to look here.
- `test` - This is how Unity and its scripts are all tested. If you're just using - `test` - This is how Unity and its scripts are all tested. If you're just using

View File

@@ -2,7 +2,7 @@ Eclipse error parsers
===================== =====================
These are a godsend for extracting & quickly navigating to 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 I don't know how to write an Eclipse plugin so you'll have
to add them manually. to add them manually.

View File

@@ -8,7 +8,7 @@
#include "unity.h" #include "unity.h"
#include <stddef.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 #ifdef UNITY_OMIT_OUTPUT_CHAR_HEADER_DECLARATION
void UNITY_OUTPUT_CHAR(int); void UNITY_OUTPUT_CHAR(int);
#endif #endif

View File

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