Skip to content

Commit b377070

Browse files
authored
Merge branch 'master' into write-string
2 parents 8532e06 + 2072e2b commit b377070

File tree

16 files changed

+151
-48
lines changed

16 files changed

+151
-48
lines changed

.github/workflows/clang-format.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: clang-format check
2-
on: [check_run, push]
2+
on: [check_run, pull_request, push]
33

44
jobs:
55
formatting-check:

.github/workflows/cmake.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: cmake
2+
on: [check_run, push, pull_request]
3+
jobs:
4+
cmake-publish:
5+
runs-on: ${{ matrix.os }}
6+
7+
strategy:
8+
fail-fast: false
9+
matrix:
10+
os: [ubuntu-latest, windows-latest, macos-latest]
11+
12+
steps:
13+
- name: checkout project
14+
uses: actions/checkout@v4
15+
16+
- name: build project
17+
uses: threeal/[email protected]
18+

.github/workflows/meson.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
name: meson build and test
22
run-name: update pushed to ${{ github.ref }}
3-
on: [check_run, push]
3+
on: [check_run, push, pull_request]
44

55
jobs:
6-
publish:
6+
meson-publish:
77
runs-on: ${{ matrix.os }}
88

99
strategy:
@@ -32,7 +32,7 @@ jobs:
3232
ninja-version: 1.11.1.1
3333
action: test
3434

35-
coverage:
35+
meson-coverage:
3636
runs-on: ubuntu-latest
3737

3838
steps:

CMakeLists.txt

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,6 @@ endif()
5454

5555
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
5656

