strengthen region validation
Change-Id: I75ee7bc4dd7a2f5357ac8994a23bc8b8bfb6eb44
This commit is contained in:
parent
2c7c8ba56a
commit
068d47f29d
|
@ -26,10 +26,10 @@ namespace android {
|
||||||
template<typename RECT>
|
template<typename RECT>
|
||||||
class region_operator
|
class region_operator
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
typedef typename RECT::value_type TYPE;
|
typedef typename RECT::value_type TYPE;
|
||||||
static const TYPE max_value = 0x7FFFFFF;
|
static const TYPE max_value = 0x7FFFFFF;
|
||||||
|
|
||||||
public:
|
|
||||||
/*
|
/*
|
||||||
* Common boolean operations:
|
* Common boolean operations:
|
||||||
* value is computed as 0b101 op 0b110
|
* value is computed as 0b101 op 0b110
|
||||||
|
|
|
@ -161,7 +161,8 @@ private:
|
||||||
static void translate(Region& reg, int dx, int dy);
|
static void translate(Region& reg, int dx, int dy);
|
||||||
static void translate(Region& dst, const Region& reg, int dx, int dy);
|
static void translate(Region& dst, const Region& reg, int dx, int dy);
|
||||||
|
|
||||||
static bool validate(const Region& reg, const char* name);
|
static bool validate(const Region& reg,
|
||||||
|
const char* name, bool silent = false);
|
||||||
|
|
||||||
// mStorage is a (manually) sorted array of Rects describing the region
|
// mStorage is a (manually) sorted array of Rects describing the region
|
||||||
// with an extra Rect as the last element which is set to the
|
// with an extra Rect as the last element which is set to the
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include <utils/Log.h>
|
#include <utils/Log.h>
|
||||||
#include <utils/String8.h>
|
#include <utils/String8.h>
|
||||||
|
#include <utils/CallStack.h>
|
||||||
|
|
||||||
#include <ui/Rect.h>
|
#include <ui/Rect.h>
|
||||||
#include <ui/Region.h>
|
#include <ui/Region.h>
|
||||||
|
@ -338,47 +339,72 @@ private:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
bool Region::validate(const Region& reg, const char* name)
|
bool Region::validate(const Region& reg, const char* name, bool silent)
|
||||||
{
|
{
|
||||||
bool result = true;
|
bool result = true;
|
||||||
const_iterator cur = reg.begin();
|
const_iterator cur = reg.begin();
|
||||||
const_iterator const tail = reg.end();
|
const_iterator const tail = reg.end();
|
||||||
const_iterator prev = cur++;
|
const_iterator prev = cur;
|
||||||
Rect b(*prev);
|
Rect b(*prev);
|
||||||
while (cur != tail) {
|
while (cur != tail) {
|
||||||
b.left = b.left < cur->left ? b.left : cur->left;
|
if (cur->isValid() == false) {
|
||||||
b.top = b.top < cur->top ? b.top : cur->top;
|
ALOGE_IF(!silent, "%s: region contains an invalid Rect", name);
|
||||||
b.right = b.right > cur->right ? b.right : cur->right;
|
result = false;
|
||||||
b.bottom = b.bottom > cur->bottom ? b.bottom : cur->bottom;
|
}
|
||||||
if (cur->top == prev->top) {
|
if (cur->right > region_operator<Rect>::max_value) {
|
||||||
if (cur->bottom != prev->bottom) {
|
ALOGE_IF(!silent, "%s: rect->right > max_value", name);
|
||||||
ALOGE("%s: invalid span %p", name, cur);
|
result = false;
|
||||||
|
}
|
||||||
|
if (cur->bottom > region_operator<Rect>::max_value) {
|
||||||
|
ALOGE_IF(!silent, "%s: rect->right > max_value", name);
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
if (prev != cur) {
|
||||||
|
b.left = b.left < cur->left ? b.left : cur->left;
|
||||||
|
b.top = b.top < cur->top ? b.top : cur->top;
|
||||||
|
b.right = b.right > cur->right ? b.right : cur->right;
|
||||||
|
b.bottom = b.bottom > cur->bottom ? b.bottom : cur->bottom;
|
||||||
|
if ((*prev < *cur) == false) {
|
||||||
|
ALOGE_IF(!silent, "%s: region's Rects not sorted", name);
|
||||||
result = false;
|
result = false;
|
||||||
} else if (cur->left < prev->right) {
|
}
|
||||||
ALOGE("%s: spans overlap horizontally prev=%p, cur=%p",
|
if (cur->top == prev->top) {
|
||||||
|
if (cur->bottom != prev->bottom) {
|
||||||
|
ALOGE_IF(!silent, "%s: invalid span %p", name, cur);
|
||||||
|
result = false;
|
||||||
|
} else if (cur->left < prev->right) {
|
||||||
|
ALOGE_IF(!silent,
|
||||||
|
"%s: spans overlap horizontally prev=%p, cur=%p",
|
||||||
|
name, prev, cur);
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
} else if (cur->top < prev->bottom) {
|
||||||
|
ALOGE_IF(!silent,
|
||||||
|
"%s: spans overlap vertically prev=%p, cur=%p",
|
||||||
name, prev, cur);
|
name, prev, cur);
|
||||||
result = false;
|
result = false;
|
||||||
}
|
}
|
||||||
} else if (cur->top < prev->bottom) {
|
prev = cur;
|
||||||
ALOGE("%s: spans overlap vertically prev=%p, cur=%p",
|
|
||||||
name, prev, cur);
|
|
||||||
result = false;
|
|
||||||
}
|
}
|
||||||
prev = cur;
|
|
||||||
cur++;
|
cur++;
|
||||||
}
|
}
|
||||||
if (b != reg.getBounds()) {
|
if (b != reg.getBounds()) {
|
||||||
result = false;
|
result = false;
|
||||||
ALOGE("%s: invalid bounds [%d,%d,%d,%d] vs. [%d,%d,%d,%d]", name,
|
ALOGE_IF(!silent,
|
||||||
|
"%s: invalid bounds [%d,%d,%d,%d] vs. [%d,%d,%d,%d]", name,
|
||||||
b.left, b.top, b.right, b.bottom,
|
b.left, b.top, b.right, b.bottom,
|
||||||
reg.getBounds().left, reg.getBounds().top,
|
reg.getBounds().left, reg.getBounds().top,
|
||||||
reg.getBounds().right, reg.getBounds().bottom);
|
reg.getBounds().right, reg.getBounds().bottom);
|
||||||
}
|
}
|
||||||
if (reg.mStorage.size() == 2) {
|
if (reg.mStorage.size() == 2) {
|
||||||
ALOGE("mStorage size is 2, which is never valid");
|
result = false;
|
||||||
|
ALOGE_IF(!silent, "%s: mStorage size is 2, which is never valid", name);
|
||||||
}
|
}
|
||||||
if (result == false) {
|
if (result == false && !silent) {
|
||||||
reg.dump(name);
|
reg.dump(name);
|
||||||
|
CallStack stack;
|
||||||
|
stack.update();
|
||||||
|
stack.dump("");
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -564,27 +590,37 @@ size_t Region::getSize() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t Region::flatten(void* buffer) const {
|
status_t Region::flatten(void* buffer) const {
|
||||||
|
#if VALIDATE_REGIONS
|
||||||
|
validate(*this, "Region::flatten");
|
||||||
|
#endif
|
||||||
Rect* rects = reinterpret_cast<Rect*>(buffer);
|
Rect* rects = reinterpret_cast<Rect*>(buffer);
|
||||||
memcpy(rects, mStorage.array(), mStorage.size() * sizeof(Rect));
|
memcpy(rects, mStorage.array(), mStorage.size() * sizeof(Rect));
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t Region::unflatten(void const* buffer, size_t size) {
|
status_t Region::unflatten(void const* buffer, size_t size) {
|
||||||
mStorage.clear();
|
Region result;
|
||||||
if (size >= sizeof(Rect)) {
|
if (size >= sizeof(Rect)) {
|
||||||
Rect const* rects = reinterpret_cast<Rect const*>(buffer);
|
Rect const* rects = reinterpret_cast<Rect const*>(buffer);
|
||||||
size_t count = size / sizeof(Rect);
|
size_t count = size / sizeof(Rect);
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
ssize_t err = mStorage.insertAt(0, count);
|
result.mStorage.clear();
|
||||||
|
ssize_t err = result.mStorage.insertAt(0, count);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
return status_t(err);
|
return status_t(err);
|
||||||
}
|
}
|
||||||
memcpy(mStorage.editArray(), rects, count*sizeof(Rect));
|
memcpy(result.mStorage.editArray(), rects, count*sizeof(Rect));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if VALIDATE_REGIONS
|
#if VALIDATE_REGIONS
|
||||||
validate(*this, "Region::unflatten");
|
validate(result, "Region::unflatten");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (!result.validate(result, "Region::unflatten", true)) {
|
||||||
|
ALOGE("Region::unflatten() failed, invalid region");
|
||||||
|
return BAD_VALUE;
|
||||||
|
}
|
||||||
|
mStorage = result.mStorage;
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue