Add the stackLimit option for jsoncpp (#1518)

This commit is contained in:
An Tao 2023-03-01 10:49:25 +08:00 committed by GitHub
parent bc028776f7
commit 394f9bd0d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 45 additions and 3 deletions

1
.gitignore vendored
View File

@ -33,6 +33,7 @@
build/ build/
cmake-build-debug/ cmake-build-debug/
cmake-build-debug-visual-studio/
.idea/ .idea/
lib/inc/drogon/version.h lib/inc/drogon/version.h
html/ html/

View File

@ -193,6 +193,8 @@
//files is the path where the csp files locate. If the path isn't prefixed with /, it is relative //files is the path where the csp files locate. If the path isn't prefixed with /, it is relative
//path of the current working directory. //path of the current working directory.
"dynamic_views_output_path": "", "dynamic_views_output_path": "",
//json_parser_stack_limit: 1000 by default, the maximum number of stack depth when reading a json string by the jsoncpp library.
"json_parser_stack_limit": 1000,
//enable_unicode_escaping_in_json: true by default, enable unicode escaping in json. //enable_unicode_escaping_in_json: true by default, enable unicode escaping in json.
"enable_unicode_escaping_in_json": true, "enable_unicode_escaping_in_json": true,
//float_precision_in_json: set precision of float number in json. //float_precision_in_json: set precision of float number in json.

View File

@ -193,6 +193,8 @@
//files is the path where the csp files locate. If the path isn't prefixed with /, it is relative //files is the path where the csp files locate. If the path isn't prefixed with /, it is relative
//path of the current working directory. //path of the current working directory.
"dynamic_views_output_path": "", "dynamic_views_output_path": "",
//json_parser_stack_limit: 1000 by default, the maximum number of stack depth when reading a json string by the jsoncpp library.
"json_parser_stack_limit": 1000,
//enable_unicode_escaping_in_json: true by default, enable unicode escaping in json. //enable_unicode_escaping_in_json: true by default, enable unicode escaping in json.
"enable_unicode_escaping_in_json": true, "enable_unicode_escaping_in_json": true,
//float_precision_in_json: set precision of float number in json. //float_precision_in_json: set precision of float number in json.

View File

@ -1193,7 +1193,7 @@ class DROGON_EXPORT HttpAppFramework : public trantor::NonCopyable
/// Set the HTML file that a directory would resolve to by default, default /// Set the HTML file that a directory would resolve to by default, default
/// is "index.html" /// is "index.html"
/** /**
* @brief Sets the page which would the server load in if it detects that * @brief Set the page which would the server load in if it detects that
* the user requested a directory * the user requested a directory
* *
* @note * @note
@ -1247,6 +1247,21 @@ class DROGON_EXPORT HttpAppFramework : public trantor::NonCopyable
virtual nosql::RedisClientPtr getFastRedisClient( virtual nosql::RedisClientPtr getFastRedisClient(
const std::string &name = "default") = 0; const std::string &name = "default") = 0;
/**
* @brief Set the maximum stack depth of the json parser when reading a json
* string, the default value is 1000.
*
* @note
* This operation can be performed by an option in the configuration file.
*/
virtual HttpAppFramework &setJsonParserStackLimit(
size_t limit) noexcept = 0;
/**
* @brief Get the maximum stack depth of the json parser when reading a json
* string.
*/
virtual size_t getJsonParserStackLimit() const noexcept = 0;
/** /**
* @brief This method is to enable or disable the unicode escaping (\u) in * @brief This method is to enable or disable the unicode escaping (\u) in
* the json string of HTTP responses or requests. it works (disable * the json string of HTTP responses or requests. it works (disable

View File

@ -378,6 +378,8 @@ static void loadApp(const Json::Value &app)
} }
} }
#endif #endif
auto stackLimit = app.get("json_parser_stack_limit", 0).asUInt64();
drogon::app().setJsonParserStackLimit(stackLimit);
auto unicodeEscaping = auto unicodeEscaping =
app.get("enable_unicode_escaping_in_json", true).asBool(); app.get("enable_unicode_escaping_in_json", true).asBool();
drogon::app().setUnicodeEscapingInJson(unicodeEscaping); drogon::app().setUnicodeEscapingInJson(unicodeEscaping);

View File

@ -431,6 +431,17 @@ class HttpAppFrameworkImpl final : public HttpAppFramework
return running_; return running_;
} }
HttpAppFramework &setJsonParserStackLimit(size_t limit) noexcept override
{
jsonStackLimit_ = limit;
return *this;
}
size_t getJsonParserStackLimit() const noexcept override
{
return jsonStackLimit_;
}
HttpAppFramework &setUnicodeEscapingInJson(bool enable) noexcept override HttpAppFramework &setUnicodeEscapingInJson(bool enable) noexcept override
{ {
usingUnicodeEscaping_ = enable; usingUnicodeEscaping_ = enable;
@ -666,6 +677,7 @@ class HttpAppFrameworkImpl final : public HttpAppFramework
size_t logfileSize_{100000000}; size_t logfileSize_{100000000};
size_t keepaliveRequestsNumber_{0}; size_t keepaliveRequestsNumber_{0};
size_t pipeliningRequestsNumber_{0}; size_t pipeliningRequestsNumber_{0};
size_t jsonStackLimit_{1000};
bool useSendfile_{true}; bool useSendfile_{true};
bool useGzip_{true}; bool useGzip_{true};
bool useBrotli_{false}; bool useBrotli_{false};

View File

@ -40,7 +40,11 @@ void HttpRequestImpl::parseJson() const
{ {
static std::once_flag once; static std::once_flag once;
static Json::CharReaderBuilder builder; static Json::CharReaderBuilder builder;
std::call_once(once, []() { builder["collectComments"] = false; }); std::call_once(once, []() {
builder["collectComments"] = false;
builder["stackLimit"] = static_cast<Json::UInt>(
drogon::app().getJsonParserStackLimit());
});
jsonPtr_ = std::make_shared<Json::Value>(); jsonPtr_ = std::make_shared<Json::Value>();
JSONCPP_STRING errs; JSONCPP_STRING errs;
std::unique_ptr<Json::CharReader> reader(builder.newCharReader()); std::unique_ptr<Json::CharReader> reader(builder.newCharReader());

View File

@ -897,7 +897,11 @@ void HttpResponseImpl::parseJson() const
{ {
static std::once_flag once; static std::once_flag once;
static Json::CharReaderBuilder builder; static Json::CharReaderBuilder builder;
std::call_once(once, []() { builder["collectComments"] = false; }); std::call_once(once, []() {
builder["collectComments"] = false;
builder["stackLimit"] =
static_cast<Json::UInt>(drogon::app().getJsonParserStackLimit());
});
JSONCPP_STRING errs; JSONCPP_STRING errs;
std::unique_ptr<Json::CharReader> reader(builder.newCharReader()); std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
if (bodyPtr_) if (bodyPtr_)