Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8df840aa authored by Mathias Agopian's avatar Mathias Agopian Committed by Android (Google) Code Review
Browse files

Merge "strengthen region validation" into jb-mr1-dev

parents e45b01f5 068d47f2
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -26,10 +26,10 @@ namespace android {
template<typename RECT>
class region_operator
{
public:
    typedef typename RECT::value_type TYPE;    
    static const TYPE max_value = 0x7FFFFFF;

public:
    /* 
     * Common boolean operations:
     * value is computed as 0b101 op 0b110
+2 −1
Original line number Diff line number Diff line
@@ -161,7 +161,8 @@ private:
    static void translate(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
    // with an extra Rect as the last element which is set to the
+59 −23
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@

#include <utils/Log.h>
#include <utils/String8.h>
#include <utils/CallStack.h>

#include <ui/Rect.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;
    const_iterator cur = reg.begin();
    const_iterator const tail = reg.end();
    const_iterator prev = cur++;
    const_iterator prev = cur;
    Rect b(*prev);
    while (cur != tail) {
        if (cur->isValid() == false) {
            ALOGE_IF(!silent, "%s: region contains an invalid Rect", name);
            result = false;
        }
        if (cur->right > region_operator<Rect>::max_value) {
            ALOGE_IF(!silent, "%s: rect->right > max_value", name);
            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;
            }
            if (cur->top == prev->top) {
                if (cur->bottom != prev->bottom) {
                ALOGE("%s: invalid span %p", name, cur);
                    ALOGE_IF(!silent, "%s: invalid span %p", name, cur);
                    result = false;
                } else if (cur->left < prev->right) {
                ALOGE("%s: spans overlap horizontally prev=%p, cur=%p",
                    ALOGE_IF(!silent,
                            "%s: spans overlap horizontally prev=%p, cur=%p",
                            name, prev, cur);
                    result = false;
                }
            } else if (cur->top < prev->bottom) {
            ALOGE("%s: spans overlap vertically prev=%p, cur=%p",
                ALOGE_IF(!silent,
                        "%s: spans overlap vertically prev=%p, cur=%p",
                        name, prev, cur);
                result = false;
            }
            prev = cur;
        }
        cur++;
    }
    if (b != reg.getBounds()) {
        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,
                reg.getBounds().left, reg.getBounds().top, 
                reg.getBounds().right, reg.getBounds().bottom);
    }
    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);
        CallStack stack;
        stack.update();
        stack.dump("");
    }
    return result;
}
@@ -564,27 +590,37 @@ size_t Region::getSize() const {
}

status_t Region::flatten(void* buffer) const {
#if VALIDATE_REGIONS
    validate(*this, "Region::flatten");
#endif
    Rect* rects = reinterpret_cast<Rect*>(buffer);
    memcpy(rects, mStorage.array(), mStorage.size() * sizeof(Rect));
    return NO_ERROR;
}

status_t Region::unflatten(void const* buffer, size_t size) {
    mStorage.clear();
    Region result;
    if (size >= sizeof(Rect)) {
        Rect const* rects = reinterpret_cast<Rect const*>(buffer);
        size_t count = size / sizeof(Rect);
        if (count > 0) {
            ssize_t err = mStorage.insertAt(0, count);
            result.mStorage.clear();
            ssize_t err = result.mStorage.insertAt(0, count);
            if (err < 0) {
                return status_t(err);
            }
            memcpy(mStorage.editArray(), rects, count*sizeof(Rect));
            memcpy(result.mStorage.editArray(), rects, count*sizeof(Rect));
        }
    }
#if VALIDATE_REGIONS
    validate(*this, "Region::unflatten");
    validate(result, "Region::unflatten");
#endif

    if (!result.validate(result, "Region::unflatten", true)) {
        ALOGE("Region::unflatten() failed, invalid region");
        return BAD_VALUE;
    }
    mStorage = result.mStorage;
    return NO_ERROR;
}