Merge pull request #609 from miloyip/issue608_required
Fix schema "required" keyword cannot handle duplicated keys
This commit is contained in:
commit
8821797f01
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user