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;
}
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);
}
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;
}
Aggregations