summaryrefslogtreecommitdiff
path: root/tools/aapt2/ResourceValues.cpp
diff options
context:
space:
mode:
authorAdam Lesinski <adamlesinski@google.com>2015-11-20 15:32:30 -0800
committerAdam Lesinski <adamlesinski@google.com>2015-11-23 12:01:15 -0800
commita587065721053ad54e34f484868142407d59512d (patch)
tree57efbb55d03b5e68610802da8e469d5d48a29078 /tools/aapt2/ResourceValues.cpp
parent78de1bcbbdad03d893d0b1df5372732cf6d0d934 (diff)
AAPT2: Verify min/max attr fields
Integers are now checked to see if they fall in the range of min/max for the attribute they are assigned. Change-Id: I42c435b15fd3f0bd23691c83efccce4ad5973276
Diffstat (limited to 'tools/aapt2/ResourceValues.cpp')
-rw-r--r--tools/aapt2/ResourceValues.cpp84
1 files changed, 81 insertions, 3 deletions
diff --git a/tools/aapt2/ResourceValues.cpp b/tools/aapt2/ResourceValues.cpp
index 5550f192d51a..04c375f5f974 100644
--- a/tools/aapt2/ResourceValues.cpp
+++ b/tools/aapt2/ResourceValues.cpp
@@ -15,9 +15,9 @@
*/
#include "Resource.h"
+#include "ResourceUtils.h"
#include "ResourceValues.h"
#include "ValueVisitor.h"
-
#include "util/Util.h"
#include "flatten/ResourceTypeExtensions.h"
@@ -216,7 +216,7 @@ void BinaryPrimitive::print(std::ostream* out) const {
*out << "(null)";
break;
case android::Res_value::TYPE_INT_DEC:
- *out << "(integer) " << value.data;
+ *out << "(integer) " << static_cast<int32_t>(value.data);
break;
case android::Res_value::TYPE_INT_HEX:
*out << "(integer) " << std::hex << value.data << std::dec;
@@ -237,7 +237,10 @@ void BinaryPrimitive::print(std::ostream* out) const {
}
}
-Attribute::Attribute(bool w, uint32_t t) : weak(w), typeMask(t) {
+Attribute::Attribute(bool w, uint32_t t) :
+ weak(w), typeMask(t),
+ minInt(std::numeric_limits<int32_t>::min()),
+ maxInt(std::numeric_limits<int32_t>::max()) {
}
bool Attribute::isWeak() const {
@@ -361,6 +364,81 @@ void Attribute::print(std::ostream* out) const {
}
}
+static void buildAttributeMismatchMessage(DiagMessage* msg, const Attribute* attr,
+ const Item* value) {
+ *msg << "expected";
+ if (attr->typeMask & android::ResTable_map::TYPE_BOOLEAN) {
+ *msg << " boolean";
+ }
+
+ if (attr->typeMask & android::ResTable_map::TYPE_COLOR) {
+ *msg << " color";
+ }
+
+ if (attr->typeMask & android::ResTable_map::TYPE_DIMENSION) {
+ *msg << " dimension";
+ }
+
+ if (attr->typeMask & android::ResTable_map::TYPE_ENUM) {
+ *msg << " enum";
+ }
+
+ if (attr->typeMask & android::ResTable_map::TYPE_FLAGS) {
+ *msg << " flags";
+ }
+
+ if (attr->typeMask & android::ResTable_map::TYPE_FLOAT) {
+ *msg << " float";
+ }
+
+ if (attr->typeMask & android::ResTable_map::TYPE_FRACTION) {
+ *msg << " fraction";
+ }
+
+ if (attr->typeMask & android::ResTable_map::TYPE_INTEGER) {
+ *msg << " integer";
+ }
+
+ if (attr->typeMask & android::ResTable_map::TYPE_REFERENCE) {
+ *msg << " reference";
+ }
+
+ if (attr->typeMask & android::ResTable_map::TYPE_STRING) {
+ *msg << " string";
+ }
+
+ *msg << " but got " << *value;
+}
+
+bool Attribute::matches(const Item* item, DiagMessage* outMsg) const {
+ android::Res_value val = {};
+ item->flatten(&val);
+
+ // Always allow references.
+ const uint32_t mask = typeMask | android::ResTable_map::TYPE_REFERENCE;
+ if (!(mask & ResourceUtils::androidTypeToAttributeTypeMask(val.dataType))) {
+ if (outMsg) {
+ buildAttributeMismatchMessage(outMsg, this, item);
+ }
+ return false;
+
+ } else if (ResourceUtils::androidTypeToAttributeTypeMask(val.dataType) &
+ android::ResTable_map::TYPE_INTEGER) {
+ if (static_cast<int32_t>(util::deviceToHost32(val.data)) < minInt) {
+ if (outMsg) {
+ *outMsg << *item << " is less than minimum integer " << minInt;
+ }
+ return false;
+ } else if (static_cast<int32_t>(util::deviceToHost32(val.data)) > maxInt) {
+ if (outMsg) {
+ *outMsg << *item << " is greater than maximum integer " << maxInt;
+ }
+ return false;
+ }
+ }
+ return true;
+}
+
Style* Style::clone(StringPool* newPool) const {
Style* style = new Style();
style->parent = parent;