Search in sources :

Example 1 with ResStringPool_span

use of org.robolectric.res.android.ResourceTypes.ResStringPool_span in project robolectric by robolectric.

the class ResStringPool method setTo.

// status_t setTo(const void* data, size_t size, bool copyData=false);
public int setTo(ByteBuffer buf, int offset, int size, boolean copyData) {
    if (!isTruthy(buf) || !isTruthy(size)) {
        return (mError = BAD_TYPE);
    }
    uninit();
    // The chunk must be at least the size of the string pool header.
    if (size < ResStringPool_header.SIZEOF) {
        ALOGW("Bad string block: data size %zu is too small to be a string block", size);
        return (mError = BAD_TYPE);
    }
    // `data + size` is safe because the source of `size` comes from the kernel/filesystem.
    if (validate_chunk(new ResChunk_header(buf, offset), ResStringPool_header.SIZEOF, size, "ResStringPool_header") != NO_ERROR) {
        ALOGW("Bad string block: malformed block dimensions");
        return (mError = BAD_TYPE);
    }
    // final boolean notDeviceEndian = htods((short) 0xf0) != 0xf0;
    // 
    // if (copyData || notDeviceEndian) {
    // mOwnedData = data;
    // if (mOwnedData == null) {
    // return (mError=NO_MEMORY);
    // }
    // //      memcpy(mOwnedData, data, size);
    // data = mOwnedData;
    // }
    // The size has been checked, so it is safe to read the data in the ResStringPool_header
    // data structure.
    mHeader = new ResStringPool_header(buf, offset);
    if (mHeader.header.headerSize > mHeader.header.size || mHeader.header.size > size) {
        ALOGW("Bad string block: header size %d or total size %d is larger than data size %d\n", (int) mHeader.header.headerSize, (int) mHeader.header.size, (int) size);
        return (mError = BAD_TYPE);
    }
    mSize = mHeader.header.size;
    mEntries = new IntArray(mHeader.myBuf(), mHeader.myOffset() + mHeader.header.headerSize);
    if (mHeader.stringCount > 0) {
        if (// uint32 overflow?
        (mHeader.stringCount * 4 < /*sizeof(uint32_t)*/
        mHeader.stringCount) || (mHeader.header.headerSize + (mHeader.stringCount * 4)) > size) {
            ALOGW("Bad string block: entry of %d items extends past data size %d\n", (int) (mHeader.header.headerSize + (mHeader.stringCount * 4)), (int) size);
            return (mError = BAD_TYPE);
        }
        int charSize;
        if (isTruthy(mHeader.flags & ResStringPool_header.UTF8_FLAG)) {
            charSize = 1;
        } else {
            charSize = 2;
        }
        // (2 bytes length, null terminator).
        if (mHeader.stringsStart >= (mSize - 2)) {
            ALOGW("Bad string block: string pool starts at %d, after total size %d\n", (int) mHeader.stringsStart, (int) mHeader.header.size);
            return (mError = BAD_TYPE);
        }
        mStrings = mHeader.stringsStart;
        if (mHeader.styleCount == 0) {
            mStringPoolSize = (mSize - mHeader.stringsStart) / charSize;
        } else {
            // check invariant: styles starts before end of data
            if (mHeader.stylesStart >= (mSize - 2)) {
                ALOGW("Bad style block: style block starts at %d past data size of %d\n", (int) mHeader.stylesStart, (int) mHeader.header.size);
                return (mError = BAD_TYPE);
            }
            // check invariant: styles follow the strings
            if (mHeader.stylesStart <= mHeader.stringsStart) {
                ALOGW("Bad style block: style block starts at %d, before strings at %d\n", (int) mHeader.stylesStart, (int) mHeader.stringsStart);
                return (mError = BAD_TYPE);
            }
            mStringPoolSize = (mHeader.stylesStart - mHeader.stringsStart) / charSize;
        }
        // check invariant: stringCount > 0 requires a string pool to exist
        if (mStringPoolSize == 0) {
            ALOGW("Bad string block: stringCount is %d but pool size is 0\n", (int) mHeader.stringCount);
            return (mError = BAD_TYPE);
        }
        if ((isTruthy(mHeader.flags & ResStringPool_header.UTF8_FLAG) && (mHeader.getByte(mStrings + mStringPoolSize - 1) != 0)) || (!isTruthy(mHeader.flags & ResStringPool_header.UTF8_FLAG) && (mHeader.getShort(mStrings + mStringPoolSize * 2 - 2) != 0))) {
            ALOGW("Bad string block: last string is not 0-terminated\n");
            return (mError = BAD_TYPE);
        }
    } else {
        mStrings = -1;
        mStringPoolSize = 0;
    }
    if (mHeader.styleCount > 0) {
        mEntryStyles = new IntArray(mEntries.myBuf(), mEntries.myOffset() + mHeader.stringCount * SIZEOF_INT);
        // invariant: integer overflow in calculating mEntryStyles
        if (mEntryStyles.myOffset() < mEntries.myOffset()) {
            ALOGW("Bad string block: integer overflow finding styles\n");
            return (mError = BAD_TYPE);
        }
        // if (((const uint8_t*)mEntryStyles-(const uint8_t*)mHeader) > (int)size) {
        if ((mEntryStyles.myOffset() - mHeader.myOffset()) > (int) size) {
            ALOGW("Bad string block: entry of %d styles extends past data size %d\n", (int) (mEntryStyles.myOffset()), (int) size);
            return (mError = BAD_TYPE);
        }
        mStyles = mHeader.stylesStart;
        if (mHeader.stylesStart >= mHeader.header.size) {
            ALOGW("Bad string block: style pool starts %d, after total size %d\n", (int) mHeader.stylesStart, (int) mHeader.header.size);
            return (mError = BAD_TYPE);
        }
        mStylePoolSize = (mHeader.header.size - mHeader.stylesStart);
        // if (notDeviceEndian) {
        // size_t i;
        // uint32_t* e = final_cast<uint32_t*>(mEntryStyles);
        // for (i=0; i<mHeader.styleCount; i++) {
        // e[i] = dtohl(mEntryStyles[i]);
        // }
        // uint32_t* s = final_cast<uint32_t*>(mStyles);
        // for (i=0; i<mStylePoolSize; i++) {
        // s[i] = dtohl(mStyles[i]);
        // }
        // }
        // final ResStringPool_span endSpan = {
        // { htodl(ResStringPool_span.END) },
        // htodl(ResStringPool_span.END), htodl(ResStringPool_span.END)
        // };
        // if (memcmp(&mStyles[mStylePoolSize-(sizeof(endSpan)/sizeof(uint32_t))],
        // &endSpan, sizeof(endSpan)) != 0) {
        ResStringPool_span endSpan = new ResStringPool_span(buf, mHeader.myOffset() + mStyles + (mStylePoolSize - ResStringPool_span.SIZEOF));
        if (!endSpan.isEnd()) {
            ALOGW("Bad string block: last style is not 0xFFFFFFFF-terminated\n");
            return (mError = BAD_TYPE);
        }
    } else {
        mEntryStyles = null;
        mStyles = 0;
        mStylePoolSize = 0;
    }
    return (mError = NO_ERROR);
}
Also used : ResStringPool_span(org.robolectric.res.android.ResourceTypes.ResStringPool_span) ResChunk_header(org.robolectric.res.android.ResourceTypes.ResChunk_header) ResStringPool_header(org.robolectric.res.android.ResourceTypes.ResStringPool_header)

