static const struct zip_cd *find_cd_for_entry(const uint8_t *map, size_t size, const struct zip_eocd *eocd, const char *filename) { /* * eocd->cd_offset points to the beginning of eocd->entry_count number * of Central Directories, one per entry. Find the one representing the * requested filename. */ const struct zip_cd *cd; size_t i; die_if(eocd->cd_offset > size, "eocd offset too large"); cd = (struct zip_cd *)(map + dtohl(eocd->cd_offset)); for (i = 0; i < eocd->entry_count; i++) { uint16_t len; die_if(dtohl(cd->magic) != ZIP_CD_MAGIC, "bad zip cd magic 0x%08x", dtohl(cd->magic)); len = dtohs(cd->filename_length); if (len == strlen(filename) && !memcmp(cd->filename, filename, len)) return cd; cd = (const struct zip_cd *) ((const uint8_t *)cd + sizeof(*cd) + len + dtohs(cd->extra_length) + dtohs(cd->comment_length)); die_if((const uint8_t *)cd > map + size, "cd outside map"); } die("no entry '%s' found", filename); return NULL; }
static const struct zip_lfh *find_lfh_for_entry(const uint8_t *map, size_t size, const struct zip_cd *cd) { const struct zip_lfh *lfh; die_if(cd->lfh_offset > size, "lfh offset outside map"); lfh = (const struct zip_lfh *)(map + cd->lfh_offset); die_if(dtohs(lfh->compression_method) != 0, "unhandled compression method %d", dtohs(lfh->compression_method)); return lfh; }
static void dump(const struct blob *blob) { uint32_t i; printf("header: package_count=%d\n", dtohl(blob->header->data.package_count)); printf("string pool (resource values): string_count=%d\n", dtohl(blob->sp_values->data.string_count)); for (i = 0; i < dtohl(blob->header->data.package_count); i++) { const struct package *pkg = &blob->packages[i]; size_t j; printf("package: id=0x%02x spec_count=%zd\n", dtohl(pkg->package->data.id), pkg->spec_count); printf("string pool (type names): string_count=%d\n", dtohl(pkg->sp_type_names->data.string_count)); printf("string pool (resource names): string_count=%d\n", dtohl(pkg->sp_resource_names->data.string_count)); for (j = 0; j < pkg->spec_count; j++) { const struct type_spec *spec = &pkg->specs[j]; size_t k; printf("type spec: id=0x%02x type_count=%zd\n", dtohs(spec->spec->data.id), spec->type_count); for (k = 0; k < spec->type_count; k++) { const struct arsc_type *type = spec->types[k]; dump_type(type); } } } }
static void dump_type(const struct arsc_type *type) { char c[CONFIG_LEN]; config_to_string(&type->data.config, c); printf("type: id=0x%02x entry_count=%d entries_start=0x%02x config=%s\n", dtohs(type->data.id), dtohl(type->data.entry_count), dtohl(type->data.entries_start), c); }
static const struct zip_eocd *find_eocd(const uint8_t *map, size_t size) { const struct zip_eocd *eocd; eocd = (struct zip_eocd *)(map + size - sizeof(*eocd)); die_if(dtohl(eocd->magic) != ZIP_EOCD_MAGIC, "bad zip eocd magic 0x%08x", dtohl(eocd->magic)); die_if(dtohs(eocd->entry_count) == 0, "bad entry count 0"); return eocd; }
static void adjust_map_to_zip_entry(struct mapped_file *map, const char *entry_name) { const struct zip_eocd *eocd; const struct zip_cd *cd; const struct zip_lfh *lfh; uint32_t entry_size; uint32_t entry_offset; eocd = find_eocd(map->map, map->map_size); cd = find_cd_for_entry(map->map, map->map_size, eocd, entry_name); lfh = find_lfh_for_entry(map->map, map->map_size, cd); entry_size = lfh->compressed_size; entry_offset = (const uint8_t *)lfh - (const uint8_t *)map->map + sizeof(*lfh) + dtohs(lfh->filename_length) + dtohs(lfh->extra_length); map->data = (const uint8_t *)map->map + entry_offset; map->data_size = entry_size; }
TypeVariant::TypeVariant(const ResTable_type* data) : data(data), mLength(dtohl(data->entryCount)) { if (data->flags & ResTable_type::FLAG_SPARSE) { const uint32_t entryCount = dtohl(data->entryCount); const uintptr_t containerEnd = reinterpret_cast<uintptr_t>(data) + dtohl(data->header.size); const uint32_t* const entryIndices = reinterpret_cast<const uint32_t*>( reinterpret_cast<uintptr_t>(data) + dtohs(data->header.headerSize)); if (reinterpret_cast<uintptr_t>(entryIndices) + (sizeof(uint32_t) * entryCount) > containerEnd) { ALOGE("Type's entry indices extend beyond its boundaries"); mLength = 0; } else { mLength = ResTable_sparseTypeEntry{entryIndices[entryCount - 1]}.idx + 1; } } }
const ResTable_entry* TypeVariant::iterator::operator*() const { const ResTable_type* type = mTypeVariant->data; if (mIndex >= mTypeVariant->mLength) { return NULL; } const uint32_t entryCount = dtohl(mTypeVariant->data->entryCount); const uintptr_t containerEnd = reinterpret_cast<uintptr_t>(type) + dtohl(type->header.size); const uint32_t* const entryIndices = reinterpret_cast<const uint32_t*>( reinterpret_cast<uintptr_t>(type) + dtohs(type->header.headerSize)); if (reinterpret_cast<uintptr_t>(entryIndices) + (sizeof(uint32_t) * entryCount) > containerEnd) { ALOGE("Type's entry indices extend beyond its boundaries"); return NULL; } uint32_t entryOffset; if (type->flags & ResTable_type::FLAG_SPARSE) { auto iter = std::lower_bound(entryIndices, entryIndices + entryCount, mIndex, keyCompare); if (iter == entryIndices + entryCount || dtohs(ResTable_sparseTypeEntry{*iter}.idx) != mIndex) { return NULL; } entryOffset = static_cast<uint32_t>(dtohs(ResTable_sparseTypeEntry{*iter}.offset)) * 4u; } else { entryOffset = dtohl(entryIndices[mIndex]); } if (entryOffset == ResTable_type::NO_ENTRY) { return NULL; } if ((entryOffset & 0x3) != 0) { ALOGE("Index %u points to entry with unaligned offset 0x%08x", mIndex, entryOffset); return NULL; } const ResTable_entry* entry = reinterpret_cast<const ResTable_entry*>( reinterpret_cast<uintptr_t>(type) + dtohl(type->entriesStart) + entryOffset); if (reinterpret_cast<uintptr_t>(entry) > containerEnd - sizeof(*entry)) { ALOGE("Entry offset at index %u points outside the Type's boundaries", mIndex); return NULL; } else if (reinterpret_cast<uintptr_t>(entry) + dtohs(entry->size) > containerEnd) { ALOGE("Entry at index %u extends beyond Type's boundaries", mIndex); return NULL; } else if (dtohs(entry->size) < sizeof(*entry)) { ALOGE("Entry at index %u is too small (%u)", mIndex, dtohs(entry->size)); return NULL; } return entry; }
static void android_content_res_XResources_rewriteXmlReferencesNative(JNIEnv* env, jclass clazz, jint parserPtr, jobject origRes, jobject repRes) { ResXMLParser* parser = (ResXMLParser*)parserPtr; const ResXMLTree& mTree = parser->mTree; uint32_t* mResIds = (uint32_t*)mTree.mResIds; ResXMLTree_attrExt* tag; int attrCount; if (parser == NULL) return; do { switch (parser->next()) { case ResXMLParser::START_TAG: tag = (ResXMLTree_attrExt*)parser->mCurExt; attrCount = dtohs(tag->attributeCount); for (int idx = 0; idx < attrCount; idx++) { ResXMLTree_attribute* attr = (ResXMLTree_attribute*) (((const uint8_t*)tag) + dtohs(tag->attributeStart) + (dtohs(tag->attributeSize)*idx)); // find resource IDs for attribute names int32_t attrNameID = parser->getAttributeNameID(idx); // only replace attribute name IDs for app packages if (attrNameID >= 0 && (size_t)attrNameID < mTree.mNumResIds && dtohl(mResIds[attrNameID]) >= 0x7f000000) { size_t attNameLen; const char16_t* attrName = mTree.mStrings.stringAt(attrNameID, &attNameLen); jint attrResID = env->CallStaticIntMethod(xresourcesClass, xresourcesTranslateAttrId, env->NewString((const jchar*)attrName, attNameLen), origRes); if (env->ExceptionCheck()) goto leave; mResIds[attrNameID] = htodl(attrResID); } // find original resource IDs for reference values (app packages only) if (attr->typedValue.dataType != Res_value::TYPE_REFERENCE) continue; jint oldValue = dtohl(attr->typedValue.data); if (oldValue < 0x7f000000) continue; jint newValue = env->CallStaticIntMethod(xresourcesClass, xresourcesTranslateResId, oldValue, origRes, repRes); if (env->ExceptionCheck()) goto leave; if (newValue != oldValue) attr->typedValue.data = htodl(newValue); } continue; case ResXMLParser::END_DOCUMENT: case ResXMLParser::BAD_DOCUMENT: goto leave; default: continue; } } while (true); leave: parser->restart(); }
_mfs_error MFS_Find_next_slave ( MFS_DRIVE_STRUCT_PTR drive_ptr, /*[IN] drive context */ pointer search_next_ptr /*[IN] address of search data block indicating the current criteria and the results ** of the last search results of this search are placed in this data block */ ) { MFS_SEARCH_DATA_PTR transfer_ptr; MFS_INTERNAL_SEARCH_PTR internal_search_ptr; MFS_DIR_ENTRY_PTR dir_entry_ptr; _mfs_error error_code; uint_32 len; boolean found; boolean match_all; boolean eightdotthree = FALSE; char_ptr lfn; char sname[SFILENAME_SIZE+1]; uint_32 dotfile = 0; MFS_DIR_ENTRY saved_dir_entry; transfer_ptr = (MFS_SEARCH_DATA_PTR) search_next_ptr; error_code = MFS_NO_ERROR; found = FALSE; if ( transfer_ptr ) { internal_search_ptr = &transfer_ptr->INTERNAL_SEARCH_DATA; if ( MFS_alloc_path(&lfn)!= MFS_NO_ERROR ) { return MFS_INSUFFICIENT_MEMORY; } match_all = MFS_Check_search_string_for_all(internal_search_ptr->SRC_PTR); if ( !match_all ) { dotfile = MFS_Is_dot_directory(internal_search_ptr->SRC_PTR); if ( dotfile == 0 ) { eightdotthree = MFS_Check_search_string_for_8dot3( internal_search_ptr->SRC_PTR); } } do { dir_entry_ptr = MFS_Find_directory_entry(drive_ptr, NULL, &internal_search_ptr->CURRENT_CLUSTER, &internal_search_ptr->DIR_ENTRY_INDEX, &internal_search_ptr->PREV_CLUSTER, internal_search_ptr->ATTRIBUTE & (~ATTR_EXCLUSIVE), &error_code); if ( dir_entry_ptr == NULL && !error_code ) { error_code = MFS_FILE_NOT_FOUND; break; } if ( internal_search_ptr->CURRENT_CLUSTER == CLUSTER_INVALID ) { error_code = MFS_FILE_NOT_FOUND; break; } if ( dir_entry_ptr == NULL ) { break; } saved_dir_entry=*dir_entry_ptr; /* Make sure the entry is not an LFN entry */ if ( *dir_entry_ptr->ATTRIBUTE != MFS_ATTR_LFN ) { MFS_Compress_nondotfile (dir_entry_ptr->NAME, sname); if ( match_all ) { found = TRUE; } else { if ( dotfile != 0 ) { if ( dotfile == 1 ) { found = internal_search_ptr->FULLNAME[0] == dir_entry_ptr->NAME[0]; } else if ( dotfile == 2 ) { found = (internal_search_ptr->FULLNAME[0] == dir_entry_ptr->NAME[0]) && (internal_search_ptr->FULLNAME[1] == dir_entry_ptr->NAME[1]); } else { found = FALSE; /* This shouldn't happen */ } } else if ( eightdotthree ) { found = MFS_Wildcard_match(internal_search_ptr->FILENAME, dir_entry_ptr->NAME); } else { if ( MFS_get_lfn_dir_cluster(drive_ptr, search_next_ptr, sname, lfn) == MFS_NO_ERROR ) { found = MFS_lfn_match(internal_search_ptr->SRC_PTR, lfn, 0); } else { found = MFS_lfn_match(internal_search_ptr->SRC_PTR, sname, 0); } } } } if ( !error_code ) { error_code = MFS_Increment_dir_index(drive_ptr, &internal_search_ptr->CURRENT_CLUSTER, &internal_search_ptr->DIR_ENTRY_INDEX, &internal_search_ptr->PREV_CLUSTER); } } while ( (error_code == MFS_NO_ERROR) && (found == FALSE) ); if ( error_code == MFS_NO_ERROR ) { transfer_ptr->ATTRIBUTE = dtohc(saved_dir_entry.ATTRIBUTE); transfer_ptr->TIME = dtohs(saved_dir_entry.TIME); transfer_ptr->DATE = dtohs(saved_dir_entry.DATE); transfer_ptr->FILE_SIZE = dtohl(saved_dir_entry.FILE_SIZE); /* Transfer the filename */ len = _strnlen(sname,13); if ( sname[len-1] == '.' ) { sname[len-1] = '\0'; } strncpy(transfer_ptr->NAME, sname, 13); } MFS_free_path((pointer)lfn); } else { error_code = MFS_INVALID_MEMORY_BLOCK_ADDRESS; } return(error_code); }
static bool keyCompare(uint32_t entry, uint16_t index) { return dtohs(ResTable_sparseTypeEntry{entry}.idx) < index; }