Merge branch 'master' into fix-czstring
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5ab9c52..cfd1a4e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -12,7 +12,7 @@
# CMake versions greater than the JSONCPP_NEWEST_VALIDATED_POLICIES_VERSION policies will
# continue to generate policy warnings "CMake Warning (dev)...Policy CMP0XXX is not set:"
#
-set(JSONCPP_OLDEST_VALIDATED_POLICIES_VERSION "3.8.0")
+set(JSONCPP_OLDEST_VALIDATED_POLICIES_VERSION "3.10.0")
set(JSONCPP_NEWEST_VALIDATED_POLICIES_VERSION "3.13.2")
cmake_minimum_required(VERSION ${JSONCPP_OLDEST_VALIDATED_POLICIES_VERSION})
if("${CMAKE_VERSION}" VERSION_LESS "${JSONCPP_NEWEST_VALIDATED_POLICIES_VERSION}")
@@ -79,6 +79,7 @@
option(JSONCPP_WITH_PKGCONFIG_SUPPORT "Generate and install .pc files" ON)
option(JSONCPP_WITH_CMAKE_PACKAGE "Generate and install cmake package files" ON)
option(JSONCPP_WITH_EXAMPLE "Compile JsonCpp example" OFF)
+option(JSONCPP_WITH_INSTALL "Include JsonCpp header and binaries in the install target" ON)
option(JSONCPP_STATIC_WINDOWS_RUNTIME "Use static (MT/MTd) Windows runtime" OFF)
option(BUILD_SHARED_LIBS "Build jsoncpp_lib as a shared library." ON)
option(BUILD_STATIC_LIBS "Build jsoncpp_lib as a static library." ON)
diff --git a/README.md b/README.md
index fbdd0be..25b2d2b 100644
--- a/README.md
+++ b/README.md
@@ -16,121 +16,89 @@
existing comment in deserialization/serialization steps, making it a convenient
format to store user input files.
-## Documentation
+## Project Status
-[JsonCpp documentation][JsonCpp-documentation] is generated using [Doxygen][].
+JsonCpp is a mature project in maintenance mode. Our priority is providing a stable,
+reliable JSON library for the long tail of C++ development.
-[JsonCpp-documentation]: http://open-source-parsers.github.io/jsoncpp-docs/doxygen/index.html
-[Doxygen]: http://www.doxygen.org
+### Current Focus
+
+* **Security:** Addressing vulnerabilities and fuzzing results.
+* **Compatibility:** Ensuring the library builds without warnings on the latest versions of GCC,
+Clang, and MSVC.
+* **Reliability:** Fixing regressions and critical logical bugs.
+
+### Out of Scope
+
+* **Performance:** We are not competing with SIMD-accelerated or reflection-based parsers.
+* **Features:** We are generally not accepting requests for new data formats or major API changes.
+
+JsonCpp remains a primary choice for developers who require comment preservation and support for
+legacy toolchains where modern C++ standards are unavailable. The library is intended to be a
+reliable dependency that does not require frequent updates or major migration efforts.
## A note on backward-compatibility
-* `1.y.z` is built with C++11.
-* `0.y.z` can be used with older compilers.
-* `00.11.z` can be used both in old and new compilers.
-* Major versions maintain binary-compatibility.
+* **`1.y.z` (master):** Actively maintained. Requires C++11.
-### Special note
+* **`0.y.z`:** Legacy support for pre-C++11 compilers. Maintenance is limited to critical security fixes.
-The branch `00.11.z`is a new branch, its major version number `00` is to show
-that it is different from `0.y.z` and `1.y.z`, the main purpose of this branch
-is to make a balance between the other two branches. Thus, users can use some
-new features in this new branch that introduced in 1.y.z, but can hardly applied
-into 0.y.z.
+* **`00.11.z`:** Discontinued.
-## Using JsonCpp in your project
+Major versions maintain binary compatibility. Critical security fixes are accepted for both the `master` and `0.y.z` branches.
-### The vcpkg dependency manager
+## Integration
-You can download and install JsonCpp using the [vcpkg](https://github.com/Microsoft/vcpkg/)
-dependency manager, which has installation instruction dependent on your
-build system. For example, if you are in a CMake project, the
-[CMake install tutorial](https://learn.microsoft.com/en-us/vcpkg/get_started/get-started?pivots=shell-powershell)
-suggests the follow installation method.
+> [!NOTE]
+> Package manager ports (vcpkg, Conan, etc.) are community-maintained. Please report outdated versions or missing generators to their respective repositories.
-First, clone and set up `vcpkg`.
+### vcpkg
+Add `jsoncpp` to your `vcpkg.json` manifest:
-```sh
- git clone https://github.com/Microsoft/vcpkg.git
- cd vcpkg
- ./bootstrap-vcpkg.sh
-```
-
-Then, create a [vcpkg.json manifest](https://learn.microsoft.com/en-us/vcpkg/reference/vcpkg-json),
-enabling manifest mode and adding JsonCpp to the manifest's dependencies list.
-
-```sh
- vcpkg new --application
- vcpkg add port jsoncpp
-```
-
-> [!NOTE]: you can use vcpkg in either classic mode or manifest mode (recommended).
-
-#### Classic mode
-
-If your project does not have a `vcpkg.json`,
-your project is in [Classic mode](https://learn.microsoft.com/en-us/vcpkg/concepts/classic-mode)
-you can install JsonCpp by directly invoking the `install` command:
-
-```sh
- vcpkg install jsoncpp
-```
-
-### Manifest mode
-
-If your project *does* have a vcpkg.json manifest, your project is in [Manifest mode](https://learn.microsoft.com/en-us/vcpkg/concepts/manifest-mode)
-and you need to add JsonCpp to your package manifest dependencies, then invoke
-install with no arguments.
-
-```sh
- vcpkg add port jsoncpp
- vcpkg install
-```
-
-Example manifest:
-
-```sh
+```json
{
- "name": "best-app-ever",
- "dependencies": [ "jsoncpp" ],
+ "dependencies": ["jsoncpp"]
}
```
-> [!NOTE] The JsonCpp 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.
+Or install via classic mode: `vcpkg install jsoncpp`.
-### Conan package manager
-
-You can download and install JsonCpp using the [Conan](https://conan.io/)
-package manager:
+### Conan
```sh
- conan install -r conancenter --requires="jsoncpp/[*]" --build=missing
+conan install --requires="jsoncpp/[*]" --build=missing
```
-The JsonCpp package in Conan Center is kept up to date by [ConanCenterIndex](https://github.com/conan-io/conan-center-index)
-contributors. If the version is out of date, please create an issue or pull request on the
-Conan Center Index repository.
+If you are using a `conanfile.txt` in a Conan 2 project, ensure you use the appropriate generators:
+
+```ini
+[requires]
+jsoncpp/[*]
+
+[generators]
+CMakeToolchain
+CMakeDeps
+```
+
+### Meson
+
+```sh
+meson wrap install jsoncpp
+```
### Amalgamated source
-See the [Wiki entry on Amalgamated Source](https://github.com/open-source-parsers/jsoncpp/wiki/Amalgamated-(Possibly-outdated)).
+> [!NOTE]
+> This approach may be outdated.
-### The Meson Build System
+For projects requiring a single-header approach, see the [Wiki entry](https://github.com/open-source-parsers/jsoncpp/wiki/Amalgamated-(Possibly-outdated)).
-If you are using the [Meson Build System](http://mesonbuild.com), then you can
-get a wrap file by downloading it from [Meson WrapDB](https://mesonbuild.com/Wrapdb-projects.html),
-or simply use `meson wrap install jsoncpp`.
+## Documentation
-### Other ways
-
-If you have trouble, see the
-[Wiki](https://github.com/open-source-parsers/jsoncpp/wiki), or post a question
-as an Issue.
+Documentation is generated via [Doxygen](http://open-source-parsers.github.io/jsoncpp-docs/doxygen/index.html).
+Additional information is available on the [Project Wiki](https://github.com/open-source-parsers/jsoncpp/wiki).
## License
-See the [LICENSE](./LICENSE) file for details. In summary, JsonCpp is licensed
-under the MIT license, or public domain if desired and recognized in your
-jurisdiction.
+JsonCpp is licensed under the MIT license, or public domain where recognized.
+See [LICENSE](./LICENSE) for details.
diff --git a/RELEASE_1.9.7.md b/RELEASE_1.9.7.md
new file mode 100644
index 0000000..3607998
--- /dev/null
+++ b/RELEASE_1.9.7.md
@@ -0,0 +1,52 @@
+# jsoncpp 1.9.7 Release Work
+
+Issues to fix before tagging 1.9.7, each in a separate CL.
+
+---
+
+## Done
+
+- [x] **#1656** — Fix uninitialized CMake variable `JSONCPP_VERSION` in `version.in`
+ → Change `@JSONCPP_VERSION@` to `@jsoncpp_VERSION@`
+
+---
+
+## To Do
+
+### Security / Memory Safety
+
+- [ ] **#1626** — MemorySanitizer: use-of-uninitialized-value in `Json::Value::resolveReference`
+ → Uninitialized value detected by MSan in `json_value.cpp`. Need to identify and zero-initialize the offending member.
+
+- [ ] **#1623** — Use-after-free: `Json::Reader::parse` stores raw pointers into input string
+ → `Reader` stores `begin_`/`end_` pointers that dangle after the input `std::string` goes out of scope. `getFormattedErrorMessages()` then reads freed memory.
+ → Fix: copy the input document internally, or clearly document the lifetime requirement (the simpler option given the old Reader API is deprecated).
+
+### Correctness
+
+- [x] **#1565** — Number parsing breaks when user sets a non-C locale (e.g. `de_DE`)
+ → `istringstream`/`ostringstream` used for number parsing/writing inherit the global locale, which may use `,` as decimal separator instead of `.`.
+ → Fix: imbue streams with `std::locale::classic()` in `json_reader.cpp` and `json_writer.cpp`.
+
+- [ ] **#1546** — Control characters below 0x20 not rejected during parsing
+ → JSON spec requires rejecting unescaped control characters. jsoncpp currently accepts them.
+
+### Build / CMake
+
+- [ ] **#1634** — `JSON_DLL_BUILD` compile definition applied globally instead of per-target
+ → `add_compile_definitions` scopes it to all targets; should use `target_compile_definitions` scoped to the shared lib only.
+
+- [x] **#1598** — CMake 3.31 deprecation warning about compatibility with CMake < 3.10
+ → Update `cmake_minimum_required` to use `<min>...<max>` version range syntax, e.g. `cmake_minimum_required(VERSION 3.10...3.31)`.
+
+- [x] **#1595** — Linker errors with `string_view` API when jsoncpp built as C++11 but consumer uses C++17
+ → Root cause: `JSONCPP_HAS_STRING_VIEW` is not defined when building the library (forced C++11), but consumer with C++17 sees the `string_view` overloads in headers and tries to link them.
+ → Fix options: (a) export `JSONCPP_HAS_STRING_VIEW` in the CMake config so consumers see the same value, or (b) drop `CMAKE_CXX_STANDARD` force and use `target_compile_features(cxx_std_11)` instead.
+
+---
+
+## Skipped (not bugs)
+
+- **#1548** — "Memory leak" after parsing large files: confirmed to be normal allocator behavior (OS doesn't immediately reclaim heap). Not a library bug.
+- **#1533** — `clear()` then adding values fails: `clear()` preserves the value type by design. Confirmed user error.
+- **#1547** — Trailing commas/garbage not rejected: existing behavior, controllable via `strictMode()`. Not a regression.
diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt
index dc40d95..bbd6405 100644
--- a/include/CMakeLists.txt
+++ b/include/CMakeLists.txt
@@ -1,5 +1,8 @@
+if (JSONCPP_WITH_INSTALL)
+
file(GLOB INCLUDE_FILES "json/*.h")
install(FILES
${INCLUDE_FILES}
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/json)
+endif()
\ No newline at end of file
diff --git a/src/lib_json/CMakeLists.txt b/src/lib_json/CMakeLists.txt
index 3037eb0..9658941 100644
--- a/src/lib_json/CMakeLists.txt
+++ b/src/lib_json/CMakeLists.txt
@@ -107,12 +107,6 @@
if(BUILD_SHARED_LIBS)
- if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
- add_compile_definitions(JSON_DLL_BUILD)
- else()
- add_definitions(-DJSON_DLL_BUILD)
- endif()
-
set(SHARED_LIB ${PROJECT_NAME}_lib)
add_library(${SHARED_LIB} SHARED ${PUBLIC_HEADERS} ${JSONCPP_SOURCES})
set_target_properties(${SHARED_LIB} PROPERTIES
@@ -122,6 +116,8 @@
POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS}
)
+ target_compile_definitions(${SHARED_LIB} PRIVATE JSON_DLL_BUILD)
+
# Set library's runtime search path on OSX
if(APPLE)
set_target_properties(${SHARED_LIB} PROPERTIES INSTALL_RPATH "@loader_path/.")
@@ -196,6 +192,8 @@
list(APPEND CMAKE_TARGETS ${OBJECT_LIB})
endif()
+if (JSONCPP_WITH_INSTALL)
+
install(TARGETS ${CMAKE_TARGETS} ${INSTALL_EXPORT}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
@@ -203,3 +201,4 @@
OBJECTS DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
+endif()
diff --git a/src/lib_json/json_reader.cpp b/src/lib_json/json_reader.cpp
index 265b030..b0b6eb0 100644
--- a/src/lib_json/json_reader.cpp
+++ b/src/lib_json/json_reader.cpp
@@ -39,7 +39,7 @@
// Define JSONCPP_DEPRECATED_STACK_LIMIT as an appropriate integer at compile
// time to change the stack limit
#if !defined(JSONCPP_DEPRECATED_STACK_LIMIT)
-#define JSONCPP_DEPRECATED_STACK_LIMIT 1000
+#define JSONCPP_DEPRECATED_STACK_LIMIT 256
#endif
static size_t const stackLimit_g =
@@ -583,6 +583,7 @@
bool Reader::decodeDouble(Token& token, Value& decoded) {
double value = 0;
IStringStream is(String(token.start_, token.end_));
+ is.imbue(std::locale::classic());
if (!(is >> value)) {
if (value == std::numeric_limits<double>::max())
value = std::numeric_limits<double>::infinity();
@@ -1617,6 +1618,7 @@
bool OurReader::decodeDouble(Token& token, Value& decoded) {
double value = 0;
IStringStream is(String(token.start_, token.end_));
+ is.imbue(std::locale::classic());
if (!(is >> value)) {
if (value == std::numeric_limits<double>::max())
value = std::numeric_limits<double>::infinity();
@@ -1932,7 +1934,7 @@
(*settings)["allowDroppedNullPlaceholders"] = false;
(*settings)["allowNumericKeys"] = false;
(*settings)["allowSingleQuotes"] = false;
- (*settings)["stackLimit"] = 1000;
+ (*settings)["stackLimit"] = 256;
(*settings)["failIfExtra"] = true;
(*settings)["rejectDupKeys"] = true;
(*settings)["allowSpecialFloats"] = false;
@@ -1949,7 +1951,7 @@
(*settings)["allowDroppedNullPlaceholders"] = false;
(*settings)["allowNumericKeys"] = false;
(*settings)["allowSingleQuotes"] = false;
- (*settings)["stackLimit"] = 1000;
+ (*settings)["stackLimit"] = 256;
(*settings)["failIfExtra"] = false;
(*settings)["rejectDupKeys"] = false;
(*settings)["allowSpecialFloats"] = false;
@@ -1965,7 +1967,7 @@
(*settings)["allowDroppedNullPlaceholders"] = false;
(*settings)["allowNumericKeys"] = false;
(*settings)["allowSingleQuotes"] = false;
- (*settings)["stackLimit"] = 1000;
+ (*settings)["stackLimit"] = 256;
(*settings)["failIfExtra"] = true;
(*settings)["rejectDupKeys"] = false;
(*settings)["allowSpecialFloats"] = false;
diff --git a/src/test_lib_json/main.cpp b/src/test_lib_json/main.cpp
index 7ebd466..d6938c1 100644
--- a/src/test_lib_json/main.cpp
+++ b/src/test_lib_json/main.cpp
@@ -3413,6 +3413,16 @@
JSONTEST_ASSERT_THROWS(
reader->parse(doc, doc + std::strlen(doc), &root, &errs));
}
+ // Default stack limit should reject deeply nested input (regression test for
+ // stack exhaustion from fuzz input like [[[[...]]]])
+ {
+ Json::CharReaderBuilder defaultBuilder;
+ Json::String nested(300, '[');
+ CharReaderPtr reader(defaultBuilder.newCharReader());
+ Json::String errs;
+ JSONTEST_ASSERT_THROWS(reader->parse(
+ nested.data(), nested.data() + nested.size(), &root, &errs));
+ }
#endif // JSON_USE_EXCEPTION
}
diff --git a/version.in b/version.in
index bfc03f7..f1e3335 100644
--- a/version.in
+++ b/version.in
@@ -1 +1 @@
-@JSONCPP_VERSION@
+@jsoncpp_VERSION@