Skip to content

Commit 9bb81e2

Browse files
author
Steve Hanson
committed
fix crash where simple type with sub-schema has a bad value
1 parent 167efb4 commit 9bb81e2

File tree

2 files changed

+64
-32
lines changed

2 files changed

+64
-32
lines changed

include/rapidjson/schema.h

Lines changed: 36 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,7 @@ class Schema {
733733
}
734734

735735
RAPIDJSON_FORCEINLINE bool EndValue(Context& context) const {
736+
// Only check pattern properties if we have validators
736737
if (context.patternPropertiesValidatorCount > 0) {
737738
bool otherValid = false;
738739
SizeType count = context.patternPropertiesValidatorCount;
@@ -775,41 +776,44 @@ class Schema {
775776
foundEnum:;
776777
}
777778

778-
if (allOf_.schemas)
779-
for (SizeType i = allOf_.begin; i < allOf_.begin + allOf_.count; i++)
780-
if (!context.validators[i]->IsValid()) {
781-
context.error_handler.NotAllOf(&context.validators[allOf_.begin], allOf_.count);
782-
RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAllOf);
783-
}
784-
785-
if (anyOf_.schemas) {
786-
for (SizeType i = anyOf_.begin; i < anyOf_.begin + anyOf_.count; i++)
787-
if (context.validators[i]->IsValid())
788-
goto foundAny;
789-
context.error_handler.NoneOf(&context.validators[anyOf_.begin], anyOf_.count);
790-
RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAnyOf);
791-
foundAny:;
792-
}
793-
794-
if (oneOf_.schemas) {
795-
bool oneValid = false;
796-
for (SizeType i = oneOf_.begin; i < oneOf_.begin + oneOf_.count; i++)
797-
if (context.validators[i]->IsValid()) {
798-
if (oneValid) {
799-
context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count, true);
800-
RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorOneOfMatch);
801-
} else
802-
oneValid = true;
779+
// Only check allOf etc if we have validators
780+
if (context.validatorCount > 0) {
781+
if (allOf_.schemas)
782+
for (SizeType i = allOf_.begin; i < allOf_.begin + allOf_.count; i++)
783+
if (!context.validators[i]->IsValid()) {
784+
context.error_handler.NotAllOf(&context.validators[allOf_.begin], allOf_.count);
785+
RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAllOf);
786+
}
787+
788+
if (anyOf_.schemas) {
789+
for (SizeType i = anyOf_.begin; i < anyOf_.begin + anyOf_.count; i++)
790+
if (context.validators[i]->IsValid())
791+
goto foundAny;
792+
context.error_handler.NoneOf(&context.validators[anyOf_.begin], anyOf_.count);
793+
RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAnyOf);
794+
foundAny:;
795+
}
796+
797+
if (oneOf_.schemas) {
798+
bool oneValid = false;
799+
for (SizeType i = oneOf_.begin; i < oneOf_.begin + oneOf_.count; i++)
800+
if (context.validators[i]->IsValid()) {
801+
if (oneValid) {
802+
context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count, true);
803+
RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorOneOfMatch);
804+
} else
805+
oneValid = true;
806+
}
807+
if (!oneValid) {
808+
context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count, false);
809+
RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorOneOf);
803810
}
804-
if (!oneValid) {
805-
context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count, false);
806-
RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorOneOf);
807811
}
808-
}
809812

810-
if (not_ && context.validators[notValidatorIndex_]->IsValid()) {
811-
context.error_handler.Disallowed();
812-
RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorNot);
813+
if (not_ && context.validators[notValidatorIndex_]->IsValid()) {
814+
context.error_handler.Disallowed();
815+
RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorNot);
816+
}
813817
}
814818

815819
return true;

test/unittest/schematest.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2550,6 +2550,34 @@ TEST(SchemaValidator, ContinueOnErrors_RogueString) {
25502550
CrtAllocator::Free(schema);
25512551
}
25522552

2553+
// Test that when kValidateContinueOnErrorFlag is set, an incorrect simple type with a sub-schema is handled correctly.
2554+
// This tests that we don't blow up when there is a type mismatch but there is a sub-schema present
2555+
TEST(SchemaValidator, ContinueOnErrors_Issue2) {
2556+
Document sd;
2557+
sd.Parse("{\"type\":\"string\", \"anyOf\":[{\"maxLength\":2}]}");
2558+
ASSERT_FALSE(sd.HasParseError());
2559+
SchemaDocument s(sd);
2560+
VALIDATE(s, "\"AB\"", true);
2561+
INVALIDATE_(s, "\"ABC\"", "#", "errors", "#",
2562+
"{ \"anyOf\": {"
2563+
" \"errors\": [{"
2564+
" \"maxLength\": {"
2565+
" \"errorCode\": 6, \"instanceRef\": \"#\", \"schemaRef\": \"#/anyOf/0\", \"expected\": 2, \"actual\": \"ABC\""
2566+
" }"
2567+
" }],"
2568+
" \"errorCode\": 24, \"instanceRef\": \"#\", \"schemaRef\": \"#\""
2569+
" }"
2570+
"}",
2571+
kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidator, Pointer);
2572+
// Invalid type
2573+
INVALIDATE_(s, "333", "#", "errors", "#",
2574+
"{ \"type\": {"
2575+
" \"errorCode\": 20, \"instanceRef\": \"#\", \"schemaRef\": \"#\", \"expected\": [\"string\"], \"actual\": \"integer\""
2576+
" }"
2577+
"}",
2578+
kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidator, Pointer);
2579+
}
2580+
25532581
TEST(SchemaValidator, Schema_UnknownError) {
25542582
ASSERT_TRUE(SchemaValidator::SchemaType::GetValidateErrorKeyword(kValidateErrors).GetString() == std::string("null"));
25552583
}

0 commit comments

Comments
 (0)