Example 2 with ResStringPool_span

use of org.robolectric.res.android.ResourceTypes.ResStringPool_span in project robolectric by robolectric.

the class ShadowStringBlock method nativeGetStyle.

@Implementation(minSdk = LOLLIPOP)
protected static int[] nativeGetStyle(long obj, int idx) {
    ResStringPool osb = ResStringPool.getNativeObject(obj);
    ResStringPool_span spans = osb.styleAt(idx);
    if (spans == null) {
        return null;
    }
    ResStringPool_span pos = spans;
    int num = 0;
    while (pos.name.index != ResStringPool_span.END) {
        num++;
        // pos++;
        pos = new ResStringPool_span(pos.myBuf(), pos.myOffset() + ResStringPool_span.SIZEOF);
    }
    if (num == 0) {
        return null;
    }
    // jintArray array = env->NewIntArray((num*sizeof(ResStringPool_span))/sizeof(jint));
    int[] array = new int[num * ResStringPool_span.SIZEOF / SIZEOF_INT];
    if (array == null) {
        // NewIntArray already threw OutOfMemoryError.
        return null;
    }
    num = 0;
    final int numInts = ResStringPool_span.SIZEOF / SIZEOF_INT;
    while (spans.name.index != ResStringPool_span.END) {
        // env->SetIntArrayRegion(array,
        // num*numInts, numInts,
        // (jint*)spans);
        setIntArrayRegion(array, num, numInts, spans);
        // spans++;
        spans = new ResStringPool_span(spans.myBuf(), spans.myOffset() + ResStringPool_span.SIZEOF);
        num++;
    }
    return array;
}
Also used : ResStringPool_span(org.robolectric.res.android.ResourceTypes.ResStringPool_span) ResStringPool(org.robolectric.res.android.ResStringPool) Implementation(org.robolectric.annotation.Implementation)

Aggregations

ResStringPool_span (org.robolectric.res.android.ResourceTypes.ResStringPool_span)2 Implementation (org.robolectric.annotation.Implementation)1 ResStringPool (org.robolectric.res.android.ResStringPool)1 ResChunk_header (org.robolectric.res.android.ResourceTypes.ResChunk_header)1 ResStringPool_header (org.robolectric.res.android.ResourceTypes.ResStringPool_header)1