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

View File

@ -2550,6 +2550,34 @@ TEST(SchemaValidator, ContinueOnErrors_RogueString) {
CrtAllocator::Free(schema); 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) { TEST(SchemaValidator, Schema_UnknownError) {
ASSERT_TRUE(SchemaValidator::SchemaType::GetValidateErrorKeyword(kValidateErrors).GetString() == std::string("null")); ASSERT_TRUE(SchemaValidator::SchemaType::GetValidateErrorKeyword(kValidateErrors).GetString() == std::string("null"));
} }