libweave: Validate constraints in FromJson methods
Also fixed public TypedValueBase::SetValue method that allows to create
invalid values.
BUG=brillo:1246
TEST='FEATURES=test emerge-gizmo buffet'
Change-Id: Ia60354c3daf2f150fe3e8d1781d0f37420e03563
Reviewed-on: https://chromium-review.googlesource.com/289641
Trybot-Ready: Vitaly Buka <vitalybuka@chromium.org>
Tested-by: Vitaly Buka <vitalybuka@chromium.org>
Reviewed-by: Alex Vakulenko <avakulenko@chromium.org>
Commit-Queue: Vitaly Buka <vitalybuka@chromium.org>
diff --git a/libweave/src/commands/prop_types.cc b/libweave/src/commands/prop_types.cc
index ffec8f4..a5db4cb 100644
--- a/libweave/src/commands/prop_types.cc
+++ b/libweave/src/commands/prop_types.cc
@@ -187,8 +187,7 @@
const base::Value* defval = nullptr; // Owned by value
if (value->GetWithoutPathExpansion(commands::attributes::kDefault, &defval)) {
std::unique_ptr<PropValue> prop_value = CreateValue();
- if (!prop_value->FromJson(defval, error) ||
- !ValidateValue(prop_value->GetValueAsAny(), error)) {
+ if (!prop_value->FromJson(defval, error)) {
chromeos::Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
errors::commands::kInvalidPropValue,
"Invalid value for property '%s'",
@@ -237,7 +236,7 @@
chromeos::ErrorPtr* error) const {
std::unique_ptr<PropValue> val = CreateValue();
CHECK(val) << "Failed to create value object";
- return val->FromJson(value, error) && ValidateConstraints(*val, error);
+ return val->FromJson(value, error);
}
bool PropType::ValidateValue(const chromeos::Any& value,
diff --git a/libweave/src/commands/prop_types.h b/libweave/src/commands/prop_types.h
index eb605a7..6b364f3 100644
--- a/libweave/src/commands/prop_types.h
+++ b/libweave/src/commands/prop_types.h
@@ -225,16 +225,14 @@
std::unique_ptr<PropValue> CreateValue(
const chromeos::Any& v,
chromeos::ErrorPtr* error) const override {
- std::unique_ptr<PropValue> prop_value;
- if (v.IsTypeCompatible<T>()) {
- std::unique_ptr<Value> value{new Value{Clone()}};
- value->SetValue(v.Get<T>());
- if (ValidateConstraints(*value, error))
- prop_value = std::move(value);
- } else {
+ if (!v.IsTypeCompatible<T>()) {
GenerateErrorValueTypeMismatch(error);
+ return nullptr;
}
- return prop_value;
+ std::unique_ptr<Value> value{new Value{Clone()}};
+ if (!value->SetValue(v.Get<T>(), error))
+ return nullptr;
+ return std::move(value);
}
chromeos::Any ConvertArrayToDBusVariant(
diff --git a/libweave/src/commands/prop_values.h b/libweave/src/commands/prop_values.h
index d0b2dc7..fa9963a 100644
--- a/libweave/src/commands/prop_values.h
+++ b/libweave/src/commands/prop_values.h
@@ -156,7 +156,10 @@
}
bool FromJson(const base::Value* value, chromeos::ErrorPtr* error) override {
- return TypedValueFromJson(value, GetPropType(), &value_, error);
+ T tmp_value;
+ if (!TypedValueFromJson(value, GetPropType(), &tmp_value, error))
+ return false;
+ return SetValue(tmp_value, error);
}
bool IsEqual(const PropValue* value) const override {
@@ -169,7 +172,13 @@
// Helper methods to get and set the C++ representation of the value.
chromeos::Any GetValueAsAny() const override { return value_; }
const T& GetValue() const { return value_; }
- void SetValue(T value) { value_ = std::move(value); }
+ bool SetValue(T value, chromeos::ErrorPtr* error) {
+ std::swap(value_, value); // Backup.
+ if (GetPropType()->ValidateConstraints(*this, error))
+ return true;
+ std::swap(value_, value); // Restore.
+ return false;
+ }
protected:
T value_{}; // The value of the parameter in C++ data representation.
diff --git a/libweave/src/commands/schema_utils.cc b/libweave/src/commands/schema_utils.cc
index 04b8bcb..034eca9 100644
--- a/libweave/src/commands/schema_utils.cc
+++ b/libweave/src/commands/schema_utils.cc
@@ -147,8 +147,7 @@
const base::Value* param_value = nullptr;
CHECK(dict->GetWithoutPathExpansion(pair.first, ¶m_value))
<< "Unable to get parameter";
- if (!value->FromJson(param_value, error) ||
- !pair.second->ValidateValue(value->GetValueAsAny(), error)) {
+ if (!value->FromJson(param_value, error)) {
chromeos::Error::AddToPrintf(
error, FROM_HERE, errors::commands::kDomain,
errors::commands::kInvalidPropValue,
@@ -215,8 +214,7 @@
value_out->reserve(list->GetSize());
for (const base::Value* item : *list) {
std::unique_ptr<PropValue> prop_value = item_type->CreateValue();
- if (!prop_value->FromJson(item, error) ||
- !item_type->ValidateValue(prop_value->GetValueAsAny(), error)) {
+ if (!prop_value->FromJson(item, error)) {
return false;
}
value_out->push_back(std::move(prop_value));
diff --git a/libweave/src/commands/schema_utils.h b/libweave/src/commands/schema_utils.h
index ea1639f..f00a89f 100644
--- a/libweave/src/commands/schema_utils.h
+++ b/libweave/src/commands/schema_utils.h
@@ -75,6 +75,9 @@
// Similarly to TypedValueToJson() function above, the following overloaded
// helper methods allow to extract specific C++ data types from base::Value.
// Also used in template classes below to simplify specialization logic.
+// TODO(vitalybuka): Fix this. Interface is misleading. Seeing PropType internal
+// type validation is expected. In reality only ValueMap and ValueVector do
+// validation.
bool TypedValueFromJson(const base::Value* value_in,
const PropType* type,
bool* value_out,
diff --git a/libweave/src/commands/unittest_utils.h b/libweave/src/commands/unittest_utils.h
index 345e92d..d0d39ee 100644
--- a/libweave/src/commands/unittest_utils.h
+++ b/libweave/src/commands/unittest_utils.h
@@ -34,7 +34,8 @@
std::unique_ptr<const PropVal> make_prop_value(const T& value) {
std::unique_ptr<PropVal> result{
new PropVal{PropType::Create(GetValueType<T>())}};
- result->SetValue(value);
+ if (!result->SetValue(value, nullptr))
+ return nullptr;
return std::move(result);
}