PageRenderTime 53ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/frameworks/base/libs/androidfw/ResourceTypes.cpp

https://gitlab.com/brian0218/rk3066_r-box_android4.2.2_sdk
C++ | 1474 lines | 1224 code | 153 blank | 97 comment | 292 complexity | dd8bd439d64b3614fb92a7328eb10094 MD5 | raw file
  1. /*
  2. * Copyright (C) 2008 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #define LOG_TAG "ResourceType"
  17. //#define LOG_NDEBUG 0
  18. #include <androidfw/ResourceTypes.h>
  19. #include <utils/Atomic.h>
  20. #include <utils/ByteOrder.h>
  21. #include <utils/Debug.h>
  22. #include <utils/Log.h>
  23. #include <utils/String16.h>
  24. #include <utils/String8.h>
  25. #include <utils/TextOutput.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <memory.h>
  29. #include <ctype.h>
  30. #include <stdint.h>
  31. #ifndef INT32_MAX
  32. #define INT32_MAX ((int32_t)(2147483647))
  33. #endif
  34. #define POOL_NOISY(x) //x
  35. #define XML_NOISY(x) //x
  36. #define TABLE_NOISY(x) //x
  37. #define TABLE_GETENTRY(x) //x
  38. #define TABLE_SUPER_NOISY(x) //x
  39. #define LOAD_TABLE_NOISY(x) //x
  40. #define TABLE_THEME(x) //x
  41. namespace android {
  42. #ifdef HAVE_WINSOCK
  43. #undef nhtol
  44. #undef htonl
  45. #ifdef HAVE_LITTLE_ENDIAN
  46. #define ntohl(x) ( ((x) << 24) | (((x) >> 24) & 255) | (((x) << 8) & 0xff0000) | (((x) >> 8) & 0xff00) )
  47. #define htonl(x) ntohl(x)
  48. #define ntohs(x) ( (((x) << 8) & 0xff00) | (((x) >> 8) & 255) )
  49. #define htons(x) ntohs(x)
  50. #else
  51. #define ntohl(x) (x)
  52. #define htonl(x) (x)
  53. #define ntohs(x) (x)
  54. #define htons(x) (x)
  55. #endif
  56. #endif
  57. #define IDMAP_MAGIC 0x706d6469
  58. // size measured in sizeof(uint32_t)
  59. #define IDMAP_HEADER_SIZE (ResTable::IDMAP_HEADER_SIZE_BYTES / sizeof(uint32_t))
  60. static void printToLogFunc(void* cookie, const char* txt)
  61. {
  62. ALOGV("%s", txt);
  63. }
  64. // Standard C isspace() is only required to look at the low byte of its input, so
  65. // produces incorrect results for UTF-16 characters. For safety's sake, assume that
  66. // any high-byte UTF-16 code point is not whitespace.
  67. inline int isspace16(char16_t c) {
  68. return (c < 0x0080 && isspace(c));
  69. }
  70. // range checked; guaranteed to NUL-terminate within the stated number of available slots
  71. // NOTE: if this truncates the dst string due to running out of space, no attempt is
  72. // made to avoid splitting surrogate pairs.
  73. static void strcpy16_dtoh(uint16_t* dst, const uint16_t* src, size_t avail)
  74. {
  75. uint16_t* last = dst + avail - 1;
  76. while (*src && (dst < last)) {
  77. char16_t s = dtohs(*src);
  78. *dst++ = s;
  79. src++;
  80. }
  81. *dst = 0;
  82. }
  83. static status_t validate_chunk(const ResChunk_header* chunk,
  84. size_t minSize,
  85. const uint8_t* dataEnd,
  86. const char* name)
  87. {
  88. const uint16_t headerSize = dtohs(chunk->headerSize);
  89. const uint32_t size = dtohl(chunk->size);
  90. if (headerSize >= minSize) {
  91. if (headerSize <= size) {
  92. if (((headerSize|size)&0x3) == 0) {
  93. if ((ssize_t)size <= (dataEnd-((const uint8_t*)chunk))) {
  94. return NO_ERROR;
  95. }
  96. ALOGW("%s data size %p extends beyond resource end %p.",
  97. name, (void*)size,
  98. (void*)(dataEnd-((const uint8_t*)chunk)));
  99. return BAD_TYPE;
  100. }
  101. ALOGW("%s size 0x%x or headerSize 0x%x is not on an integer boundary.",
  102. name, (int)size, (int)headerSize);
  103. return BAD_TYPE;
  104. }
  105. ALOGW("%s size %p is smaller than header size %p.",
  106. name, (void*)size, (void*)(int)headerSize);
  107. return BAD_TYPE;
  108. }
  109. ALOGW("%s header size %p is too small.",
  110. name, (void*)(int)headerSize);
  111. return BAD_TYPE;
  112. }
  113. inline void Res_value::copyFrom_dtoh(const Res_value& src)
  114. {
  115. size = dtohs(src.size);
  116. res0 = src.res0;
  117. dataType = src.dataType;
  118. data = dtohl(src.data);
  119. }
  120. void Res_png_9patch::deviceToFile()
  121. {
  122. for (int i = 0; i < numXDivs; i++) {
  123. xDivs[i] = htonl(xDivs[i]);
  124. }
  125. for (int i = 0; i < numYDivs; i++) {
  126. yDivs[i] = htonl(yDivs[i]);
  127. }
  128. paddingLeft = htonl(paddingLeft);
  129. paddingRight = htonl(paddingRight);
  130. paddingTop = htonl(paddingTop);
  131. paddingBottom = htonl(paddingBottom);
  132. for (int i=0; i<numColors; i++) {
  133. colors[i] = htonl(colors[i]);
  134. }
  135. }
  136. void Res_png_9patch::fileToDevice()
  137. {
  138. for (int i = 0; i < numXDivs; i++) {
  139. xDivs[i] = ntohl(xDivs[i]);
  140. }
  141. for (int i = 0; i < numYDivs; i++) {
  142. yDivs[i] = ntohl(yDivs[i]);
  143. }
  144. paddingLeft = ntohl(paddingLeft);
  145. paddingRight = ntohl(paddingRight);
  146. paddingTop = ntohl(paddingTop);
  147. paddingBottom = ntohl(paddingBottom);
  148. for (int i=0; i<numColors; i++) {
  149. colors[i] = ntohl(colors[i]);
  150. }
  151. }
  152. size_t Res_png_9patch::serializedSize()
  153. {
  154. // The size of this struct is 32 bytes on the 32-bit target system
  155. // 4 * int8_t
  156. // 4 * int32_t
  157. // 3 * pointer
  158. return 32
  159. + numXDivs * sizeof(int32_t)
  160. + numYDivs * sizeof(int32_t)
  161. + numColors * sizeof(uint32_t);
  162. }
  163. void* Res_png_9patch::serialize()
  164. {
  165. // Use calloc since we're going to leave a few holes in the data
  166. // and want this to run cleanly under valgrind
  167. void* newData = calloc(1, serializedSize());
  168. serialize(newData);
  169. return newData;
  170. }
  171. void Res_png_9patch::serialize(void * outData)
  172. {
  173. char* data = (char*) outData;
  174. memmove(data, &wasDeserialized, 4); // copy wasDeserialized, numXDivs, numYDivs, numColors
  175. memmove(data + 12, &paddingLeft, 16); // copy paddingXXXX
  176. data += 32;
  177. memmove(data, this->xDivs, numXDivs * sizeof(int32_t));
  178. data += numXDivs * sizeof(int32_t);
  179. memmove(data, this->yDivs, numYDivs * sizeof(int32_t));
  180. data += numYDivs * sizeof(int32_t);
  181. memmove(data, this->colors, numColors * sizeof(uint32_t));
  182. }
  183. static void deserializeInternal(const void* inData, Res_png_9patch* outData) {
  184. char* patch = (char*) inData;
  185. if (inData != outData) {
  186. memmove(&outData->wasDeserialized, patch, 4); // copy wasDeserialized, numXDivs, numYDivs, numColors
  187. memmove(&outData->paddingLeft, patch + 12, 4); // copy wasDeserialized, numXDivs, numYDivs, numColors
  188. }
  189. outData->wasDeserialized = true;
  190. char* data = (char*)outData;
  191. data += sizeof(Res_png_9patch);
  192. outData->xDivs = (int32_t*) data;
  193. data += outData->numXDivs * sizeof(int32_t);
  194. outData->yDivs = (int32_t*) data;
  195. data += outData->numYDivs * sizeof(int32_t);
  196. outData->colors = (uint32_t*) data;
  197. }
  198. static bool assertIdmapHeader(const uint32_t* map, size_t sizeBytes)
  199. {
  200. if (sizeBytes < ResTable::IDMAP_HEADER_SIZE_BYTES) {
  201. ALOGW("idmap assertion failed: size=%d bytes\n", (int)sizeBytes);
  202. return false;
  203. }
  204. if (*map != htodl(IDMAP_MAGIC)) { // htodl: map data expected to be in correct endianess
  205. ALOGW("idmap assertion failed: invalid magic found (is 0x%08x, expected 0x%08x)\n",
  206. *map, htodl(IDMAP_MAGIC));
  207. return false;
  208. }
  209. return true;
  210. }
  211. static status_t idmapLookup(const uint32_t* map, size_t sizeBytes, uint32_t key, uint32_t* outValue)
  212. {
  213. // see README for details on the format of map
  214. if (!assertIdmapHeader(map, sizeBytes)) {
  215. return UNKNOWN_ERROR;
  216. }
  217. map = map + IDMAP_HEADER_SIZE; // skip ahead to data segment
  218. // size of data block, in uint32_t
  219. const size_t size = (sizeBytes - ResTable::IDMAP_HEADER_SIZE_BYTES) / sizeof(uint32_t);
  220. const uint32_t type = Res_GETTYPE(key) + 1; // add one, idmap stores "public" type id
  221. const uint32_t entry = Res_GETENTRY(key);
  222. const uint32_t typeCount = *map;
  223. if (type > typeCount) {
  224. ALOGW("Resource ID map: type=%d exceeds number of types=%d\n", type, typeCount);
  225. return UNKNOWN_ERROR;
  226. }
  227. if (typeCount > size) {
  228. ALOGW("Resource ID map: number of types=%d exceeds size of map=%d\n", typeCount, (int)size);
  229. return UNKNOWN_ERROR;
  230. }
  231. const uint32_t typeOffset = map[type];
  232. if (typeOffset == 0) {
  233. *outValue = 0;
  234. return NO_ERROR;
  235. }
  236. if (typeOffset + 1 > size) {
  237. ALOGW("Resource ID map: type offset=%d exceeds reasonable value, size of map=%d\n",
  238. typeOffset, (int)size);
  239. return UNKNOWN_ERROR;
  240. }
  241. const uint32_t entryCount = map[typeOffset];
  242. const uint32_t entryOffset = map[typeOffset + 1];
  243. if (entryCount == 0 || entry < entryOffset || entry - entryOffset > entryCount - 1) {
  244. *outValue = 0;
  245. return NO_ERROR;
  246. }
  247. const uint32_t index = typeOffset + 2 + entry - entryOffset;
  248. if (index > size) {
  249. ALOGW("Resource ID map: entry index=%d exceeds size of map=%d\n", index, (int)size);
  250. *outValue = 0;
  251. return NO_ERROR;
  252. }
  253. *outValue = map[index];
  254. return NO_ERROR;
  255. }
  256. static status_t getIdmapPackageId(const uint32_t* map, size_t mapSize, uint32_t *outId)
  257. {
  258. if (!assertIdmapHeader(map, mapSize)) {
  259. return UNKNOWN_ERROR;
  260. }
  261. const uint32_t* p = map + IDMAP_HEADER_SIZE + 1;
  262. while (*p == 0) {
  263. ++p;
  264. }
  265. *outId = (map[*p + IDMAP_HEADER_SIZE + 2] >> 24) & 0x000000ff;
  266. return NO_ERROR;
  267. }
  268. Res_png_9patch* Res_png_9patch::deserialize(const void* inData)
  269. {
  270. if (sizeof(void*) != sizeof(int32_t)) {
  271. ALOGE("Cannot deserialize on non 32-bit system\n");
  272. return NULL;
  273. }
  274. deserializeInternal(inData, (Res_png_9patch*) inData);
  275. return (Res_png_9patch*) inData;
  276. }
  277. // --------------------------------------------------------------------
  278. // --------------------------------------------------------------------
  279. // --------------------------------------------------------------------
  280. ResStringPool::ResStringPool()
  281. : mError(NO_INIT), mOwnedData(NULL), mHeader(NULL), mCache(NULL)
  282. {
  283. }
  284. ResStringPool::ResStringPool(const void* data, size_t size, bool copyData)
  285. : mError(NO_INIT), mOwnedData(NULL), mHeader(NULL), mCache(NULL)
  286. {
  287. setTo(data, size, copyData);
  288. }
  289. ResStringPool::~ResStringPool()
  290. {
  291. uninit();
  292. }
  293. status_t ResStringPool::setTo(const void* data, size_t size, bool copyData)
  294. {
  295. if (!data || !size) {
  296. return (mError=BAD_TYPE);
  297. }
  298. uninit();
  299. const bool notDeviceEndian = htods(0xf0) != 0xf0;
  300. if (copyData || notDeviceEndian) {
  301. mOwnedData = malloc(size);
  302. if (mOwnedData == NULL) {
  303. return (mError=NO_MEMORY);
  304. }
  305. memcpy(mOwnedData, data, size);
  306. data = mOwnedData;
  307. }
  308. mHeader = (const ResStringPool_header*)data;
  309. if (notDeviceEndian) {
  310. ResStringPool_header* h = const_cast<ResStringPool_header*>(mHeader);
  311. h->header.headerSize = dtohs(mHeader->header.headerSize);
  312. h->header.type = dtohs(mHeader->header.type);
  313. h->header.size = dtohl(mHeader->header.size);
  314. h->stringCount = dtohl(mHeader->stringCount);
  315. h->styleCount = dtohl(mHeader->styleCount);
  316. h->flags = dtohl(mHeader->flags);
  317. h->stringsStart = dtohl(mHeader->stringsStart);
  318. h->stylesStart = dtohl(mHeader->stylesStart);
  319. }
  320. if (mHeader->header.headerSize > mHeader->header.size
  321. || mHeader->header.size > size) {
  322. ALOGW("Bad string block: header size %d or total size %d is larger than data size %d\n",
  323. (int)mHeader->header.headerSize, (int)mHeader->header.size, (int)size);
  324. return (mError=BAD_TYPE);
  325. }
  326. mSize = mHeader->header.size;
  327. mEntries = (const uint32_t*)
  328. (((const uint8_t*)data)+mHeader->header.headerSize);
  329. if (mHeader->stringCount > 0) {
  330. if ((mHeader->stringCount*sizeof(uint32_t) < mHeader->stringCount) // uint32 overflow?
  331. || (mHeader->header.headerSize+(mHeader->stringCount*sizeof(uint32_t)))
  332. > size) {
  333. ALOGW("Bad string block: entry of %d items extends past data size %d\n",
  334. (int)(mHeader->header.headerSize+(mHeader->stringCount*sizeof(uint32_t))),
  335. (int)size);
  336. return (mError=BAD_TYPE);
  337. }
  338. size_t charSize;
  339. if (mHeader->flags&ResStringPool_header::UTF8_FLAG) {
  340. charSize = sizeof(uint8_t);
  341. mCache = (char16_t**)calloc(mHeader->stringCount, sizeof(char16_t**));
  342. } else {
  343. charSize = sizeof(char16_t);
  344. }
  345. mStrings = (const void*)
  346. (((const uint8_t*)data)+mHeader->stringsStart);
  347. if (mHeader->stringsStart >= (mHeader->header.size-sizeof(uint16_t))) {
  348. ALOGW("Bad string block: string pool starts at %d, after total size %d\n",
  349. (int)mHeader->stringsStart, (int)mHeader->header.size);
  350. return (mError=BAD_TYPE);
  351. }
  352. if (mHeader->styleCount == 0) {
  353. mStringPoolSize =
  354. (mHeader->header.size-mHeader->stringsStart)/charSize;
  355. } else {
  356. // check invariant: styles starts before end of data
  357. if (mHeader->stylesStart >= (mHeader->header.size-sizeof(uint16_t))) {
  358. ALOGW("Bad style block: style block starts at %d past data size of %d\n",
  359. (int)mHeader->stylesStart, (int)mHeader->header.size);
  360. return (mError=BAD_TYPE);
  361. }
  362. // check invariant: styles follow the strings
  363. if (mHeader->stylesStart <= mHeader->stringsStart) {
  364. ALOGW("Bad style block: style block starts at %d, before strings at %d\n",
  365. (int)mHeader->stylesStart, (int)mHeader->stringsStart);
  366. return (mError=BAD_TYPE);
  367. }
  368. mStringPoolSize =
  369. (mHeader->stylesStart-mHeader->stringsStart)/charSize;
  370. }
  371. // check invariant: stringCount > 0 requires a string pool to exist
  372. if (mStringPoolSize == 0) {
  373. ALOGW("Bad string block: stringCount is %d but pool size is 0\n", (int)mHeader->stringCount);
  374. return (mError=BAD_TYPE);
  375. }
  376. if (notDeviceEndian) {
  377. size_t i;
  378. uint32_t* e = const_cast<uint32_t*>(mEntries);
  379. for (i=0; i<mHeader->stringCount; i++) {
  380. e[i] = dtohl(mEntries[i]);
  381. }
  382. if (!(mHeader->flags&ResStringPool_header::UTF8_FLAG)) {
  383. const char16_t* strings = (const char16_t*)mStrings;
  384. char16_t* s = const_cast<char16_t*>(strings);
  385. for (i=0; i<mStringPoolSize; i++) {
  386. s[i] = dtohs(strings[i]);
  387. }
  388. }
  389. }
  390. if ((mHeader->flags&ResStringPool_header::UTF8_FLAG &&
  391. ((uint8_t*)mStrings)[mStringPoolSize-1] != 0) ||
  392. (!mHeader->flags&ResStringPool_header::UTF8_FLAG &&
  393. ((char16_t*)mStrings)[mStringPoolSize-1] != 0)) {
  394. ALOGW("Bad string block: last string is not 0-terminated\n");
  395. return (mError=BAD_TYPE);
  396. }
  397. } else {
  398. mStrings = NULL;
  399. mStringPoolSize = 0;
  400. }
  401. if (mHeader->styleCount > 0) {
  402. mEntryStyles = mEntries + mHeader->stringCount;
  403. // invariant: integer overflow in calculating mEntryStyles
  404. if (mEntryStyles < mEntries) {
  405. ALOGW("Bad string block: integer overflow finding styles\n");
  406. return (mError=BAD_TYPE);
  407. }
  408. if (((const uint8_t*)mEntryStyles-(const uint8_t*)mHeader) > (int)size) {
  409. ALOGW("Bad string block: entry of %d styles extends past data size %d\n",
  410. (int)((const uint8_t*)mEntryStyles-(const uint8_t*)mHeader),
  411. (int)size);
  412. return (mError=BAD_TYPE);
  413. }
  414. mStyles = (const uint32_t*)
  415. (((const uint8_t*)data)+mHeader->stylesStart);
  416. if (mHeader->stylesStart >= mHeader->header.size) {
  417. ALOGW("Bad string block: style pool starts %d, after total size %d\n",
  418. (int)mHeader->stylesStart, (int)mHeader->header.size);
  419. return (mError=BAD_TYPE);
  420. }
  421. mStylePoolSize =
  422. (mHeader->header.size-mHeader->stylesStart)/sizeof(uint32_t);
  423. if (notDeviceEndian) {
  424. size_t i;
  425. uint32_t* e = const_cast<uint32_t*>(mEntryStyles);
  426. for (i=0; i<mHeader->styleCount; i++) {
  427. e[i] = dtohl(mEntryStyles[i]);
  428. }
  429. uint32_t* s = const_cast<uint32_t*>(mStyles);
  430. for (i=0; i<mStylePoolSize; i++) {
  431. s[i] = dtohl(mStyles[i]);
  432. }
  433. }
  434. const ResStringPool_span endSpan = {
  435. { htodl(ResStringPool_span::END) },
  436. htodl(ResStringPool_span::END), htodl(ResStringPool_span::END)
  437. };
  438. if (memcmp(&mStyles[mStylePoolSize-(sizeof(endSpan)/sizeof(uint32_t))],
  439. &endSpan, sizeof(endSpan)) != 0) {
  440. ALOGW("Bad string block: last style is not 0xFFFFFFFF-terminated\n");
  441. return (mError=BAD_TYPE);
  442. }
  443. } else {
  444. mEntryStyles = NULL;
  445. mStyles = NULL;
  446. mStylePoolSize = 0;
  447. }
  448. return (mError=NO_ERROR);
  449. }
  450. status_t ResStringPool::getError() const
  451. {
  452. return mError;
  453. }
  454. void ResStringPool::uninit()
  455. {
  456. mError = NO_INIT;
  457. if (mOwnedData) {
  458. free(mOwnedData);
  459. mOwnedData = NULL;
  460. }
  461. if (mHeader != NULL && mCache != NULL) {
  462. for (size_t x = 0; x < mHeader->stringCount; x++) {
  463. if (mCache[x] != NULL) {
  464. free(mCache[x]);
  465. mCache[x] = NULL;
  466. }
  467. }
  468. free(mCache);
  469. mCache = NULL;
  470. }
  471. }
  472. /**
  473. * Strings in UTF-16 format have length indicated by a length encoded in the
  474. * stored data. It is either 1 or 2 characters of length data. This allows a
  475. * maximum length of 0x7FFFFFF (2147483647 bytes), but if you're storing that
  476. * much data in a string, you're abusing them.
  477. *
  478. * If the high bit is set, then there are two characters or 4 bytes of length
  479. * data encoded. In that case, drop the high bit of the first character and
  480. * add it together with the next character.
  481. */
  482. static inline size_t
  483. decodeLength(const char16_t** str)
  484. {
  485. size_t len = **str;
  486. if ((len & 0x8000) != 0) {
  487. (*str)++;
  488. len = ((len & 0x7FFF) << 16) | **str;
  489. }
  490. (*str)++;
  491. return len;
  492. }
  493. /**
  494. * Strings in UTF-8 format have length indicated by a length encoded in the
  495. * stored data. It is either 1 or 2 characters of length data. This allows a
  496. * maximum length of 0x7FFF (32767 bytes), but you should consider storing
  497. * text in another way if you're using that much data in a single string.
  498. *
  499. * If the high bit is set, then there are two characters or 2 bytes of length
  500. * data encoded. In that case, drop the high bit of the first character and
  501. * add it together with the next character.
  502. */
  503. static inline size_t
  504. decodeLength(const uint8_t** str)
  505. {
  506. size_t len = **str;
  507. if ((len & 0x80) != 0) {
  508. (*str)++;
  509. len = ((len & 0x7F) << 8) | **str;
  510. }
  511. (*str)++;
  512. return len;
  513. }
  514. const uint16_t* ResStringPool::stringAt(size_t idx, size_t* u16len) const
  515. {
  516. if (mError == NO_ERROR && idx < mHeader->stringCount) {
  517. const bool isUTF8 = (mHeader->flags&ResStringPool_header::UTF8_FLAG) != 0;
  518. const uint32_t off = mEntries[idx]/(isUTF8?sizeof(char):sizeof(char16_t));
  519. if (off < (mStringPoolSize-1)) {
  520. if (!isUTF8) {
  521. const char16_t* strings = (char16_t*)mStrings;
  522. const char16_t* str = strings+off;
  523. *u16len = decodeLength(&str);
  524. if ((uint32_t)(str+*u16len-strings) < mStringPoolSize) {
  525. return str;
  526. } else {
  527. ALOGW("Bad string block: string #%d extends to %d, past end at %d\n",
  528. (int)idx, (int)(str+*u16len-strings), (int)mStringPoolSize);
  529. }
  530. } else {
  531. const uint8_t* strings = (uint8_t*)mStrings;
  532. const uint8_t* u8str = strings+off;
  533. *u16len = decodeLength(&u8str);
  534. size_t u8len = decodeLength(&u8str);
  535. // encLen must be less than 0x7FFF due to encoding.
  536. if ((uint32_t)(u8str+u8len-strings) < mStringPoolSize) {
  537. AutoMutex lock(mDecodeLock);
  538. if (mCache[idx] != NULL) {
  539. return mCache[idx];
  540. }
  541. ssize_t actualLen = utf8_to_utf16_length(u8str, u8len);
  542. if (actualLen < 0 || (size_t)actualLen != *u16len) {
  543. ALOGW("Bad string block: string #%lld decoded length is not correct "
  544. "%lld vs %llu\n",
  545. (long long)idx, (long long)actualLen, (long long)*u16len);
  546. return NULL;
  547. }
  548. char16_t *u16str = (char16_t *)calloc(*u16len+1, sizeof(char16_t));
  549. if (!u16str) {
  550. ALOGW("No memory when trying to allocate decode cache for string #%d\n",
  551. (int)idx);
  552. return NULL;
  553. }
  554. utf8_to_utf16(u8str, u8len, u16str);
  555. mCache[idx] = u16str;
  556. return u16str;
  557. } else {
  558. ALOGW("Bad string block: string #%lld extends to %lld, past end at %lld\n",
  559. (long long)idx, (long long)(u8str+u8len-strings),
  560. (long long)mStringPoolSize);
  561. }
  562. }
  563. } else {
  564. ALOGW("Bad string block: string #%d entry is at %d, past end at %d\n",
  565. (int)idx, (int)(off*sizeof(uint16_t)),
  566. (int)(mStringPoolSize*sizeof(uint16_t)));
  567. }
  568. }
  569. return NULL;
  570. }
  571. const char* ResStringPool::string8At(size_t idx, size_t* outLen) const
  572. {
  573. if (mError == NO_ERROR && idx < mHeader->stringCount) {
  574. const bool isUTF8 = (mHeader->flags&ResStringPool_header::UTF8_FLAG) != 0;
  575. const uint32_t off = mEntries[idx]/(isUTF8?sizeof(char):sizeof(char16_t));
  576. if (off < (mStringPoolSize-1)) {
  577. if (isUTF8) {
  578. const uint8_t* strings = (uint8_t*)mStrings;
  579. const uint8_t* str = strings+off;
  580. *outLen = decodeLength(&str);
  581. size_t encLen = decodeLength(&str);
  582. if ((uint32_t)(str+encLen-strings) < mStringPoolSize) {
  583. return (const char*)str;
  584. } else {
  585. ALOGW("Bad string block: string #%d extends to %d, past end at %d\n",
  586. (int)idx, (int)(str+encLen-strings), (int)mStringPoolSize);
  587. }
  588. }
  589. } else {
  590. ALOGW("Bad string block: string #%d entry is at %d, past end at %d\n",
  591. (int)idx, (int)(off*sizeof(uint16_t)),
  592. (int)(mStringPoolSize*sizeof(uint16_t)));
  593. }
  594. }
  595. return NULL;
  596. }
  597. const String8 ResStringPool::string8ObjectAt(size_t idx) const
  598. {
  599. size_t len;
  600. const char *str = (const char*)string8At(idx, &len);
  601. if (str != NULL) {
  602. return String8(str);
  603. }
  604. return String8(stringAt(idx, &len));
  605. }
  606. const ResStringPool_span* ResStringPool::styleAt(const ResStringPool_ref& ref) const
  607. {
  608. return styleAt(ref.index);
  609. }
  610. const ResStringPool_span* ResStringPool::styleAt(size_t idx) const
  611. {
  612. if (mError == NO_ERROR && idx < mHeader->styleCount) {
  613. const uint32_t off = (mEntryStyles[idx]/sizeof(uint32_t));
  614. if (off < mStylePoolSize) {
  615. return (const ResStringPool_span*)(mStyles+off);
  616. } else {
  617. ALOGW("Bad string block: style #%d entry is at %d, past end at %d\n",
  618. (int)idx, (int)(off*sizeof(uint32_t)),
  619. (int)(mStylePoolSize*sizeof(uint32_t)));
  620. }
  621. }
  622. return NULL;
  623. }
  624. ssize_t ResStringPool::indexOfString(const char16_t* str, size_t strLen) const
  625. {
  626. if (mError != NO_ERROR) {
  627. return mError;
  628. }
  629. size_t len;
  630. // TODO optimize searching for UTF-8 strings taking into account
  631. // the cache fill to determine when to convert the searched-for
  632. // string key to UTF-8.
  633. if (mHeader->flags&ResStringPool_header::SORTED_FLAG) {
  634. // Do a binary search for the string...
  635. ssize_t l = 0;
  636. ssize_t h = mHeader->stringCount-1;
  637. ssize_t mid;
  638. while (l <= h) {
  639. mid = l + (h - l)/2;
  640. const char16_t* s = stringAt(mid, &len);
  641. int c = s ? strzcmp16(s, len, str, strLen) : -1;
  642. POOL_NOISY(printf("Looking for %s, at %s, cmp=%d, l/mid/h=%d/%d/%d\n",
  643. String8(str).string(),
  644. String8(s).string(),
  645. c, (int)l, (int)mid, (int)h));
  646. if (c == 0) {
  647. return mid;
  648. } else if (c < 0) {
  649. l = mid + 1;
  650. } else {
  651. h = mid - 1;
  652. }
  653. }
  654. } else {
  655. // It is unusual to get the ID from an unsorted string block...
  656. // most often this happens because we want to get IDs for style
  657. // span tags; since those always appear at the end of the string
  658. // block, start searching at the back.
  659. for (int i=mHeader->stringCount-1; i>=0; i--) {
  660. const char16_t* s = stringAt(i, &len);
  661. POOL_NOISY(printf("Looking for %s, at %s, i=%d\n",
  662. String8(str, strLen).string(),
  663. String8(s).string(),
  664. i));
  665. if (s && strzcmp16(s, len, str, strLen) == 0) {
  666. return i;
  667. }
  668. }
  669. }
  670. return NAME_NOT_FOUND;
  671. }
  672. size_t ResStringPool::size() const
  673. {
  674. return (mError == NO_ERROR) ? mHeader->stringCount : 0;
  675. }
  676. size_t ResStringPool::styleCount() const
  677. {
  678. return (mError == NO_ERROR) ? mHeader->styleCount : 0;
  679. }
  680. size_t ResStringPool::bytes() const
  681. {
  682. return (mError == NO_ERROR) ? mHeader->header.size : 0;
  683. }
  684. bool ResStringPool::isSorted() const
  685. {
  686. return (mHeader->flags&ResStringPool_header::SORTED_FLAG)!=0;
  687. }
  688. bool ResStringPool::isUTF8() const
  689. {
  690. return (mHeader->flags&ResStringPool_header::UTF8_FLAG)!=0;
  691. }
  692. // --------------------------------------------------------------------
  693. // --------------------------------------------------------------------
  694. // --------------------------------------------------------------------
  695. ResXMLParser::ResXMLParser(const ResXMLTree& tree)
  696. : mTree(tree), mEventCode(BAD_DOCUMENT)
  697. {
  698. }
  699. void ResXMLParser::restart()
  700. {
  701. mCurNode = NULL;
  702. mEventCode = mTree.mError == NO_ERROR ? START_DOCUMENT : BAD_DOCUMENT;
  703. }
  704. const ResStringPool& ResXMLParser::getStrings() const
  705. {
  706. return mTree.mStrings;
  707. }
  708. ResXMLParser::event_code_t ResXMLParser::getEventType() const
  709. {
  710. return mEventCode;
  711. }
  712. ResXMLParser::event_code_t ResXMLParser::next()
  713. {
  714. if (mEventCode == START_DOCUMENT) {
  715. mCurNode = mTree.mRootNode;
  716. mCurExt = mTree.mRootExt;
  717. return (mEventCode=mTree.mRootCode);
  718. } else if (mEventCode >= FIRST_CHUNK_CODE) {
  719. return nextNode();
  720. }
  721. return mEventCode;
  722. }
  723. int32_t ResXMLParser::getCommentID() const
  724. {
  725. return mCurNode != NULL ? dtohl(mCurNode->comment.index) : -1;
  726. }
  727. const uint16_t* ResXMLParser::getComment(size_t* outLen) const
  728. {
  729. int32_t id = getCommentID();
  730. return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
  731. }
  732. uint32_t ResXMLParser::getLineNumber() const
  733. {
  734. return mCurNode != NULL ? dtohl(mCurNode->lineNumber) : -1;
  735. }
  736. int32_t ResXMLParser::getTextID() const
  737. {
  738. if (mEventCode == TEXT) {
  739. return dtohl(((const ResXMLTree_cdataExt*)mCurExt)->data.index);
  740. }
  741. return -1;
  742. }
  743. const uint16_t* ResXMLParser::getText(size_t* outLen) const
  744. {
  745. int32_t id = getTextID();
  746. return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
  747. }
  748. ssize_t ResXMLParser::getTextValue(Res_value* outValue) const
  749. {
  750. if (mEventCode == TEXT) {
  751. outValue->copyFrom_dtoh(((const ResXMLTree_cdataExt*)mCurExt)->typedData);
  752. return sizeof(Res_value);
  753. }
  754. return BAD_TYPE;
  755. }
  756. int32_t ResXMLParser::getNamespacePrefixID() const
  757. {
  758. if (mEventCode == START_NAMESPACE || mEventCode == END_NAMESPACE) {
  759. return dtohl(((const ResXMLTree_namespaceExt*)mCurExt)->prefix.index);
  760. }
  761. return -1;
  762. }
  763. const uint16_t* ResXMLParser::getNamespacePrefix(size_t* outLen) const
  764. {
  765. int32_t id = getNamespacePrefixID();
  766. //printf("prefix=%d event=%p\n", id, mEventCode);
  767. return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
  768. }
  769. int32_t ResXMLParser::getNamespaceUriID() const
  770. {
  771. if (mEventCode == START_NAMESPACE || mEventCode == END_NAMESPACE) {
  772. return dtohl(((const ResXMLTree_namespaceExt*)mCurExt)->uri.index);
  773. }
  774. return -1;
  775. }
  776. const uint16_t* ResXMLParser::getNamespaceUri(size_t* outLen) const
  777. {
  778. int32_t id = getNamespaceUriID();
  779. //printf("uri=%d event=%p\n", id, mEventCode);
  780. return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
  781. }
  782. int32_t ResXMLParser::getElementNamespaceID() const
  783. {
  784. if (mEventCode == START_TAG) {
  785. return dtohl(((const ResXMLTree_attrExt*)mCurExt)->ns.index);
  786. }
  787. if (mEventCode == END_TAG) {
  788. return dtohl(((const ResXMLTree_endElementExt*)mCurExt)->ns.index);
  789. }
  790. return -1;
  791. }
  792. const uint16_t* ResXMLParser::getElementNamespace(size_t* outLen) const
  793. {
  794. int32_t id = getElementNamespaceID();
  795. return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
  796. }
  797. int32_t ResXMLParser::getElementNameID() const
  798. {
  799. if (mEventCode == START_TAG) {
  800. return dtohl(((const ResXMLTree_attrExt*)mCurExt)->name.index);
  801. }
  802. if (mEventCode == END_TAG) {
  803. return dtohl(((const ResXMLTree_endElementExt*)mCurExt)->name.index);
  804. }
  805. return -1;
  806. }
  807. const uint16_t* ResXMLParser::getElementName(size_t* outLen) const
  808. {
  809. int32_t id = getElementNameID();
  810. return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
  811. }
  812. size_t ResXMLParser::getAttributeCount() const
  813. {
  814. if (mEventCode == START_TAG) {
  815. return dtohs(((const ResXMLTree_attrExt*)mCurExt)->attributeCount);
  816. }
  817. return 0;
  818. }
  819. int32_t ResXMLParser::getAttributeNamespaceID(size_t idx) const
  820. {
  821. if (mEventCode == START_TAG) {
  822. const ResXMLTree_attrExt* tag = (const ResXMLTree_attrExt*)mCurExt;
  823. if (idx < dtohs(tag->attributeCount)) {
  824. const ResXMLTree_attribute* attr = (const ResXMLTree_attribute*)
  825. (((const uint8_t*)tag)
  826. + dtohs(tag->attributeStart)
  827. + (dtohs(tag->attributeSize)*idx));
  828. return dtohl(attr->ns.index);
  829. }
  830. }
  831. return -2;
  832. }
  833. const uint16_t* ResXMLParser::getAttributeNamespace(size_t idx, size_t* outLen) const
  834. {
  835. int32_t id = getAttributeNamespaceID(idx);
  836. //printf("attribute namespace=%d idx=%d event=%p\n", id, idx, mEventCode);
  837. //XML_NOISY(printf("getAttributeNamespace 0x%x=0x%x\n", idx, id));
  838. return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
  839. }
  840. int32_t ResXMLParser::getAttributeNameID(size_t idx) const
  841. {
  842. if (mEventCode == START_TAG) {
  843. const ResXMLTree_attrExt* tag = (const ResXMLTree_attrExt*)mCurExt;
  844. if (idx < dtohs(tag->attributeCount)) {
  845. const ResXMLTree_attribute* attr = (const ResXMLTree_attribute*)
  846. (((const uint8_t*)tag)
  847. + dtohs(tag->attributeStart)
  848. + (dtohs(tag->attributeSize)*idx));
  849. return dtohl(attr->name.index);
  850. }
  851. }
  852. return -1;
  853. }
  854. const uint16_t* ResXMLParser::getAttributeName(size_t idx, size_t* outLen) const
  855. {
  856. int32_t id = getAttributeNameID(idx);
  857. //printf("attribute name=%d idx=%d event=%p\n", id, idx, mEventCode);
  858. //XML_NOISY(printf("getAttributeName 0x%x=0x%x\n", idx, id));
  859. return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
  860. }
  861. uint32_t ResXMLParser::getAttributeNameResID(size_t idx) const
  862. {
  863. int32_t id = getAttributeNameID(idx);
  864. if (id >= 0 && (size_t)id < mTree.mNumResIds) {
  865. return dtohl(mTree.mResIds[id]);
  866. }
  867. return 0;
  868. }
  869. int32_t ResXMLParser::getAttributeValueStringID(size_t idx) const
  870. {
  871. if (mEventCode == START_TAG) {
  872. const ResXMLTree_attrExt* tag = (const ResXMLTree_attrExt*)mCurExt;
  873. if (idx < dtohs(tag->attributeCount)) {
  874. const ResXMLTree_attribute* attr = (const ResXMLTree_attribute*)
  875. (((const uint8_t*)tag)
  876. + dtohs(tag->attributeStart)
  877. + (dtohs(tag->attributeSize)*idx));
  878. return dtohl(attr->rawValue.index);
  879. }
  880. }
  881. return -1;
  882. }
  883. const uint16_t* ResXMLParser::getAttributeStringValue(size_t idx, size_t* outLen) const
  884. {
  885. int32_t id = getAttributeValueStringID(idx);
  886. //XML_NOISY(printf("getAttributeValue 0x%x=0x%x\n", idx, id));
  887. return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
  888. }
  889. int32_t ResXMLParser::getAttributeDataType(size_t idx) const
  890. {
  891. if (mEventCode == START_TAG) {
  892. const ResXMLTree_attrExt* tag = (const ResXMLTree_attrExt*)mCurExt;
  893. if (idx < dtohs(tag->attributeCount)) {
  894. const ResXMLTree_attribute* attr = (const ResXMLTree_attribute*)
  895. (((const uint8_t*)tag)
  896. + dtohs(tag->attributeStart)
  897. + (dtohs(tag->attributeSize)*idx));
  898. return attr->typedValue.dataType;
  899. }
  900. }
  901. return Res_value::TYPE_NULL;
  902. }
  903. int32_t ResXMLParser::getAttributeData(size_t idx) const
  904. {
  905. if (mEventCode == START_TAG) {
  906. const ResXMLTree_attrExt* tag = (const ResXMLTree_attrExt*)mCurExt;
  907. if (idx < dtohs(tag->attributeCount)) {
  908. const ResXMLTree_attribute* attr = (const ResXMLTree_attribute*)
  909. (((const uint8_t*)tag)
  910. + dtohs(tag->attributeStart)
  911. + (dtohs(tag->attributeSize)*idx));
  912. return dtohl(attr->typedValue.data);
  913. }
  914. }
  915. return 0;
  916. }
  917. ssize_t ResXMLParser::getAttributeValue(size_t idx, Res_value* outValue) const
  918. {
  919. if (mEventCode == START_TAG) {
  920. const ResXMLTree_attrExt* tag = (const ResXMLTree_attrExt*)mCurExt;
  921. if (idx < dtohs(tag->attributeCount)) {
  922. const ResXMLTree_attribute* attr = (const ResXMLTree_attribute*)
  923. (((const uint8_t*)tag)
  924. + dtohs(tag->attributeStart)
  925. + (dtohs(tag->attributeSize)*idx));
  926. outValue->copyFrom_dtoh(attr->typedValue);
  927. return sizeof(Res_value);
  928. }
  929. }
  930. return BAD_TYPE;
  931. }
  932. ssize_t ResXMLParser::indexOfAttribute(const char* ns, const char* attr) const
  933. {
  934. String16 nsStr(ns != NULL ? ns : "");
  935. String16 attrStr(attr);
  936. return indexOfAttribute(ns ? nsStr.string() : NULL, ns ? nsStr.size() : 0,
  937. attrStr.string(), attrStr.size());
  938. }
  939. ssize_t ResXMLParser::indexOfAttribute(const char16_t* ns, size_t nsLen,
  940. const char16_t* attr, size_t attrLen) const
  941. {
  942. if (mEventCode == START_TAG) {
  943. const size_t N = getAttributeCount();
  944. for (size_t i=0; i<N; i++) {
  945. size_t curNsLen, curAttrLen;
  946. const char16_t* curNs = getAttributeNamespace(i, &curNsLen);
  947. const char16_t* curAttr = getAttributeName(i, &curAttrLen);
  948. //printf("%d: ns=%p attr=%p curNs=%p curAttr=%p\n",
  949. // i, ns, attr, curNs, curAttr);
  950. //printf(" --> attr=%s, curAttr=%s\n",
  951. // String8(attr).string(), String8(curAttr).string());
  952. if (attr && curAttr && (strzcmp16(attr, attrLen, curAttr, curAttrLen) == 0)) {
  953. if (ns == NULL) {
  954. if (curNs == NULL) return i;
  955. } else if (curNs != NULL) {
  956. //printf(" --> ns=%s, curNs=%s\n",
  957. // String8(ns).string(), String8(curNs).string());
  958. if (strzcmp16(ns, nsLen, curNs, curNsLen) == 0) return i;
  959. }
  960. }
  961. }
  962. }
  963. return NAME_NOT_FOUND;
  964. }
  965. ssize_t ResXMLParser::indexOfID() const
  966. {
  967. if (mEventCode == START_TAG) {
  968. const ssize_t idx = dtohs(((const ResXMLTree_attrExt*)mCurExt)->idIndex);
  969. if (idx > 0) return (idx-1);
  970. }
  971. return NAME_NOT_FOUND;
  972. }
  973. ssize_t ResXMLParser::indexOfClass() const
  974. {
  975. if (mEventCode == START_TAG) {
  976. const ssize_t idx = dtohs(((const ResXMLTree_attrExt*)mCurExt)->classIndex);
  977. if (idx > 0) return (idx-1);
  978. }
  979. return NAME_NOT_FOUND;
  980. }
  981. ssize_t ResXMLParser::indexOfStyle() const
  982. {
  983. if (mEventCode == START_TAG) {
  984. const ssize_t idx = dtohs(((const ResXMLTree_attrExt*)mCurExt)->styleIndex);
  985. if (idx > 0) return (idx-1);
  986. }
  987. return NAME_NOT_FOUND;
  988. }
  989. ResXMLParser::event_code_t ResXMLParser::nextNode()
  990. {
  991. if (mEventCode < 0) {
  992. return mEventCode;
  993. }
  994. do {
  995. const ResXMLTree_node* next = (const ResXMLTree_node*)
  996. (((const uint8_t*)mCurNode) + dtohl(mCurNode->header.size));
  997. //ALOGW("Next node: prev=%p, next=%p\n", mCurNode, next);
  998. if (((const uint8_t*)next) >= mTree.mDataEnd) {
  999. mCurNode = NULL;
  1000. return (mEventCode=END_DOCUMENT);
  1001. }
  1002. if (mTree.validateNode(next) != NO_ERROR) {
  1003. mCurNode = NULL;
  1004. return (mEventCode=BAD_DOCUMENT);
  1005. }
  1006. mCurNode = next;
  1007. const uint16_t headerSize = dtohs(next->header.headerSize);
  1008. const uint32_t totalSize = dtohl(next->header.size);
  1009. mCurExt = ((const uint8_t*)next) + headerSize;
  1010. size_t minExtSize = 0;
  1011. event_code_t eventCode = (event_code_t)dtohs(next->header.type);
  1012. switch ((mEventCode=eventCode)) {
  1013. case RES_XML_START_NAMESPACE_TYPE:
  1014. case RES_XML_END_NAMESPACE_TYPE:
  1015. minExtSize = sizeof(ResXMLTree_namespaceExt);
  1016. break;
  1017. case RES_XML_START_ELEMENT_TYPE:
  1018. minExtSize = sizeof(ResXMLTree_attrExt);
  1019. break;
  1020. case RES_XML_END_ELEMENT_TYPE:
  1021. minExtSize = sizeof(ResXMLTree_endElementExt);
  1022. break;
  1023. case RES_XML_CDATA_TYPE:
  1024. minExtSize = sizeof(ResXMLTree_cdataExt);
  1025. break;
  1026. default:
  1027. ALOGW("Unknown XML block: header type %d in node at %d\n",
  1028. (int)dtohs(next->header.type),
  1029. (int)(((const uint8_t*)next)-((const uint8_t*)mTree.mHeader)));
  1030. continue;
  1031. }
  1032. if ((totalSize-headerSize) < minExtSize) {
  1033. ALOGW("Bad XML block: header type 0x%x in node at 0x%x has size %d, need %d\n",
  1034. (int)dtohs(next->header.type),
  1035. (int)(((const uint8_t*)next)-((const uint8_t*)mTree.mHeader)),
  1036. (int)(totalSize-headerSize), (int)minExtSize);
  1037. return (mEventCode=BAD_DOCUMENT);
  1038. }
  1039. //printf("CurNode=%p, CurExt=%p, headerSize=%d, minExtSize=%d\n",
  1040. // mCurNode, mCurExt, headerSize, minExtSize);
  1041. return eventCode;
  1042. } while (true);
  1043. }
  1044. void ResXMLParser::getPosition(ResXMLParser::ResXMLPosition* pos) const
  1045. {
  1046. pos->eventCode = mEventCode;
  1047. pos->curNode = mCurNode;
  1048. pos->curExt = mCurExt;
  1049. }
  1050. void ResXMLParser::setPosition(const ResXMLParser::ResXMLPosition& pos)
  1051. {
  1052. mEventCode = pos.eventCode;
  1053. mCurNode = pos.curNode;
  1054. mCurExt = pos.curExt;
  1055. }
  1056. // --------------------------------------------------------------------
  1057. static volatile int32_t gCount = 0;
  1058. ResXMLTree::ResXMLTree()
  1059. : ResXMLParser(*this)
  1060. , mError(NO_INIT), mOwnedData(NULL)
  1061. {
  1062. //ALOGI("Creating ResXMLTree %p #%d\n", this, android_atomic_inc(&gCount)+1);
  1063. restart();
  1064. }
  1065. ResXMLTree::ResXMLTree(const void* data, size_t size, bool copyData)
  1066. : ResXMLParser(*this)
  1067. , mError(NO_INIT), mOwnedData(NULL)
  1068. {
  1069. //ALOGI("Creating ResXMLTree %p #%d\n", this, android_atomic_inc(&gCount)+1);
  1070. setTo(data, size, copyData);
  1071. }
  1072. ResXMLTree::~ResXMLTree()
  1073. {
  1074. //ALOGI("Destroying ResXMLTree in %p #%d\n", this, android_atomic_dec(&gCount)-1);
  1075. uninit();
  1076. }
  1077. status_t ResXMLTree::setTo(const void* data, size_t size, bool copyData)
  1078. {
  1079. uninit();
  1080. mEventCode = START_DOCUMENT;
  1081. if (copyData) {
  1082. mOwnedData = malloc(size);
  1083. if (mOwnedData == NULL) {
  1084. return (mError=NO_MEMORY);
  1085. }
  1086. memcpy(mOwnedData, data, size);
  1087. data = mOwnedData;
  1088. }
  1089. mHeader = (const ResXMLTree_header*)data;
  1090. mSize = dtohl(mHeader->header.size);
  1091. if (dtohs(mHeader->header.headerSize) > mSize || mSize > size) {
  1092. ALOGW("Bad XML block: header size %d or total size %d is larger than data size %d\n",
  1093. (int)dtohs(mHeader->header.headerSize),
  1094. (int)dtohl(mHeader->header.size), (int)size);
  1095. mError = BAD_TYPE;
  1096. restart();
  1097. return mError;
  1098. }
  1099. mDataEnd = ((const uint8_t*)mHeader) + mSize;
  1100. mStrings.uninit();
  1101. mRootNode = NULL;
  1102. mResIds = NULL;
  1103. mNumResIds = 0;
  1104. // First look for a couple interesting chunks: the string block
  1105. // and first XML node.
  1106. const ResChunk_header* chunk =
  1107. (const ResChunk_header*)(((const uint8_t*)mHeader) + dtohs(mHeader->header.headerSize));
  1108. const ResChunk_header* lastChunk = chunk;
  1109. while (((const uint8_t*)chunk) < (mDataEnd-sizeof(ResChunk_header)) &&
  1110. ((const uint8_t*)chunk) < (mDataEnd-dtohl(chunk->size))) {
  1111. status_t err = validate_chunk(chunk, sizeof(ResChunk_header), mDataEnd, "XML");
  1112. if (err != NO_ERROR) {
  1113. mError = err;
  1114. goto done;
  1115. }
  1116. const uint16_t type = dtohs(chunk->type);
  1117. const size_t size = dtohl(chunk->size);
  1118. XML_NOISY(printf("Scanning @ %p: type=0x%x, size=0x%x\n",
  1119. (void*)(((uint32_t)chunk)-((uint32_t)mHeader)), type, size));
  1120. if (type == RES_STRING_POOL_TYPE) {
  1121. mStrings.setTo(chunk, size);
  1122. } else if (type == RES_XML_RESOURCE_MAP_TYPE) {
  1123. mResIds = (const uint32_t*)
  1124. (((const uint8_t*)chunk)+dtohs(chunk->headerSize));
  1125. mNumResIds = (dtohl(chunk->size)-dtohs(chunk->headerSize))/sizeof(uint32_t);
  1126. } else if (type >= RES_XML_FIRST_CHUNK_TYPE
  1127. && type <= RES_XML_LAST_CHUNK_TYPE) {
  1128. if (validateNode((const ResXMLTree_node*)chunk) != NO_ERROR) {
  1129. mError = BAD_TYPE;
  1130. goto done;
  1131. }
  1132. mCurNode = (const ResXMLTree_node*)lastChunk;
  1133. if (nextNode() == BAD_DOCUMENT) {
  1134. mError = BAD_TYPE;
  1135. goto done;
  1136. }
  1137. mRootNode = mCurNode;
  1138. mRootExt = mCurExt;
  1139. mRootCode = mEventCode;
  1140. break;
  1141. } else {
  1142. XML_NOISY(printf("Skipping unknown chunk!\n"));
  1143. }
  1144. lastChunk = chunk;
  1145. chunk = (const ResChunk_header*)
  1146. (((const uint8_t*)chunk) + size);
  1147. }
  1148. if (mRootNode == NULL) {
  1149. ALOGW("Bad XML block: no root element node found\n");
  1150. mError = BAD_TYPE;
  1151. goto done;
  1152. }
  1153. mError = mStrings.getError();
  1154. done:
  1155. restart();
  1156. return mError;
  1157. }
  1158. status_t ResXMLTree::getError() const
  1159. {
  1160. return mError;
  1161. }
  1162. void ResXMLTree::uninit()
  1163. {
  1164. mError = NO_INIT;
  1165. mStrings.uninit();
  1166. if (mOwnedData) {
  1167. free(mOwnedData);
  1168. mOwnedData = NULL;
  1169. }
  1170. restart();
  1171. }
  1172. status_t ResXMLTree::validateNode(const ResXMLTree_node* node) const
  1173. {
  1174. const uint16_t eventCode = dtohs(node->header.type);
  1175. status_t err = validate_chunk(
  1176. &node->header, sizeof(ResXMLTree_node),
  1177. mDataEnd, "ResXMLTree_node");
  1178. if (err >= NO_ERROR) {
  1179. // Only perform additional validation on START nodes
  1180. if (eventCode != RES_XML_START_ELEMENT_TYPE) {
  1181. return NO_ERROR;
  1182. }
  1183. const uint16_t headerSize = dtohs(node->header.headerSize);
  1184. const uint32_t size = dtohl(node->header.size);
  1185. const ResXMLTree_attrExt* attrExt = (const ResXMLTree_attrExt*)
  1186. (((const uint8_t*)node) + headerSize);
  1187. // check for sensical values pulled out of the stream so far...
  1188. if ((size >= headerSize + sizeof(ResXMLTree_attrExt))
  1189. && ((void*)attrExt > (void*)node)) {
  1190. const size_t attrSize = ((size_t)dtohs(attrExt->attributeSize))
  1191. * dtohs(attrExt->attributeCount);
  1192. if ((dtohs(attrExt->attributeStart)+attrSize) <= (size-headerSize)) {
  1193. return NO_ERROR;
  1194. }
  1195. ALOGW("Bad XML block: node attributes use 0x%x bytes, only have 0x%x bytes\n",
  1196. (unsigned int)(dtohs(attrExt->attributeStart)+attrSize),
  1197. (unsigned int)(size-headerSize));
  1198. }
  1199. else {
  1200. ALOGW("Bad XML start block: node header size 0x%x, size 0x%x\n",
  1201. (unsigned int)headerSize, (unsigned int)size);
  1202. }
  1203. return BAD_TYPE;
  1204. }
  1205. return err;
  1206. #if 0
  1207. const bool isStart = dtohs(node->header.type) == RES_XML_START_ELEMENT_TYPE;
  1208. const uint16_t headerSize = dtohs(node->header.headerSize);
  1209. const uint32_t size = dtohl(node->header.size);
  1210. if (headerSize >= (isStart ? sizeof(ResXMLTree_attrNode) : sizeof(ResXMLTree_node))) {
  1211. if (size >= headerSize) {
  1212. if (((const uint8_t*)node) <= (mDataEnd-size)) {
  1213. if (!isStart) {
  1214. return NO_ERROR;
  1215. }
  1216. if ((((size_t)dtohs(node->attributeSize))*dtohs(node->attributeCount))
  1217. <= (size-headerSize)) {
  1218. return NO_ERROR;
  1219. }
  1220. ALOGW("Bad XML block: node attributes use 0x%x bytes, only have 0x%x bytes\n",
  1221. ((int)dtohs(node->attributeSize))*dtohs(node->attributeCount),
  1222. (int)(size-headerSize));
  1223. return BAD_TYPE;
  1224. }
  1225. ALOGW("Bad XML block: node at 0x%x extends beyond data end 0x%x\n",
  1226. (int)(((const uint8_t*)node)-((const uint8_t*)mHeader)), (int)mSize);
  1227. return BAD_TYPE;
  1228. }
  1229. ALOGW("Bad XML block: node at 0x%x header size 0x%x smaller than total size 0x%x\n",
  1230. (int)(((const uint8_t*)node)-((const uint8_t*)mHeader)),
  1231. (int)headerSize, (int)size);
  1232. return BAD_TYPE;
  1233. }
  1234. ALOGW("Bad XML block: node at 0x%x header size 0x%x too small\n",
  1235. (int)(((const uint8_t*)node)-((const uint8_t*)mHeader)),
  1236. (int)headerSize);
  1237. return BAD_TYPE;
  1238. #endif
  1239. }
  1240. // --------------------------------------------------------------------
  1241. // --------------------------------------------------------------------
  1242. // --------------------------------------------------------------------
  1243. void ResTable_config::copyFromDeviceNoSwap(const ResTable_config& o) {
  1244. const size_t size = dtohl(o.size);
  1245. if (size >= sizeof(ResTable_config)) {
  1246. *this = o;
  1247. } else {
  1248. memcpy(this, &o, size);
  1249. memset(((uint8_t*)this)+size, 0, sizeof(ResTable_config)-size);
  1250. }
  1251. }
  1252. void ResTable_config::copyFromDtoH(const ResTable_config& o) {
  1253. copyFromDeviceNoSwap(o);
  1254. size = sizeof(ResTable_config);
  1255. mcc = dtohs(mcc);
  1256. mnc = dtohs(mnc);
  1257. density = dtohs(density);
  1258. screenWidth = dtohs(screenWidth);
  1259. screenHeight = dtohs(screenHeight);
  1260. sdkVersion = dtohs(sdkVersion);
  1261. minorVersion = dtohs(minorVersion);
  1262. smallestScreenWidthDp = dtohs(smallestScreenWidthDp);
  1263. screenWidthDp = dtohs(screenWidthDp);
  1264. screenHeightDp = dtohs(screenHeightDp);
  1265. }
  1266. void ResTable_config::swapHtoD() {
  1267. size = htodl(size);
  1268. mcc = htods(mcc);
  1269. mnc = htods(mnc);
  1270. density = htods(density);
  1271. screenWidth = htods(screenWidth);
  1272. screenHeight = htods(screenHeight);
  1273. sdkVersion = htods(sdkVersion);
  1274. minorVersion = htods(minorVersion);
  1275. smallestScreenWidthDp = htods(smallestScreenWidthDp);
  1276. screenWidthDp = htods(screenWidthDp);
  1277. screenHeightDp = htods(screenHeightDp);
  1278. }
  1279. int ResTable_config::compare(const ResTable_config& o) const {
  1280. int32_t diff = (int32_t)(imsi - o.imsi);
  1281. if (diff != 0) return diff;
  1282. diff = (int32_t)(locale - o.locale);
  1283. if (diff != 0) return diff;
  1284. diff = (int32_t)(screenType - o.screenType);
  1285. if (diff != 0) return diff;
  1286. diff = (int32_t)(input - o.input);
  1287. if (diff != 0) return diff;
  1288. diff = (int32_t)(screenSize - o.screenSize);
  1289. if (diff != 0) return diff;
  1290. diff = (int32_t)(version - o.version);
  1291. if (diff != 0) return diff;
  1292. diff = (int32_t)(screenLayout - o.screenLayout);
  1293. if (diff != 0) return diff;
  1294. diff = (int32_t)(uiMode - o.uiMode);
  1295. if (diff != 0) return diff;
  1296. diff = (int32_t)(smallestScreenWidthDp - o.smallestScreenWidthDp);
  1297. if (diff != 0) return diff;
  1298. diff = (int32_t)(screenSizeDp - o.screenSizeDp);
  1299. return (int)diff;
  1300. }
  1301. int ResTable_config::compareLogical(const ResTable_config& o) const {
  1302. if (mcc != o.mcc) {
  1303. return mcc < o.mcc ? -1 : 1;
  1304. }
  1305. if (mnc != o.mnc) {
  1306. return mnc < o.mnc ? -1 : 1;
  1307. }
  1308. if (language[0] != o.language[0]) {
  1309. return language[0] < o.language[0] ? -1 : 1;
  1310. }
  1311. if (language[1] != o.language[1]) {
  1312. return language[1] < o.language[1] ? -1 : 1;
  1313. }
  1314. if (country[0] != o.country[0]) {
  1315. return country[0] < o.country[0] ? -1 : 1;
  1316. }
  1317. if (country[1] != o.country[1]) {
  1318. return country[1] < o.country[1] ? -1 : 1;
  1319. }
  1320. if ((screenLayout & MASK_LAYOUTDIR) != (o.screenLayout & MASK_LAYOUTDIR)) {
  1321. return (screenLayout & MASK_LAYOUTDIR) < (o.screenLayou