Merge pull request #1844 from smhdfdl/multiple-validation-failures-and-validation-messages

After PR 1837, fix crash where simple type with sub-schema has a bad value
diff --git a/include/rapidjson/schema.h b/include/rapidjson/schema.h
index 11f7160..6576c25 100644
--- a/include/rapidjson/schema.h
+++ b/include/rapidjson/schema.h
@@ -733,6 +733,7 @@
     }
 
     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 @@
             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;
diff --git a/test/unittest/schematest.cpp b/test/unittest/schematest.cpp
index ad19cd9..f381b4e 100644
--- a/test/unittest/schematest.cpp
+++ b/test/unittest/schematest.cpp
@@ -2550,6 +2550,34 @@
     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"));
 }