summaryrefslogtreecommitdiffstats
path: root/libs/androidfw
diff options
context:
space:
mode:
Diffstat (limited to 'libs/androidfw')
-rw-r--r--libs/androidfw/BackupHelpers.cpp21
-rw-r--r--libs/androidfw/ResourceTypes.cpp86
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;
}