|
|
|
@ -25,6 +25,9 @@ |
|
|
|
|
|
|
|
|
|
#include "src/core/lib/json/json.h" |
|
|
|
|
|
|
|
|
|
#define GRPC_JSON_MAX_DEPTH 255 |
|
|
|
|
#define GRPC_JSON_MAX_ERRORS 16 |
|
|
|
|
|
|
|
|
|
namespace grpc_core { |
|
|
|
|
|
|
|
|
|
namespace { |
|
|
|
@ -92,7 +95,7 @@ class JsonReader { |
|
|
|
|
void StringAddUtf32(uint32_t c); |
|
|
|
|
|
|
|
|
|
Json* CreateAndLinkValue(); |
|
|
|
|
void StartContainer(Json::Type type); |
|
|
|
|
bool StartContainer(Json::Type type); |
|
|
|
|
void EndContainer(); |
|
|
|
|
void SetKey(); |
|
|
|
|
void SetString(); |
|
|
|
@ -111,6 +114,7 @@ class JsonReader { |
|
|
|
|
uint16_t unicode_char_ = 0; |
|
|
|
|
uint16_t unicode_high_surrogate_ = 0; |
|
|
|
|
std::vector<grpc_error*> errors_; |
|
|
|
|
bool truncated_errors_ = false; |
|
|
|
|
|
|
|
|
|
Json root_value_; |
|
|
|
|
std::vector<Json*> stack_; |
|
|
|
@ -169,11 +173,15 @@ Json* JsonReader::CreateAndLinkValue() { |
|
|
|
|
Json* parent = stack_.back(); |
|
|
|
|
if (parent->type() == Json::Type::OBJECT) { |
|
|
|
|
if (parent->object_value().find(key_) != parent->object_value().end()) { |
|
|
|
|
char* msg; |
|
|
|
|
gpr_asprintf(&msg, "duplicate key \"%s\" at index %" PRIuPTR, |
|
|
|
|
key_.c_str(), CurrentIndex()); |
|
|
|
|
errors_.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg)); |
|
|
|
|
gpr_free(msg); |
|
|
|
|
if (errors_.size() == GRPC_JSON_MAX_ERRORS) { |
|
|
|
|
truncated_errors_ = true; |
|
|
|
|
} else { |
|
|
|
|
char* msg; |
|
|
|
|
gpr_asprintf(&msg, "duplicate key \"%s\" at index %" PRIuPTR, |
|
|
|
|
key_.c_str(), CurrentIndex()); |
|
|
|
|
errors_.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg)); |
|
|
|
|
gpr_free(msg); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
value = &(*parent->mutable_object())[std::move(key_)]; |
|
|
|
|
} else { |
|
|
|
@ -185,7 +193,19 @@ Json* JsonReader::CreateAndLinkValue() { |
|
|
|
|
return value; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void JsonReader::StartContainer(Json::Type type) { |
|
|
|
|
bool JsonReader::StartContainer(Json::Type type) { |
|
|
|
|
if (stack_.size() == GRPC_JSON_MAX_DEPTH) { |
|
|
|
|
if (errors_.size() == GRPC_JSON_MAX_ERRORS) { |
|
|
|
|
truncated_errors_ = true; |
|
|
|
|
} else { |
|
|
|
|
char* msg; |
|
|
|
|
gpr_asprintf(&msg, "exceeded max stack depth (%d) at index %" PRIuPTR, |
|
|
|
|
GRPC_JSON_MAX_DEPTH, CurrentIndex()); |
|
|
|
|
errors_.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg)); |
|
|
|
|
gpr_free(msg); |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
Json* value = CreateAndLinkValue(); |
|
|
|
|
if (type == Json::Type::OBJECT) { |
|
|
|
|
*value = Json::Object(); |
|
|
|
@ -194,6 +214,7 @@ void JsonReader::StartContainer(Json::Type type) { |
|
|
|
|
*value = Json::Array(); |
|
|
|
|
} |
|
|
|
|
stack_.push_back(value); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void JsonReader::EndContainer() { |
|
|
|
@ -483,13 +504,17 @@ JsonReader::Status JsonReader::Run() { |
|
|
|
|
|
|
|
|
|
case '{': |
|
|
|
|
container_just_begun_ = true; |
|
|
|
|
StartContainer(Json::Type::OBJECT); |
|
|
|
|
if (!StartContainer(Json::Type::OBJECT)) { |
|
|
|
|
return Status::GRPC_JSON_PARSE_ERROR; |
|
|
|
|
} |
|
|
|
|
state_ = State::GRPC_JSON_STATE_OBJECT_KEY_BEGIN; |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case '[': |
|
|
|
|
container_just_begun_ = true; |
|
|
|
|
StartContainer(Json::Type::ARRAY); |
|
|
|
|
if (!StartContainer(Json::Type::ARRAY)) { |
|
|
|
|
return Status::GRPC_JSON_PARSE_ERROR; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
return Status::GRPC_JSON_PARSE_ERROR; |
|
|
|
@ -793,6 +818,11 @@ JsonReader::Status JsonReader::Run() { |
|
|
|
|
grpc_error* JsonReader::Parse(StringView input, Json* output) { |
|
|
|
|
JsonReader reader(input); |
|
|
|
|
Status status = reader.Run(); |
|
|
|
|
if (reader.truncated_errors_) { |
|
|
|
|
reader.errors_.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
|
|
|
|
"too many errors encountered during JSON parsing -- fix reported " |
|
|
|
|
"errors and try again to see additional errors")); |
|
|
|
|
} |
|
|
|
|
if (status == Status::GRPC_JSON_INTERNAL_ERROR) { |
|
|
|
|
char* msg; |
|
|
|
|
gpr_asprintf(&msg, "internal error in JSON parser at index %" PRIuPTR, |
|
|
|
|