Commit 8821797f authored by Milo Yip's avatar Milo Yip

Merge pull request #609 from miloyip/issue608_required

Fix schema "required" keyword cannot handle duplicated keys
parents 07343d5e bbcdb8b5
...@@ -54,6 +54,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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,7 +827,10 @@ public: ...@@ -832,7 +827,10 @@ public:
} }
bool EndObject(Context& context, SizeType memberCount) const { bool EndObject(Context& context, SizeType memberCount) const {
if (context.objectRequiredCount != requiredCount_) if (hasRequired_)
for (SizeType index = 0; index < propertyCount_; index++)
if (properties_[index].required)
if (!context.propertyExist[index])
RAPIDJSON_INVALID_KEYWORD_RETURN(GetRequiredString()); RAPIDJSON_INVALID_KEYWORD_RETURN(GetRequiredString());
if (memberCount < minProperties_) if (memberCount < minProperties_)
...@@ -843,10 +841,10 @@ public: ...@@ -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: ...@@ -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) { ...@@ -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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment