Commit message: None
CVE: CVE-2015-3849
CWE: CWE-264
Vulnerability description: The Region_createFromParcel function in core/jni/android/graphics/Region.cpp in Region in Android before 5.1.1 LMY48M does not check the return values of certain read operations, which allows attackers to execute arbitrary code via an application that sends a crafted message to a service, aka internal bug 21585255.

Project: Android

static inline SkRegion* GetSkRegion(JNIEnv* env, jobject regionObject) {
    jlong regionHandle = env->GetLongField(regionObject, gRegion_nativeInstanceFieldID);
 SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle);
 SkASSERT(region != NULL);
 return region;
}

Project: Android

static jlong RegionIter_constructor(JNIEnv* env, jobject, jlong regionHandle)
{
 const SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle);
 SkASSERT(region);
 return reinterpret_cast<jlong>(new RgnIterPair(*region));
}

Project: Android

static void RegionIter_destructor(JNIEnv* env, jobject, jlong pairHandle)
{
 RgnIterPair* pair = reinterpret_cast<RgnIterPair*>(pairHandle);
 SkASSERT(pair);
 delete pair;
}

Project: Android

static jlong Region_constructor(JNIEnv* env, jobject) {
 return reinterpret_cast<jlong>(new SkRegion);
}

Project: Android

static jboolean Region_contains(JNIEnv* env, jobject region, jint x, jint y) {
 bool result = GetSkRegion(env, region)->contains(x, y);
 return boolTojboolean(result);
}

Project: Android

static void Region_destructor(JNIEnv* env, jobject, jlong regionHandle) {
 SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle);
 SkASSERT(region);
 delete region;
}

Project: Android

static jboolean Region_equals(JNIEnv* env, jobject clazz, jlong r1Handle, jlong r2Handle)
{
 const SkRegion *r1 = reinterpret_cast<SkRegion*>(r1Handle);
 const SkRegion *r2 = reinterpret_cast<SkRegion*>(r2Handle);
 return boolTojboolean(*r1 == *r2);
}

Project: Android

static jboolean Region_getBoundaryPath(JNIEnv* env, jobject, jlong regionHandle, jlong pathHandle) {
 const SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle);
 SkPath*   path = reinterpret_cast<SkPath*>(pathHandle);
 bool result = region->getBoundaryPath(path);
 return boolTojboolean(result);
}

Project: Android

static jboolean Region_getBounds(JNIEnv* env, jobject, jlong regionHandle, jobject rectBounds) {
 SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle);
 GraphicsJNI::irect_to_jrect(region->getBounds(), env, rectBounds);
 bool result = !region->isEmpty();
 return boolTojboolean(result);
}

Project: Android

static jboolean Region_isComplex(JNIEnv* env, jobject region) {
 bool result = GetSkRegion(env, region)->isComplex();
 return boolTojboolean(result);
}

Project: Android

static jboolean Region_isEmpty(JNIEnv* env, jobject region) {
 bool result = GetSkRegion(env, region)->isEmpty();
 return boolTojboolean(result);
}

Project: Android

static jboolean Region_isRect(JNIEnv* env, jobject region) {
 bool result = GetSkRegion(env, region)->isRect();
 return boolTojboolean(result);
}

Project: Android

static jboolean Region_op0(JNIEnv* env, jobject, jlong dstHandle, jint left, jint top, jint right, jint bottom, jint op) {
 SkRegion* dst = reinterpret_cast<SkRegion*>(dstHandle);
 SkIRect ir;

    ir.set(left, top, right, bottom);
 bool result = dst->op(ir, (SkRegion::Op)op);
 return boolTojboolean(result);
}

Project: Android

static jboolean Region_op1(JNIEnv* env, jobject, jlong dstHandle, jobject rectObject, jlong regionHandle, jint op) {
 SkRegion* dst = reinterpret_cast<SkRegion*>(dstHandle);
 const SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle);
 SkIRect    ir;
 GraphicsJNI::jrect_to_irect(env, rectObject, &ir);
 bool result = dst->op(ir, *region, (SkRegion::Op)op);
 return boolTojboolean(result);
}

Project: Android

static jboolean Region_op2(JNIEnv* env, jobject, jlong dstHandle, jlong region1Handle, jlong region2Handle, jint op) {
 SkRegion* dst = reinterpret_cast<SkRegion*>(dstHandle);
 const SkRegion* region1 = reinterpret_cast<SkRegion*>(region1Handle);
 const SkRegion* region2 = reinterpret_cast<SkRegion*>(region2Handle);
 bool result = dst->op(*region1, *region2, (SkRegion::Op)op);
 return boolTojboolean(result);
}

Project: Android

static jboolean Region_quickContains(JNIEnv* env, jobject region, jint left, jint top, jint right, jint bottom) {
 bool result = GetSkRegion(env, region)->quickContains(left, top, right, bottom);
 return boolTojboolean(result);
}

Project: Android

static jboolean Region_quickRejectRgn(JNIEnv* env, jobject region, jobject other) {
 bool result = GetSkRegion(env, region)->quickReject(*GetSkRegion(env, other));
 return boolTojboolean(result);
}

Project: Android

static void Region_scale(JNIEnv* env, jobject region, jfloat scale, jobject dst) {
 SkRegion* rgn = GetSkRegion(env, region);
 if (dst)
        scale_rgn(GetSkRegion(env, dst), *rgn, scale);
 else
        scale_rgn(rgn, *rgn, scale);
}

Project: Android

static jboolean Region_setPath(JNIEnv* env, jobject, jlong dstHandle,
                               jlong pathHandle, jlong clipHandle) {
 SkRegion*       dst  = reinterpret_cast<SkRegion*>(dstHandle);
 const SkPath*   path = reinterpret_cast<SkPath*>(pathHandle);
 const SkRegion* clip = reinterpret_cast<SkRegion*>(clipHandle);
 SkASSERT(dst && path && clip);
 bool result = dst->setPath(*path, *clip);
 return boolTojboolean(result);

}

Project: Android

static jboolean Region_setRect(JNIEnv* env, jobject, jlong dstHandle, jint left, jint top, jint right, jint bottom) {
 SkRegion* dst = reinterpret_cast<SkRegion*>(dstHandle);
 bool result = dst->setRect(left, top, right, bottom);
 return boolTojboolean(result);
}

Project: Android

static void Region_setRegion(JNIEnv* env, jobject, jlong dstHandle, jlong srcHandle) {
 SkRegion* dst = reinterpret_cast<SkRegion*>(dstHandle);
 const SkRegion* src = reinterpret_cast<SkRegion*>(srcHandle);
 SkASSERT(dst && src);
 *dst = *src;
}

Project: Android

static void Region_translate(JNIEnv* env, jobject region, jint x, jint y, jobject dst) {
 SkRegion* rgn = GetSkRegion(env, region);
 if (dst)
        rgn->translate(x, y, GetSkRegion(env, dst));
 else
        rgn->translate(x, y);
}

Project: Android

 RgnIterPair(const SkRegion& rgn) : fRgn(rgn) {
        fIter.reset(fRgn);
 }

Project: Android

SkRegion* android_graphics_Region_getSkRegion(JNIEnv* env, jobject regionObj) {
 return GetSkRegion(env, regionObj);
}

Project: Android

static inline jboolean boolTojboolean(bool value) {
 return value ? JNI_TRUE : JNI_FALSE;
}

Project: Android

static void scale_rect(SkIRect* dst, const SkIRect& src, float scale) {
   dst->fLeft = (int)::roundf(src.fLeft * scale);
   dst->fTop = (int)::roundf(src.fTop * scale);
   dst->fRight = (int)::roundf(src.fRight * scale);
   dst->fBottom = (int)::roundf(src.fBottom * scale);
}

Project: Android

static void scale_rgn(SkRegion* dst, const SkRegion& src, float scale) {
 SkRegion tmp;
 SkRegion::Iterator iter(src);

 for (; !iter.done(); iter.next()) {
 SkIRect r;
       scale_rect(&r, iter.rect(), scale);
       tmp.op(r, SkRegion::kUnion_Op);
 }
   dst->swap(tmp);
}