fix crash where simple type with sub-schema has a bad value

This commit is contained in:
Steve Hanson 2021-02-12 17:36:55 +00:00
parent 167efb4fa0
commit 9bb81e20ff
2 changed files with 64 additions and 32 deletions

View File

@ -733,6 +733,7 @@ public:
}
RAPIDJSON_FORCEINLINE bool EndValue(Context& context) const {
// Only check pattern properties if we have validators
if (context.patternPropertiesValidatorCount > 0) {
bool otherValid = false;
SizeType count = context.patternPropertiesValidatorCount;
@ -775,41 +776,44 @@ public:
foundEnum:;
}
if (allOf_.schemas)
for (SizeType i = allOf_.begin; i < allOf_.begin + allOf_.count; i++)
if (!context.validators[i]->IsValid()) {
context.error_handler.NotAllOf(&context.validators[allOf_.begin], allOf_.count);
RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAllOf);
}
if (anyOf_.schemas) {
for (SizeType i = anyOf_.begin; i < anyOf_.begin + anyOf_.count; i++)
if (context.validators[i]->IsValid())
goto foundAny;
context.error_handler.NoneOf(&context.validators[anyOf_.begin], anyOf_.count);
RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAnyOf);
foundAny:;
}
// Only check allOf etc if we have validators
if (context.validatorCount > 0) {
if (allOf_.schemas)
for (SizeType i = allOf_.begin; i < allOf_.begin + allOf_.count; i++)
if (!context.validators[i]->IsValid()) {
context.error_handler.NotAllOf(&context.validators[allOf_.begin], allOf_.count);
RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAllOf);
}
if (oneOf_.schemas) {
bool oneValid = false;
for (SizeType i = oneOf_.begin; i < oneOf_.begin + oneOf_.count; i++)
if (context.validators[i]->IsValid()) {
if (oneValid) {
context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count, true);
RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorOneOfMatch);
} else
oneValid = true;
}
if (!oneValid) {
context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count, false);
RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorOneOf);
if (anyOf_.schemas) {
for (SizeType i = anyOf_.begin; i < anyOf_.begin + anyOf_.count; i++)
if (context.validators[i]->IsValid())
goto foundAny;
context.error_handler.NoneOf(&context.validators[anyOf_.begin], anyOf_.count);
RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAnyOf);
foundAny:;
}
}
if (not_ && context.validators[notValidatorIndex_]->IsValid()) {
context.error_handler.Disallowed();
RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorNot);
if (oneOf_.schemas) {
bool oneValid = false;
for (SizeType i = oneOf_.begin; i < oneOf_.begin + oneOf_.count; i++)
if (context.validators[i]->IsValid()) {
if (oneValid) {
context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count, true);
RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorOneOfMatch);
} else
oneValid = true;
}
if (!oneValid) {
context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count, false);
RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorOneOf);
}
}
if (not_ && context.validators[notValidatorIndex_]->IsValid()) {
context.error_handler.Disallowed();
RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorNot);
}
}
return true;

View File

@ -2550,6 +2550,34 @@ TEST(SchemaValidator, ContinueOnErrors_RogueString) {
CrtAllocator::Free(schema);
}
// Test that when kValidateContinueOnErrorFlag is set, an incorrect simple type with a sub-schema is handled correctly.
// This tests that we don't blow up when there is a type mismatch but there is a sub-schema present
TEST(SchemaValidator, ContinueOnErrors_Issue2) {
Document sd;
sd.Parse("{\"type\":\"string\", \"anyOf\":[{\"maxLength\":2}]}");
ASSERT_FALSE(sd.HasParseError());
SchemaDocument s(sd);
VALIDATE(s, "\"AB\"", true);
INVALIDATE_(s, "\"ABC\"", "#", "errors", "#",
"{ \"anyOf\": {"
" \"errors\": [{"
" \"maxLength\": {"
" \"errorCode\": 6, \"instanceRef\": \"#\", \"schemaRef\": \"#/anyOf/0\", \"expected\": 2, \"actual\": \"ABC\""
" }"
" }],"
" \"errorCode\": 24, \"instanceRef\": \"#\", \"schemaRef\": \"#\""
" }"
"}",
kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidator, Pointer);
// Invalid type
INVALIDATE_(s, "333", "#", "errors", "#",
"{ \"type\": {"
" \"errorCode\": 20, \"instanceRef\": \"#\", \"schemaRef\": \"#\", \"expected\": [\"string\"], \"actual\": \"integer\""
" }"
"}",
kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidator, Pointer);
}
TEST(SchemaValidator, Schema_UnknownError) {
ASSERT_TRUE(SchemaValidator::SchemaType::GetValidateErrorKeyword(kValidateErrors).GetString() == std::string("null"));
}