diff options
author | Adam Lesinski <adamlesinski@google.com> | 2015-11-20 15:32:30 -0800 |
---|---|---|
committer | Adam Lesinski <adamlesinski@google.com> | 2015-11-23 12:01:15 -0800 |
commit | a587065721053ad54e34f484868142407d59512d (patch) | |
tree | 57efbb55d03b5e68610802da8e469d5d48a29078 /tools/aapt2/ResourceValues.cpp | |
parent | 78de1bcbbdad03d893d0b1df5372732cf6d0d934 (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.cpp | 84 |
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; |