Search in sources :

Example 1 with ResStringPool_header

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

the class ResStringPool method setToEmpty.

void setToEmpty() {
    uninit();
    ByteBuffer buf = ByteBuffer.allocate(16 * 1024).order(ByteOrder.LITTLE_ENDIAN);
    Writer resStringPoolWriter = new Writer();
    resStringPoolWriter.write(buf);
    mOwnedData = new byte[buf.position()];
    buf.position();
    buf.get(mOwnedData);
    ResStringPool_header header = new ResStringPool_header(buf, 0);
    mSize = 0;
    mEntries = null;
    mStrings = 0;
    mStringPoolSize = 0;
    mEntryStyles = null;
    mStyles = 0;
    mStylePoolSize = 0;
    mHeader = header;
}
Also used : ResStringPool_header(org.robolectric.res.android.ResourceTypes.ResStringPool_header) ByteBuffer(java.nio.ByteBuffer) Writer(org.robolectric.res.android.ResourceTypes.ResStringPool_header.Writer)

Example 2 with ResStringPool_header

use of org.robolectric.res.android.ResourceTypes.ResStringPool_header 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 3 with ResStringPool_header

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

the class LoadedArsc method LoadTable.

boolean LoadTable(Chunk chunk, LoadedIdmap loaded_idmap, boolean load_as_shared_library) {
    // ResTable_header header = chunk.header<ResTable_header>();
    ResTable_header header = chunk.asResTable_header();
    if (header == null) {
        logError("RES_TABLE_TYPE too small.");
        return false;
    }
    int package_count = dtohl(header.packageCount);
    int packages_seen = 0;
    // packages_.reserve(package_count);
    Chunk.Iterator iter = new Iterator(chunk.data_ptr(), chunk.data_size());
    while (iter.HasNext()) {
        Chunk child_chunk = iter.Next();
        switch(child_chunk.type()) {
            case RES_STRING_POOL_TYPE:
                // Only use the first string pool. Ignore others.
                if (global_string_pool_.getError() == NO_INIT) {
                    ResStringPool_header resStringPool_header = child_chunk.asResStringPool_header();
                    int err = global_string_pool_.setTo(resStringPool_header.myBuf(), resStringPool_header.myOffset(), child_chunk.size(), false);
                    if (err != NO_ERROR) {
                        logError("RES_STRING_POOL_TYPE corrupt.");
                        return false;
                    }
                } else {
                    logWarning("Multiple RES_STRING_POOL_TYPEs found in RES_TABLE_TYPE.");
                }
                break;
            case RES_TABLE_PACKAGE_TYPE:
                {
                    if (packages_seen + 1 > package_count) {
                        logError("More package chunks were found than the " + package_count + " declared in the header.");
                        return false;
                    }
                    packages_seen++;
                    LoadedPackage loaded_package = LoadedPackage.Load(child_chunk, loaded_idmap, system_, load_as_shared_library);
                    if (!isTruthy(loaded_package)) {
                        return false;
                    }
                    packages_.add(loaded_package);
                }
                break;
            default:
                logWarning(String.format("Unknown chunk type '%02x'.", chunk.type()));
                break;
        }
    }
    if (iter.HadError()) {
        logError(iter.GetLastError());
        if (iter.HadFatalError()) {
            return false;
        }
    }
    return true;
}
Also used : ResTable_header(org.robolectric.res.android.ResourceTypes.ResTable_header) Iterator(org.robolectric.res.android.Chunk.Iterator) ResStringPool_header(org.robolectric.res.android.ResourceTypes.ResStringPool_header) Iterator(org.robolectric.res.android.Chunk.Iterator)

Aggregations

ResStringPool_header (org.robolectric.res.android.ResourceTypes.ResStringPool_header)3 ByteBuffer (java.nio.ByteBuffer)1 Iterator (org.robolectric.res.android.Chunk.Iterator)1 ResChunk_header (org.robolectric.res.android.ResourceTypes.ResChunk_header)1 Writer (org.robolectric.res.android.ResourceTypes.ResStringPool_header.Writer)1 ResStringPool_span (org.robolectric.res.android.ResourceTypes.ResStringPool_span)1 ResTable_header (org.robolectric.res.android.ResourceTypes.ResTable_header)1