diff options
Diffstat (limited to 'libs/androidfw')
-rw-r--r-- | libs/androidfw/BackupHelpers.cpp | 21 | ||||
-rw-r--r-- | libs/androidfw/ResourceTypes.cpp | 86 |
2 files changed, 91 insertions, 16 deletions
diff --git a/libs/androidfw/BackupHelpers.cpp b/libs/androidfw/BackupHelpers.cpp index 227de3b..9300794 100644 --- a/libs/androidfw/BackupHelpers.cpp +++ b/libs/androidfw/BackupHelpers.cpp @@ -478,7 +478,8 @@ void send_tarfile_chunk(BackupDataWriter* writer, const char* buffer, size_t siz } int write_tarfile(const String8& packageName, const String8& domain, - const String8& rootpath, const String8& filepath, BackupDataWriter* writer) + const String8& rootpath, const String8& filepath, off_t* outSize, + BackupDataWriter* writer) { // In the output stream everything is stored relative to the root const char* relstart = filepath.string() + rootpath.length(); @@ -488,6 +489,7 @@ int write_tarfile(const String8& packageName, const String8& domain, // If relpath is empty, it means this is the top of one of the standard named // domain directories, so we should just skip it if (relpath.length() == 0) { + *outSize = 0; return 0; } @@ -517,12 +519,25 @@ int write_tarfile(const String8& packageName, const String8& domain, return err; } + // very large files need a pax extended size header + if (s.st_size > 077777777777LL) { + needExtended = true; + } + String8 fullname; // for pax later on String8 prefix; const int isdir = S_ISDIR(s.st_mode); if (isdir) s.st_size = 0; // directories get no actual data in the tar stream + // Report the size, including a rough tar overhead estimation: 512 bytes for the + // overall tar file-block header, plus 2 blocks if using the pax extended format, + // plus the raw content size rounded up to a multiple of 512. + *outSize = 512 + (needExtended ? 1024 : 0) + 512*((s.st_size + 511)/512); + + // Measure case: we've returned the size; now return without moving data + if (!writer) return 0; + // !!! TODO: use mmap when possible to avoid churning the buffer cache // !!! TODO: this will break with symlinks; need to use readlink(2) int fd = open(filepath.string(), O_RDONLY); @@ -560,10 +575,6 @@ int write_tarfile(const String8& packageName, const String8& domain, snprintf(buf + 116, 8, "0%lo", (unsigned long)s.st_gid); // [ 124 : 12 ] file size in bytes - if (s.st_size > 077777777777LL) { - // very large files need a pax extended size header - needExtended = true; - } snprintf(buf + 124, 12, "%011llo", (isdir) ? 0LL : s.st_size); // [ 136 : 12 ] last mod time as a UTC time_t diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp index fbe08ec..04ebe70 100644 --- a/libs/androidfw/ResourceTypes.cpp +++ b/libs/androidfw/ResourceTypes.cpp @@ -704,6 +704,12 @@ const char16_t* ResStringPool::stringAt(size_t idx, size_t* u16len) const *u16len = decodeLength(&str); if ((uint32_t)(str+*u16len-strings) < mStringPoolSize) { + // Reject malformed (non null-terminated) strings + if (str[*u16len] != 0x0000) { + ALOGW("Bad string block: string #%d is not null-terminated", + (int)idx); + return NULL; + } return reinterpret_cast<const char16_t*>(str); } else { ALOGW("Bad string block: string #%d extends to %d, past end at %d\n", @@ -751,6 +757,13 @@ const char16_t* ResStringPool::stringAt(size_t idx, size_t* u16len) const return NULL; } + // Reject malformed (non null-terminated) strings + if (u8str[u8len] != 0x00) { + ALOGW("Bad string block: string #%d is not null-terminated", + (int)idx); + return NULL; + } + char16_t *u16str = (char16_t *)calloc(*u16len+1, sizeof(char16_t)); if (!u16str) { ALOGW("No memory when trying to allocate decode cache for string #%d\n", @@ -2540,6 +2553,58 @@ bool ResTable_config::match(const ResTable_config& settings) const { return true; } +void ResTable_config::appendDirLocale(String8& out) const { + if (!language[0]) { + return; + } + + if (!localeScript[0] && !localeVariant[0]) { + // Legacy format. + if (out.size() > 0) { + out.append("-"); + } + + char buf[4]; + size_t len = unpackLanguage(buf); + out.append(buf, len); + + if (country[0]) { + out.append("-r"); + len = unpackRegion(buf); + out.append(buf, len); + } + return; + } + + // We are writing the modified bcp47 tag. + // It starts with 'b+' and uses '+' as a separator. + + if (out.size() > 0) { + out.append("-"); + } + out.append("b+"); + + char buf[4]; + size_t len = unpackLanguage(buf); + out.append(buf, len); + + if (localeScript[0]) { + out.append("+"); + out.append(localeScript, sizeof(localeScript)); + } + + if (country[0]) { + out.append("+"); + len = unpackRegion(buf); + out.append(buf, len); + } + + if (localeVariant[0]) { + out.append("+"); + out.append(localeVariant, sizeof(localeVariant)); + } +} + void ResTable_config::getBcp47Locale(char str[RESTABLE_MAX_LOCALE_LEN]) const { memset(str, 0, RESTABLE_MAX_LOCALE_LEN); @@ -2640,12 +2705,7 @@ String8 ResTable_config::toString() const { res.appendFormat("mnc%d", dtohs(mnc)); } - char localeStr[RESTABLE_MAX_LOCALE_LEN]; - getBcp47Locale(localeStr); - if (strlen(localeStr) > 0) { - if (res.size() > 0) res.append("-"); - res.append(localeStr); - } + appendDirLocale(res); if ((screenLayout&MASK_LAYOUTDIR) != 0) { if (res.size() > 0) res.append("-"); @@ -3119,7 +3179,8 @@ ResTable::Theme::package_info* ResTable::Theme::copy_package(package_info* pi) size_t cnt = pi->types[j].numEntries; newpi->types[j].numEntries = cnt; theme_entry* te = pi->types[j].entries; - if (te != NULL) { + size_t cnt_max = SIZE_MAX / sizeof(theme_entry); + if (te != NULL && (cnt < 0xFFFFFFFF-1) && (cnt < cnt_max)) { theme_entry* newte = (theme_entry*)malloc(cnt*sizeof(theme_entry)); newpi->types[j].entries = newte; memcpy(newte, te, cnt*sizeof(theme_entry)); @@ -3186,9 +3247,12 @@ status_t ResTable::Theme::applyStyle(uint32_t resID, bool force) if (curEntries == NULL) { PackageGroup* const grp = mTable.mPackageGroups[curPackageIndex]; const TypeList& typeList = grp->types[t]; - int cnt = typeList.isEmpty() ? 0 : typeList[0]->entryCount; - curEntries = (theme_entry*)malloc(cnt*sizeof(theme_entry)); - memset(curEntries, Res_value::TYPE_NULL, cnt*sizeof(theme_entry)); + size_t cnt = typeList.isEmpty() ? 0 : typeList[0]->entryCount; + size_t cnt_max = SIZE_MAX / sizeof(theme_entry); + size_t buff_size = (cnt < cnt_max && cnt < 0xFFFFFFFF-1) ? + cnt*sizeof(theme_entry) : 0; + curEntries = (theme_entry*)malloc(buff_size); + memset(curEntries, Res_value::TYPE_NULL, buff_size); curPI->types[t].numEntries = cnt; curPI->types[t].entries = curEntries; } @@ -4672,7 +4736,7 @@ bool ResTable::stringToFloat(const char16_t* s, size_t len, Res_value* outValue) if (len > 0) { return false; } - if (buf[0] < '0' && buf[0] > '9' && buf[0] != '.') { + if ((buf[0] < '0' || buf[0] > '9') && buf[0] != '.' && buf[0] != '-' && buf[0] != '+') { return false; } |