mirror of
				https://github.com/Tencent/rapidjson.git
				synced 2025-11-04 12:17:41 +01:00 
			
		
		
		
	Merge pull request #609 from miloyip/issue608_required
Fix schema "required" keyword cannot handle duplicated keys
This commit is contained in:
		@@ -54,6 +54,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
 | 
				
			|||||||
* Fix memory leak for invalid regex (26e69ffde95ba4773ab06db6457b78f308716f4b)
 | 
					* Fix memory leak for invalid regex (26e69ffde95ba4773ab06db6457b78f308716f4b)
 | 
				
			||||||
* Fix a bug in schema minimum/maximum keywords for 64-bit integer (e7149d665941068ccf8c565e77495521331cf390)
 | 
					* Fix a bug in schema minimum/maximum keywords for 64-bit integer (e7149d665941068ccf8c565e77495521331cf390)
 | 
				
			||||||
* Fix a crash bug in regex (#605)
 | 
					* Fix a crash bug in regex (#605)
 | 
				
			||||||
 | 
					* Fix schema "required" keyword cannot handle duplicated keys (#609)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Changed
 | 
					### Changed
 | 
				
			||||||
* Clarify problematic JSON license (#392)
 | 
					* Clarify problematic JSON license (#392)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -289,7 +289,7 @@ struct SchemaValidationContext {
 | 
				
			|||||||
        patternPropertiesSchemas(),
 | 
					        patternPropertiesSchemas(),
 | 
				
			||||||
        patternPropertiesSchemaCount(),
 | 
					        patternPropertiesSchemaCount(),
 | 
				
			||||||
        valuePatternValidatorType(kPatternValidatorOnly),
 | 
					        valuePatternValidatorType(kPatternValidatorOnly),
 | 
				
			||||||
        objectDependencies(),
 | 
					        propertyExist(),
 | 
				
			||||||
        inArray(false),
 | 
					        inArray(false),
 | 
				
			||||||
        valueUniqueness(false),
 | 
					        valueUniqueness(false),
 | 
				
			||||||
        arrayUniqueness(false)
 | 
					        arrayUniqueness(false)
 | 
				
			||||||
@@ -311,8 +311,8 @@ struct SchemaValidationContext {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        if (patternPropertiesSchemas)
 | 
					        if (patternPropertiesSchemas)
 | 
				
			||||||
            factory.FreeState(patternPropertiesSchemas);
 | 
					            factory.FreeState(patternPropertiesSchemas);
 | 
				
			||||||
        if (objectDependencies)
 | 
					        if (propertyExist)
 | 
				
			||||||
            factory.FreeState(objectDependencies);
 | 
					            factory.FreeState(propertyExist);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    SchemaValidatorFactoryType& factory;
 | 
					    SchemaValidatorFactoryType& factory;
 | 
				
			||||||
@@ -329,9 +329,8 @@ struct SchemaValidationContext {
 | 
				
			|||||||
    SizeType patternPropertiesSchemaCount;
 | 
					    SizeType patternPropertiesSchemaCount;
 | 
				
			||||||
    PatternValidatorType valuePatternValidatorType;
 | 
					    PatternValidatorType valuePatternValidatorType;
 | 
				
			||||||
    PatternValidatorType objectPatternValidatorType;
 | 
					    PatternValidatorType objectPatternValidatorType;
 | 
				
			||||||
    SizeType objectRequiredCount;
 | 
					 | 
				
			||||||
    SizeType arrayElementIndex;
 | 
					    SizeType arrayElementIndex;
 | 
				
			||||||
    bool* objectDependencies;
 | 
					    bool* propertyExist;
 | 
				
			||||||
    bool inArray;
 | 
					    bool inArray;
 | 
				
			||||||
    bool valueUniqueness;
 | 
					    bool valueUniqueness;
 | 
				
			||||||
    bool arrayUniqueness;
 | 
					    bool arrayUniqueness;
 | 
				
			||||||
@@ -365,11 +364,11 @@ public:
 | 
				
			|||||||
        patternProperties_(),
 | 
					        patternProperties_(),
 | 
				
			||||||
        patternPropertyCount_(),
 | 
					        patternPropertyCount_(),
 | 
				
			||||||
        propertyCount_(),
 | 
					        propertyCount_(),
 | 
				
			||||||
        requiredCount_(),
 | 
					 | 
				
			||||||
        minProperties_(),
 | 
					        minProperties_(),
 | 
				
			||||||
        maxProperties_(SizeType(~0)),
 | 
					        maxProperties_(SizeType(~0)),
 | 
				
			||||||
        additionalProperties_(true),
 | 
					        additionalProperties_(true),
 | 
				
			||||||
        hasDependencies_(),
 | 
					        hasDependencies_(),
 | 
				
			||||||
 | 
					        hasRequired_(),
 | 
				
			||||||
        hasSchemaDependencies_(),
 | 
					        hasSchemaDependencies_(),
 | 
				
			||||||
        additionalItemsSchema_(),
 | 
					        additionalItemsSchema_(),
 | 
				
			||||||
        itemsList_(),
 | 
					        itemsList_(),
 | 
				
			||||||
@@ -490,7 +489,7 @@ public:
 | 
				
			|||||||
                    SizeType index;
 | 
					                    SizeType index;
 | 
				
			||||||
                    if (FindPropertyIndex(*itr, &index)) {
 | 
					                    if (FindPropertyIndex(*itr, &index)) {
 | 
				
			||||||
                        properties_[index].required = true;
 | 
					                        properties_[index].required = true;
 | 
				
			||||||
                        requiredCount_++;
 | 
					                        hasRequired_ = true;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -767,10 +766,9 @@ public:
 | 
				
			|||||||
        if (!(type_ & (1 << kObjectSchemaType)))
 | 
					        if (!(type_ & (1 << kObjectSchemaType)))
 | 
				
			||||||
            RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
 | 
					            RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        context.objectRequiredCount = 0;
 | 
					        if (hasDependencies_ || hasRequired_) {
 | 
				
			||||||
        if (hasDependencies_) {
 | 
					            context.propertyExist = static_cast<bool*>(context.factory.MallocState(sizeof(bool) * propertyCount_));
 | 
				
			||||||
            context.objectDependencies = static_cast<bool*>(context.factory.MallocState(sizeof(bool) * propertyCount_));
 | 
					            std::memset(context.propertyExist, 0, sizeof(bool) * propertyCount_);
 | 
				
			||||||
            std::memset(context.objectDependencies, 0, sizeof(bool) * propertyCount_);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (patternProperties_) { // pre-allocate schema array
 | 
					        if (patternProperties_) { // pre-allocate schema array
 | 
				
			||||||
@@ -801,11 +799,8 @@ public:
 | 
				
			|||||||
            else
 | 
					            else
 | 
				
			||||||
                context.valueSchema = properties_[index].schema;
 | 
					                context.valueSchema = properties_[index].schema;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (properties_[index].required)
 | 
					            if (context.propertyExist)
 | 
				
			||||||
                context.objectRequiredCount++;
 | 
					                context.propertyExist[index] = true;
 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (hasDependencies_)
 | 
					 | 
				
			||||||
                context.objectDependencies[index] = true;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -832,8 +827,11 @@ public:
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool EndObject(Context& context, SizeType memberCount) const {
 | 
					    bool EndObject(Context& context, SizeType memberCount) const {
 | 
				
			||||||
        if (context.objectRequiredCount != requiredCount_)
 | 
					        if (hasRequired_)
 | 
				
			||||||
            RAPIDJSON_INVALID_KEYWORD_RETURN(GetRequiredString());
 | 
					            for (SizeType index = 0; index < propertyCount_; index++)
 | 
				
			||||||
 | 
					                if (properties_[index].required)
 | 
				
			||||||
 | 
					                    if (!context.propertyExist[index])
 | 
				
			||||||
 | 
					                        RAPIDJSON_INVALID_KEYWORD_RETURN(GetRequiredString());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (memberCount < minProperties_)
 | 
					        if (memberCount < minProperties_)
 | 
				
			||||||
            RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinPropertiesString());
 | 
					            RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinPropertiesString());
 | 
				
			||||||
@@ -843,10 +841,10 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if (hasDependencies_) {
 | 
					        if (hasDependencies_) {
 | 
				
			||||||
            for (SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++)
 | 
					            for (SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++)
 | 
				
			||||||
                if (context.objectDependencies[sourceIndex]) {
 | 
					                if (context.propertyExist[sourceIndex]) {
 | 
				
			||||||
                    if (properties_[sourceIndex].dependencies) {
 | 
					                    if (properties_[sourceIndex].dependencies) {
 | 
				
			||||||
                        for (SizeType targetIndex = 0; targetIndex < propertyCount_; targetIndex++)
 | 
					                        for (SizeType targetIndex = 0; targetIndex < propertyCount_; targetIndex++)
 | 
				
			||||||
                            if (properties_[sourceIndex].dependencies[targetIndex] && !context.objectDependencies[targetIndex])
 | 
					                            if (properties_[sourceIndex].dependencies[targetIndex] && !context.propertyExist[targetIndex])
 | 
				
			||||||
                                RAPIDJSON_INVALID_KEYWORD_RETURN(GetDependenciesString());
 | 
					                                RAPIDJSON_INVALID_KEYWORD_RETURN(GetDependenciesString());
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    else if (properties_[sourceIndex].dependenciesSchema)
 | 
					                    else if (properties_[sourceIndex].dependenciesSchema)
 | 
				
			||||||
@@ -1236,11 +1234,11 @@ private:
 | 
				
			|||||||
    PatternProperty* patternProperties_;
 | 
					    PatternProperty* patternProperties_;
 | 
				
			||||||
    SizeType patternPropertyCount_;
 | 
					    SizeType patternPropertyCount_;
 | 
				
			||||||
    SizeType propertyCount_;
 | 
					    SizeType propertyCount_;
 | 
				
			||||||
    SizeType requiredCount_;
 | 
					 | 
				
			||||||
    SizeType minProperties_;
 | 
					    SizeType minProperties_;
 | 
				
			||||||
    SizeType maxProperties_;
 | 
					    SizeType maxProperties_;
 | 
				
			||||||
    bool additionalProperties_;
 | 
					    bool additionalProperties_;
 | 
				
			||||||
    bool hasDependencies_;
 | 
					    bool hasDependencies_;
 | 
				
			||||||
 | 
					    bool hasRequired_;
 | 
				
			||||||
    bool hasSchemaDependencies_;
 | 
					    bool hasSchemaDependencies_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const SchemaType* additionalItemsSchema_;
 | 
					    const SchemaType* additionalItemsSchema_;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1299,6 +1299,15 @@ TEST(Schema, Issue552) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
 | 
					#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(SchemaValidator, Issue608) {
 | 
				
			||||||
 | 
					    Document sd;
 | 
				
			||||||
 | 
					    sd.Parse("{\"required\": [\"a\", \"b\"] }");
 | 
				
			||||||
 | 
					    SchemaDocument s(sd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    VALIDATE(s, "{\"a\" : null, \"b\": null}", true);
 | 
				
			||||||
 | 
					    INVALIDATE(s, "{\"a\" : null, \"a\" : null}", "", "required", "");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __clang__
 | 
					#ifdef __clang__
 | 
				
			||||||
RAPIDJSON_DIAG_POP
 | 
					RAPIDJSON_DIAG_POP
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user