57-
# ---------------------------------------------------------------------------
58-
# use ccache if found, has to be done before project()
59-
# ---------------------------------------------------------------------------
60-
find_program(CCACHE_EXECUTABLE "ccache" HINTS /usr/local/bin /opt/local/bin)
61-
if(CCACHE_EXECUTABLE)
62-
message(STATUS "use ccache")
63-
set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_EXECUTABLE}" CACHE PATH "ccache" FORCE)
64-
set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_EXECUTABLE}" CACHE PATH "ccache" FORCE)
65-
endif()
66-
6757
project(jsoncpp
6858
# Note: version must be updated in three places when doing a release. This
6959
# annoying process ensures that amalgamate, CMake, and meson all report the
@@ -103,7 +93,9 @@ if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
10393
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" CACHE PATH "Executable/dll output dir.")
10494
endif()
10595

106-
set(JSONCPP_USE_SECURE_MEMORY "0" CACHE STRING "-D...=1 to use memory-wiping allocator for STL")
96+
if(JSONCPP_USE_SECURE_MEMORY)
97+
add_definitions("-DJSONCPP_USE_SECURE_MEMORY=1")
98+
endif()
10799

108100
configure_file("${PROJECT_SOURCE_DIR}/version.in"
109101
"${PROJECT_BINARY_DIR}/version"

SECURITY.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Security Policy
2+
3+
If you have discovered a security vulnerability in this project, please report it
4+
privately. **Do not disclose it as a public issue.** This gives us time to work with you
5+
to fix the issue before public exposure, reducing the chance that the exploit will be
6+
used before a patch is released.
7+
8+
Please submit the report by filling out
9+
[this form](https://github.com/open-source-parsers/jsoncpp/security/advisories/new).
10+
11+
Please provide the following information in your report:
12+
13+
- A description of the vulnerability and its impact
14+
- How to reproduce the issue
15+
16+
This project is maintained by volunteers on a reasonable-effort basis. As such,
17+
we ask that you give us 90 days to work on a fix before public exposure.

amalgamate.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def amalgamate_source(source_top_dir=None,
6363
"""
6464
print("Amalgamating header...")
6565
header = AmalgamationFile(source_top_dir)
66-
header.add_text("/// Json-cpp amalgamated header (http://jsoncpp.sourceforge.net/).")
66+
header.add_text("/// Json-cpp amalgamated header (https://github.com/open-source-parsers/jsoncpp/).")
6767
header.add_text('/// It is intended to be used with #include "%s"' % header_include_path)
6868
header.add_file("LICENSE", wrap_in_comment=True)
6969
header.add_text("#ifndef JSON_AMALGAMATED_H_INCLUDED")
@@ -90,7 +90,7 @@ def amalgamate_source(source_top_dir=None,
9090
forward_header_include_path = base + "-forwards" + ext
9191
print("Amalgamating forward header...")
9292
header = AmalgamationFile(source_top_dir)
93-
header.add_text("/// Json-cpp amalgamated forward header (http://jsoncpp.sourceforge.net/).")
93+
header.add_text("/// Json-cpp amalgamated forward header (https://github.com/open-source-parsers/jsoncpp/).")
9494
header.add_text('/// It is intended to be used with #include "%s"' % forward_header_include_path)
9595
header.add_text("/// This header provides forward declaration for all JsonCpp types.")
9696
header.add_file("LICENSE", wrap_in_comment=True)
@@ -112,7 +112,7 @@ def amalgamate_source(source_top_dir=None,
112112

113113
print("Amalgamating source...")
114114
source = AmalgamationFile(source_top_dir)
115-
source.add_text("/// Json-cpp amalgamated source (http://jsoncpp.sourceforge.net/).")
115+
source.add_text("/// Json-cpp amalgamated source (https://github.com/open-source-parsers/jsoncpp/).")
116116
source.add_text('/// It is intended to be used with #include "%s"' % header_include_path)
117117
source.add_file("LICENSE", wrap_in_comment=True)
118118
source.add_text("")

example/readFromString/readFromString.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ int main() {
2525
const std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
2626
if (!reader->parse(rawJson.c_str(), rawJson.c_str() + rawJsonLength, &root,
2727
&err)) {
28-
std::cout << "error" << std::endl;
28+
std::cout << "error: " << err << std::endl;
2929
return EXIT_FAILURE;
3030
}
3131
}

include/PreventInSourceBuilds.cmake

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
# This function will prevent in-source builds
33
function(AssureOutOfSourceBuilds)
44
# make sure the user doesn't play dirty with symlinks
5-
get_filename_component(srcdir "${CMAKE_SOURCE_DIR}" REALPATH)
6-
get_filename_component(bindir "${CMAKE_BINARY_DIR}" REALPATH)
5+
get_filename_component(srcdir "${CMAKE_CURRENT_SOURCE_DIR}" REALPATH)
6+
get_filename_component(bindir "${CMAKE_CURRENT_BINARY_DIR}" REALPATH)
77

88
# disallow in-source builds
99
if("${srcdir}" STREQUAL "${bindir}")

include/json/reader.h

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,12 @@ class JSON_API Reader {
244244
*/
245245
class JSON_API CharReader {
246246
public:
247+
struct JSON_API StructuredError {
248+
ptrdiff_t offset_start;
249+
ptrdiff_t offset_limit;
250+
String message;
251+
};
252+
247253
virtual ~CharReader() = default;
248254
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
249255
* document. The document must be a UTF-8 encoded string containing the
@@ -262,7 +268,12 @@ class JSON_API CharReader {
262268
* error occurred.
263269
*/
264270
virtual bool parse(char const* beginDoc, char const* endDoc, Value* root,
265-
String* errs) = 0;
271+
String* errs);
272+
273+
/** \brief Returns a vector of structured errors encountered while parsing.
274+
* Each parse call resets the stored list of errors.
275+
*/
276+
std::vector<StructuredError> getStructuredErrors() const;
266277

267278
class JSON_API Factory {
268279
public:
@@ -272,6 +283,20 @@ class JSON_API CharReader {
272283
*/
273284
virtual CharReader* newCharReader() const = 0;
274285
}; // Factory
286+
287+
protected:
288+
class Impl {
289+
public:
290+
virtual ~Impl() = default;
291+
virtual bool parse(char const* beginDoc, char const* endDoc, Value* root,
292+
String* errs) = 0;
293+
virtual std::vector<StructuredError> getStructuredErrors() const = 0;
294+
};
295+
296+
explicit CharReader(std::unique_ptr<Impl> impl) : _impl(std::move(impl)) {}
297+
298+
private:
299+
std::unique_ptr<Impl> _impl;
275300
}; // CharReader
276301

277302
/** \brief Build a CharReader implementation.

include/json/version.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,9 @@
1818
((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \
1919
(JSONCPP_VERSION_PATCH << 8))
2020

21-
#ifdef JSONCPP_USING_SECURE_MEMORY
22-
#undef JSONCPP_USING_SECURE_MEMORY
23-
#endif
21+
#if !defined(JSONCPP_USE_SECURE_MEMORY)
2422
#define JSONCPP_USING_SECURE_MEMORY 0
23+
#endif
2524
// If non-zero, the library zeroes any memory that it has allocated before
2625
// it frees its memory.
2726

jsoncppConfig.cmake.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
cmake_policy(PUSH)
2-
cmake_policy(VERSION 3.0)
2+
cmake_policy(VERSION 3.0...3.26)
33

44
@PACKAGE_INIT@
55

meson.build

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ if meson.is_subproject() or not get_option('tests')
7373
subdir_done()
7474
endif
7575

76-
python = import('python').find_installation()
76+
python = find_program('python3')
7777

7878
jsoncpp_test = executable(
7979
'jsoncpp_test', files([

src/lib_json/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ if(BUILD_STATIC_LIBS)
144144

145145
# avoid name clashes on windows as the shared import lib is also named jsoncpp.lib
146146
if(NOT DEFINED STATIC_SUFFIX AND BUILD_SHARED_LIBS)
147-
if (MSVC)
147+
if (WIN32)
148148
set(STATIC_SUFFIX "_static")
149149
else()
150150
set(STATIC_SUFFIX "")

src/lib_json/json_reader.cpp

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -877,17 +877,12 @@ class OurReader {
877877
public:
878878
using Char = char;
879879
using Location = const Char*;
880-
struct StructuredError {
881-
ptrdiff_t offset_start;
882-
ptrdiff_t offset_limit;
883-
String message;
884-
};
885880

886881
explicit OurReader(OurFeatures const& features);
887882
bool parse(const char* beginDoc, const char* endDoc, Value& root,
888883
bool collectComments = true);
889884
String getFormattedErrorMessages() const;
890-
std::vector<StructuredError> getStructuredErrors() const;
885+
std::vector<CharReader::StructuredError> getStructuredErrors() const;
891886

892887
private:
893888
OurReader(OurReader const&); // no impl
@@ -1834,10 +1829,11 @@ String OurReader::getFormattedErrorMessages() const {
18341829
return formattedMessage;
18351830
}
18361831

1837-
std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
1838-
std::vector<OurReader::StructuredError> allErrors;
1832+
std::vector<CharReader::StructuredError>
1833+
OurReader::getStructuredErrors() const {
1834+
std::vector<CharReader::StructuredError> allErrors;
18391835
for (const auto& error : errors_) {
1840-
OurReader::StructuredError structured;
1836+
CharReader::StructuredError structured;
18411837
structured.offset_start = error.token_.start_ - begin_;
18421838
structured.offset_limit = error.token_.end_ - begin_;
18431839
structured.message = error.message_;
@@ -1847,20 +1843,36 @@ std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
18471843
}
18481844

18491845
class OurCharReader : public CharReader {
1850-
bool const collectComments_;
1851-
OurReader reader_;
18521846

18531847
public:
18541848
OurCharReader(bool collectComments, OurFeatures const& features)
1855-
: collectComments_(collectComments), reader_(features) {}
1856-
bool parse(char const* beginDoc, char const* endDoc, Value* root,
1857-
String* errs) override {
1858-
bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
1859-
if (errs) {
1860-
*errs = reader_.getFormattedErrorMessages();
1849+
: CharReader(
1850+
std::unique_ptr<OurImpl>(new OurImpl(collectComments, features))) {}
1851+
1852+
protected:
1853+
class OurImpl : public Impl {
1854+
public:
1855+
OurImpl(bool collectComments, OurFeatures const& features)
1856+
: collectComments_(collectComments), reader_(features) {}
1857+
1858+
bool parse(char const* beginDoc, char const* endDoc, Value* root,
1859+
String* errs) override {
1860+
bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
1861+
if (errs) {
1862+
*errs = reader_.getFormattedErrorMessages();
1863+
}
1864+
return ok;
18611865
}
1862-
return ok;
1863-
}
1866+
1867+
std::vector<CharReader::StructuredError>
1868+
getStructuredErrors() const override {
1869+
return reader_.getStructuredErrors();
1870+
}
1871+
1872+
private:
1873+
bool const collectComments_;
1874+
OurReader reader_;
1875+
};
18641876
};
18651877

18661878
CharReaderBuilder::CharReaderBuilder() { setDefaults(&settings_); }
@@ -1950,6 +1962,16 @@ void CharReaderBuilder::setDefaults(Json::Value* settings) {
19501962
//! [CharReaderBuilderDefaults]
19511963
}
19521964

1965+
std::vector<CharReader::StructuredError>
1966+
CharReader::getStructuredErrors() const {
1967+
return _impl->getStructuredErrors();
1968+
}
1969+
1970+
bool CharReader::parse(char const* beginDoc, char const* endDoc, Value* root,
1971+
String* errs) {
1972+
return _impl->parse(beginDoc, endDoc, root, errs);
1973+
}
1974+
19531975
//////////////////////////////////
19541976
// global functions
19551977

src/lib_json/json_value.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1205,7 +1205,7 @@ bool Value::removeIndex(ArrayIndex index, Value* removed) {
12051205
return false;
12061206
}
12071207
if (removed)
1208-
*removed = it->second;
1208+
*removed = std::move(it->second);
12091209
ArrayIndex oldSize = size();
12101210
// shift left all items left, into the place of the "removed"
12111211
for (ArrayIndex i = index; i < (oldSize - 1); ++i) {

src/test_lib_json/main.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3917,6 +3917,36 @@ JSONTEST_FIXTURE_LOCAL(FuzzTest, fuzzDoesntCrash) {
39173917
example.size()));
39183918
}
39193919

3920+
struct ParseWithStructuredErrorsTest : JsonTest::TestCase {
3921+
void testErrors(
3922+
const std::string& doc, bool success,
3923+
const std::vector<Json::CharReader::StructuredError>& expectedErrors) {
3924+
Json::CharReaderBuilder b;
3925+
CharReaderPtr reader(b.newCharReader());
3926+
Json::Value root;
3927+
JSONTEST_ASSERT_EQUAL(
3928+
reader->parse(doc.data(), doc.data() + doc.length(), &root, nullptr),
3929+
success);
3930+
auto actualErrors = reader->getStructuredErrors();
3931+
JSONTEST_ASSERT_EQUAL(expectedErrors.size(), actualErrors.size());
3932+
for (std::size_t i = 0; i < actualErrors.size(); i++) {
3933+
const auto& a = actualErrors[i];
3934+
const auto& e = expectedErrors[i];
3935+
JSONTEST_ASSERT_EQUAL(a.offset_start, e.offset_start);
3936+
JSONTEST_ASSERT_EQUAL(a.offset_limit, e.offset_limit);
3937+
JSONTEST_ASSERT_STRING_EQUAL(a.message, e.message);
3938+
}
3939+
}
3940+
};
3941+
3942+
JSONTEST_FIXTURE_LOCAL(ParseWithStructuredErrorsTest, success) {
3943+
testErrors("{}", true, {});
3944+
}
3945+
3946+
JSONTEST_FIXTURE_LOCAL(ParseWithStructuredErrorsTest, singleError) {
3947+
testErrors("{ 1 : 2 }", false, {{2, 3, "Missing '}' or object member name"}});
3948+
}
3949+
39203950
int main(int argc, const char* argv[]) {
39213951
JsonTest::Runner runner;
39223952

0 commit comments

Comments
 (0)