Compare commits

..

4 Commits

Author SHA1 Message Date
Max Bruckner
88d66c5da9 Release version 1.5.7 2017-07-12 23:13:14 +02:00
Max Bruckner
954d61e5e7 Fix #189, ensure returns an invalid pointer
If realloc returns NULL, ensure didn't abort but returned
printbuffer.offset instead. If an attacker can control
printbuffer.offset and also make realloc fail at just the right moment,
this would make cJSON potentially write at an arbitrary memory address.
2017-07-12 23:02:31 +02:00
Max Bruckner
ecdff7837c Merge pull request #185 from jwilk-forks/spelling
Fix typos in json.dict
2017-07-08 20:16:33 +02:00
Jakub Wilk
a3c2eba991 Fix typos in json.dict 2017-07-08 09:39:06 +02:00
16 changed files with 79 additions and 265 deletions

View File

@@ -1,3 +1,10 @@
1.5.7
=====
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
1.5.6
=====
Fixes:

View File

@@ -7,7 +7,7 @@ project(cJSON C)
set(PROJECT_VERSION_MAJOR 1)
set(PROJECT_VERSION_MINOR 5)
set(PROJECT_VERSION_PATCH 6)
set(PROJECT_VERSION_PATCH 7)
set(CJSON_VERSION_SO 1)
set(CJSON_UTILS_VERSION_SO 1)
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
@@ -16,46 +16,33 @@ set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT
set(custom_compiler_flags)
include(CheckCCompilerFlag)
option(ENABLE_CUSTOM_COMPILER_FLAGS "Enables custom compiler flags" ON)
option(ENABLE_CUSTOM_COMPILER_FLAGS "Enables custom compiler flags for Clang and GCC" ON)
if (ENABLE_CUSTOM_COMPILER_FLAGS)
if (("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") OR ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU"))
list(APPEND custom_compiler_flags
-std=c89
-pedantic
-Wall
-Wextra
-Werror
-Wstrict-prototypes
-Wwrite-strings
-Wshadow
-Winit-self
-Wcast-align
-Wformat=2
-Wmissing-prototypes
-Wstrict-overflow=2
-Wcast-qual
-Wundef
-Wswitch-default
-Wconversion
-Wc++-compat
-fstack-protector-strong
-Wcomma
-Wdouble-promotion
-Wparentheses
-Wformat-overflow
-Wunused-macros
-Wmissing-variable-declarations
-Wused-but-marked-unused
-Wswitch-enum
list(APPEND custom_compiler_flags
-std=c89
-pedantic
-Wall
-Wextra
-Werror
-Wstrict-prototypes
-Wwrite-strings
-Wshadow
-Winit-self
-Wcast-align
-Wformat=2
-Wmissing-prototypes
-Wstrict-overflow=2
-Wcast-qual
-Wundef
-Wswitch-default
-Wconversion
-Wc++-compat
-fstack-protector-strong
-Wcomma
-Wdouble-promotion
-Wparentheses
-Wformat-overflow
)
elseif("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
list(APPEND custom_compiler_flags
/GS
/Za
/sdl
/W4
)
endif()
endif()
option(ENABLE_SANITIZERS "Enables AddressSanitizer and UndefinedBehaviorSanitizer." OFF)
@@ -112,17 +99,7 @@ set(CJSON_LIB cjson)
file(GLOB HEADERS cJSON.h)
set(SOURCES cJSON.c)
option(BUILD_SHARED_AND_STATIC_LIBS "Build both shared and static libraries" Off)
if (NOT BUILD_SHARED_AND_STATIC_LIBS)
add_library("${CJSON_LIB}" "${HEADERS}" "${SOURCES}")
else()
# See https://cmake.org/Wiki/CMake_FAQ#How_do_I_make_my_shared_and_static_libraries_have_the_same_root_name.2C_but_different_suffixes.3F
add_library("${CJSON_LIB}" SHARED "${HEADERS}" "${SOURCES}")
add_library("${CJSON_LIB}-static" STATIC "${HEADERS}" "${SOURCES}")
set_target_properties("${CJSON_LIB}-static" PROPERTIES OUTPUT_NAME "${CJSON_LIB}")
set_target_properties("${CJSON_LIB}-static" PROPERTIES PREFIX "lib")
endif()
add_library("${CJSON_LIB}" "${HEADERS}" "${SOURCES}")
if (NOT WIN32)
target_link_libraries("${CJSON_LIB}" m)
endif()
@@ -133,9 +110,6 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/library_config/libcjson.pc.in"
install(FILES cJSON.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/cjson")
install (FILES "${CMAKE_CURRENT_BINARY_DIR}/libcjson.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
install(TARGETS "${CJSON_LIB}" DESTINATION "${CMAKE_INSTALL_LIBDIR}" EXPORT "${CJSON_LIB}")
if (BUILD_SHARED_AND_STATIC_LIBS)
install(TARGETS "${CJSON_LIB}-static" DESTINATION "${CMAKE_INSTALL_LIBDIR}")
endif()
if(ENABLE_TARGET_EXPORT)
# export library information for CMake projects
install(EXPORT "${CJSON_LIB}" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/cJSON")
@@ -154,25 +128,13 @@ if(ENABLE_CJSON_UTILS)
file(GLOB HEADERS_UTILS cJSON_Utils.h)
set(SOURCES_UTILS cJSON_Utils.c)
if (NOT BUILD_SHARED_AND_STATIC_LIBS)
add_library("${CJSON_UTILS_LIB}" "${HEADERS_UTILS}" "${SOURCES_UTILS}")
target_link_libraries("${CJSON_UTILS_LIB}" "${CJSON_LIB}")
else()
add_library("${CJSON_UTILS_LIB}" SHARED "${HEADERS_UTILS}" "${SOURCES_UTILS}")
target_link_libraries("${CJSON_UTILS_LIB}" "${CJSON_LIB}")
add_library("${CJSON_UTILS_LIB}-static" STATIC "${HEADERS_UTILS}" "${SOURCES_UTILS}")
target_link_libraries("${CJSON_UTILS_LIB}-static" "${CJSON_LIB}-static")
set_target_properties("${CJSON_UTILS_LIB}-static" PROPERTIES OUTPUT_NAME "${CJSON_UTILS_LIB}")
set_target_properties("${CJSON_UTILS_LIB}-static" PROPERTIES PREFIX "lib")
endif()
add_library("${CJSON_UTILS_LIB}" "${HEADERS_UTILS}" "${SOURCES_UTILS}")
target_link_libraries("${CJSON_UTILS_LIB}" "${CJSON_LIB}")
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_LIBDIR}" EXPORT "${CJSON_UTILS_LIB}")
if (BUILD_SHARED_AND_STATIC_LIBS)
install(TARGETS "${CJSON_UTILS_LIB}-static" DESTINATION "${CMAKE_INSTALL_LIBDIR}")
endif()
install(FILES cJSON_Utils.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/cjson")
install (FILES "${CMAKE_CURRENT_BINARY_DIR}/libcjson_utils.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
if(ENABLE_TARGET_EXPORT)

View File

@@ -15,6 +15,7 @@ Contributors
* Ian Mobley
* Irwan Djadjadi
* [IvanVoid](https://github.com/npi3pak)
* [Jakub Wilk](https://github.com/jwilk)
* [Jiri Zouhar](https://github.com/loigu)
* [Jonathan Fether](https://github.com/jfether)
* [Julián Vásquez](https://github.com/juvasquezg)

View File

@@ -8,7 +8,7 @@ CJSON_TEST_SRC = cJSON.c test.c
LDLIBS = -lm
LIBVERSION = 1.5.6
LIBVERSION = 1.5.7
CJSON_SOVERSION = 1
UTILS_SOVERSION = 1

View File

@@ -85,11 +85,10 @@ You can change the build process with a list of different options that you can p
* `-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)
* `-DENABLE_CUSTOM_COMPILER_FLAGS=On`: Enable custom compiler flags (currently for Clang, GCC and MSVC). Turn off if it makes problems. (on by default)
* `-DENABLE_CUSTOM_COMPILER_FLAGS=On`: Enable custom compiler flags (currently for Clang and GCC). Turn off if it makes problems. (on by default)
* `-DENABLE_VALGRIND=On`: Run tests with [valgrind](http://valgrind.org). (off by default)
* `-DENABLE_SANITIZERS=On`: Compile cJSON with [AddressSanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizer) and [UndefinedBehaviorSanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html) enabled (if possible). (off by default)
* `-DBUILD_SHARED_LIBS=On`: Build the shared libraries. (on by default)
* `-DBUILD_SHARED_AND_STATIC_LIBS=On`: Build both shared and static libraries. (off by default)
* `-DCMAKE_INSTALL_PREFIX=/usr`: Set a prefix for the installation.
If you are packaging cJSON for a distribution of Linux, you would probably take these steps for example:

53
cJSON.c
View File

@@ -23,19 +23,9 @@
/* cJSON */
/* JSON parser in C. */
/* disable warnings about old C89 functions in MSVC */
#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER)
#define _CRT_SECURE_NO_DEPRECATE
#endif
#ifdef __GNUC__
#pragma GCC visibility push(default)
#endif
#if defined(_MSC_VER)
#pragma warning (push)
/* disable warning about single line comments in system headers */
#pragma warning (disable : 4001)
#endif
#include <string.h>
#include <stdio.h>
@@ -46,9 +36,6 @@
#include <ctype.h>
#include <locale.h>
#if defined(_MSC_VER)
#pragma warning (pop)
#endif
#ifdef __GNUC__
#pragma GCC visibility pop
#endif
@@ -71,7 +58,7 @@ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
}
/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 5) || (CJSON_VERSION_PATCH != 6)
#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 5) || (CJSON_VERSION_PATCH != 7)
#error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
#endif
@@ -114,27 +101,7 @@ typedef struct internal_hooks
void *(*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)
{
return malloc(size);
}
static void internal_free(void *pointer)
{
free(pointer);
}
static void *internal_realloc(void *pointer, size_t size)
{
return realloc(pointer, size);
}
#else
#define internal_malloc malloc
#define internal_free free
#define internal_realloc realloc
#endif
static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc };
static internal_hooks global_hooks = { malloc, free, realloc };
static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks)
{
@@ -147,8 +114,7 @@ static unsigned char* cJSON_strdup(const unsigned char* string, const internal_h
}
length = strlen((const char*)string) + sizeof("");
copy = (unsigned char*)hooks->allocate(length);
if (copy == NULL)
if (!(copy = (unsigned char*)hooks->allocate(length)))
{
return NULL;
}
@@ -242,6 +208,7 @@ typedef struct
/* check if the given size is left to read in a given parse buffer (starting with 1) */
#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
#define cannot_read(buffer, size) (!can_read(buffer, size))
/* check if the buffer can be accessed at the given index (starting with 0) */
#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
@@ -410,6 +377,14 @@ static unsigned char* ensure(printbuffer * const p, size_t needed)
{
/* reallocate with realloc if available */
newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);
if (newbuffer == NULL)
{
p->hooks.deallocate(p->buffer);
p->length = 0;
p->buffer = NULL;
return NULL;
}
}
else
{
@@ -1849,7 +1824,7 @@ CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSO
item->type &= ~cJSON_StringIsConst;
}
#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
#if defined (__clang__) || ((__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
#pragma GCC diagnostic push
#endif
#ifdef __GNUC__
@@ -1871,7 +1846,7 @@ CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJ
item->type |= cJSON_StringIsConst;
cJSON_AddItemToArray(object, item);
}
#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
#if defined (__clang__) || ((__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
#pragma GCC diagnostic pop
#endif

View File

@@ -31,7 +31,7 @@ extern "C"
/* project version */
#define CJSON_VERSION_MAJOR 1
#define CJSON_VERSION_MINOR 5
#define CJSON_VERSION_PATCH 6
#define CJSON_VERSION_PATCH 7
#include <stddef.h>

View File

@@ -20,32 +20,13 @@
THE SOFTWARE.
*/
/* disable warnings about old C89 functions in MSVC */
#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER)
#define _CRT_SECURE_NO_DEPRECATE
#endif
#ifdef __GNUCC__
#pragma GCC visibility push(default)
#endif
#if defined(_MSC_VER)
#pragma warning (push)
/* disable warning about single line comments in system headers */
#pragma warning (disable : 4001)
#endif
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#if defined(_MSC_VER)
#pragma warning (pop)
#endif
#ifdef __GNUCC__
#pragma GCC visibility pop
#endif
#include "cJSON_Utils.h"

View File

@@ -25,8 +25,8 @@ escape_sequence_r="\\r"
escape_sequence_t="\\t"
escape_sequence_quote="\\\""
escape_sequence_backslash="\\\\"
escapce_sequence_slash="\\/"
escpae_sequence_utf16_base="\\u"
escape_sequence_slash="\\/"
escape_sequence_utf16_base="\\u"
escape_sequence_utf16="\\u12ab"
number_integer="1"

View File

@@ -1,58 +0,0 @@
project('cJSON', 'c', default_options: ['c_std=c89'])
version = '1.6.0'
soversion = '0'
compiler = meson.get_compiler('c')
compiler_flags = []
if (compiler.get_id() == 'clang') or (compiler.get_id() == 'gcc')
compiler_flags += [
'-pedantic',
'-Wall',
'-Wextra',
'-Werror',
'-Wstrict-prototypes',
'-Wwrite-strings',
'-Wshadow',
'-Winit-self',
'-Wcast-align',
'-Wformat=2',
'-Wmissing-prototypes',
'-Wstrict-overflow=2',
'-Wcast-qual',
'-Wundef',
'-Wswitch-default',
'-Wconversion',
'-Wc++-compat',
'-fstack-protector-strong',
'-Wcomma',
'-Wdouble-promotion',
'-Wparentheses',
'-Wformat-overflow',
'-Wunused-macros',
'-Wmissing-variable-declarations',
'-Wused-but-marked-unused',
'-Wswitch-enum'
]
endif
foreach flag : compiler_flags
if compiler.has_argument(flag)
add_project_arguments(flag, language: 'c')
endif
endforeach
math = compiler.find_library('m', required: false)
cjson = shared_library('cjson', 'cJSON.c', dependencies: math, version: version, soversion: soversion, install: true)
if get_option('enable_cjson_utils')
cjson_utils = shared_library('cjson_utils', 'cJSON_Utils.c', link_with: cjson, version: version, soversion: soversion, install: true)
endif
if get_option('enable_cjson_tests')
cjson_test = executable('cjson_test', 'test.c', link_with: cjson)
test('cjson_test', cjson_test)
endif
subdir('tests')

View File

@@ -1,2 +0,0 @@
option('enable_cjson_utils', type: 'boolean', value: true)
option('enable_cjson_tests', type: 'boolean', value: true)

View File

@@ -25,14 +25,6 @@ if(ENABLE_CJSON_TEST)
target_compile_options(unity PRIVATE "-fno-sanitize=float-divide-by-zero")
endif()
endif()
# Disable -Wswitch-enum for Unity
if (FLAG_SUPPORTED_Wswitchenum)
if ("${CMAKE_VERSION}" VERSION_LESS "2.8.12")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-switch-enum")
else()
target_compile_options(unity PRIVATE "-Wno-switch-enum")
endif()
endif()
#copy test files
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/inputs")

View File

@@ -119,7 +119,7 @@ static cJSON_bool test_apply_patch(const cJSON * const test)
return successful;
}
static cJSON_bool test_generate_test(cJSON *test)
static cJSON_bool test_generate_test(cJSON *test __attribute__((unused)))
{
cJSON *doc = NULL;
cJSON *patch = NULL;

View File

@@ -1,58 +0,0 @@
if get_option('enable_cjson_tests')
unity_flags = []
if (compiler.get_id() == 'clang') or (compiler.get_id() == 'gcc')
unity_flags += [
'-Wno-switch-enum',
'-Wno-error',
'-fvisibility=default',
'-fno-sanitize=float-divide-by-zero'
]
endif
unity_c_args = []
foreach flag : unity_flags
if compiler.has_argument(flag)
unity_c_args += flag
endif
endforeach
unity = library('unity', 'unity/src/unity.c', c_args: unity_c_args)
common = library('test_common', 'common.c')
cjson_tests = [
'parse_examples',
'parse_number',
'parse_hex4',
'parse_string',
'parse_array',
'parse_object',
'parse_value',
'print_string',
'print_number',
'print_array',
'print_object',
'print_value',
'misc_tests',
'parse_with_opts',
'compare_tests'
]
foreach cjson_test : cjson_tests
exe = executable(cjson_test, cjson_test + '.c', link_with: [common, cjson, unity])
test(cjson_test, exe, workdir: meson.current_source_dir())
endforeach
if get_option('enable_cjson_utils')
cjson_utils_tests = [
'json_patch_tests',
'old_utils_tests',
'misc_utils_tests'
]
foreach cjson_utils_test : cjson_utils_tests
exe = executable(cjson_utils_test, cjson_utils_test + '.c', link_with: [common, cjson_utils, unity, cjson])
test(cjson_utils_test, exe, workdir: meson.current_source_dir())
endforeach
endif
endif

View File

@@ -410,6 +410,22 @@ static void cjson_functions_shouldnt_crash_with_null_pointers(void)
cJSON_Delete(item);
}
static void *failing_realloc(void *pointer, size_t size)
{
(void)size;
(void)pointer;
return NULL;
}
static void ensure_should_fail_on_failed_realloc(void)
{
printbuffer buffer = {NULL, 10, 0, 0, false, false, {&malloc, &free, &failing_realloc}};
buffer.buffer = (unsigned char*)malloc(100);
TEST_ASSERT_NOT_NULL(buffer.buffer);
TEST_ASSERT_NULL_MESSAGE(ensure(&buffer, 200), "Ensure didn't fail with failing realloc.");
}
int main(void)
{
UNITY_BEGIN();
@@ -425,6 +441,6 @@ int main(void)
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(ensure_should_fail_on_failed_realloc);
return UNITY_END();
}

View File

@@ -49,16 +49,16 @@ static void print_number_should_print_zero(void)
static void print_number_should_print_negative_integers(void)
{
assert_print_number("-1", -1.0);
assert_print_number("-32768", -32768.0);
assert_print_number("-1", -1);
assert_print_number("-32768", -32768);
assert_print_number("-2147483648", -2147483648.0);
}
static void print_number_should_print_positive_integers(void)
{
assert_print_number("1", 1.0);
assert_print_number("32767", 32767.0);
assert_print_number("2147483647", 2147483647.0);
assert_print_number("1", 1);
assert_print_number("32767", 32767);
assert_print_number("2147483647", 2147483647);
}
static void print_number_should_print_positive_reals(void)
@@ -68,7 +68,6 @@ static void print_number_should_print_positive_reals(void)
assert_print_number("1000000000000", 10e11);
assert_print_number("1.23e+129", 123e+127);
assert_print_number("1.23e-126", 123e-128);
assert_print_number("3.1415926535897931", 3.1415926535897931);
}
static void print_number_should_print_negative_reals(void)