PageRenderTime 56ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/external/android/utils/ResourceTypes.cpp

https://bitbucket.org/festevezga/xobotos
C++ | 1465 lines | 1210 code | 155 blank | 100 comment | 267 complexity | ed4d28525177b46eef3d1d4b21b5938f 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 <utils/Atomic.h>
  19. #include <utils/ByteOrder.h>
  20. #include <utils/Debug.h>
  21. #include <utils/ResourceTypes.h>
  22. #include <utils/String16.h>
  23. #include <utils/String8.h>
  24. #include <utils/TextOutput.h>
  25. #include <utils/Log.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. LOGV("%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. LOGW("%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. LOGW("%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. LOGW("%s size %p is smaller than header size %p.",
  106. name, (void*)size, (void*)(int)headerSize);
  107. return BAD_TYPE;
  108. }
  109. LOGW("%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. LOGW("idmap assertion failed: size=%d bytes\n", sizeBytes);
  202. return false;
  203. }
  204. if (*map != htodl(IDMAP_MAGIC)) { // htodl: map data expected to be in correct endianess
  205. LOGW("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. LOGW("Resource ID map: type=%d exceeds number of types=%d\n", type, typeCount);
  225. return UNKNOWN_ERROR;
  226. }
  227. if (typeCount > size) {
  228. LOGW("Resource ID map: number of types=%d exceeds size of map=%d\n", typeCount, 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. LOGW("Resource ID map: type offset=%d exceeds reasonable value, size of map=%d\n",
  238. typeOffset, 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. LOGW("Resource ID map: entry index=%d exceeds size of map=%d\n", index, 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. LOGE("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. LOGW("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. LOGW("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**)malloc(sizeof(char16_t**)*mHeader->stringCount);
  342. memset(mCache, 0, sizeof(char16_t**)*mHeader->stringCount);
  343. } else {
  344. charSize = sizeof(char16_t);
  345. }
  346. mStrings = (const void*)
  347. (((const uint8_t*)data)+mHeader->stringsStart);
  348. if (mHeader->stringsStart >= (mHeader->header.size-sizeof(uint16_t))) {
  349. LOGW("Bad string block: string pool starts at %d, after total size %d\n",
  350. (int)mHeader->stringsStart, (int)mHeader->header.size);
  351. return (mError=BAD_TYPE);
  352. }
  353. if (mHeader->styleCount == 0) {
  354. mStringPoolSize =
  355. (mHeader->header.size-mHeader->stringsStart)/charSize;
  356. } else {
  357. // check invariant: styles starts before end of data
  358. if (mHeader->stylesStart >= (mHeader->header.size-sizeof(uint16_t))) {
  359. LOGW("Bad style block: style block starts at %d past data size of %d\n",
  360. (int)mHeader->stylesStart, (int)mHeader->header.size);
  361. return (mError=BAD_TYPE);
  362. }
  363. // check invariant: styles follow the strings
  364. if (mHeader->stylesStart <= mHeader->stringsStart) {
  365. LOGW("Bad style block: style block starts at %d, before strings at %d\n",
  366. (int)mHeader->stylesStart, (int)mHeader->stringsStart);
  367. return (mError=BAD_TYPE);
  368. }
  369. mStringPoolSize =
  370. (mHeader->stylesStart-mHeader->stringsStart)/charSize;
  371. }
  372. // check invariant: stringCount > 0 requires a string pool to exist
  373. if (mStringPoolSize == 0) {
  374. LOGW("Bad string block: stringCount is %d but pool size is 0\n", (int)mHeader->stringCount);
  375. return (mError=BAD_TYPE);
  376. }
  377. if (notDeviceEndian) {
  378. size_t i;
  379. uint32_t* e = const_cast<uint32_t*>(mEntries);
  380. for (i=0; i<mHeader->stringCount; i++) {
  381. e[i] = dtohl(mEntries[i]);
  382. }
  383. if (!(mHeader->flags&ResStringPool_header::UTF8_FLAG)) {
  384. const char16_t* strings = (const char16_t*)mStrings;
  385. char16_t* s = const_cast<char16_t*>(strings);
  386. for (i=0; i<mStringPoolSize; i++) {
  387. s[i] = dtohs(strings[i]);
  388. }
  389. }
  390. }
  391. if ((mHeader->flags&ResStringPool_header::UTF8_FLAG &&
  392. ((uint8_t*)mStrings)[mStringPoolSize-1] != 0) ||
  393. (!mHeader->flags&ResStringPool_header::UTF8_FLAG &&
  394. ((char16_t*)mStrings)[mStringPoolSize-1] != 0)) {
  395. LOGW("Bad string block: last string is not 0-terminated\n");
  396. return (mError=BAD_TYPE);
  397. }
  398. } else {
  399. mStrings = NULL;
  400. mStringPoolSize = 0;
  401. }
  402. if (mHeader->styleCount > 0) {
  403. mEntryStyles = mEntries + mHeader->stringCount;
  404. // invariant: integer overflow in calculating mEntryStyles
  405. if (mEntryStyles < mEntries) {
  406. LOGW("Bad string block: integer overflow finding styles\n");
  407. return (mError=BAD_TYPE);
  408. }
  409. if (((const uint8_t*)mEntryStyles-(const uint8_t*)mHeader) > (int)size) {
  410. LOGW("Bad string block: entry of %d styles extends past data size %d\n",
  411. (int)((const uint8_t*)mEntryStyles-(const uint8_t*)mHeader),
  412. (int)size);
  413. return (mError=BAD_TYPE);
  414. }
  415. mStyles = (const uint32_t*)
  416. (((const uint8_t*)data)+mHeader->stylesStart);
  417. if (mHeader->stylesStart >= mHeader->header.size) {
  418. LOGW("Bad string block: style pool starts %d, after total size %d\n",
  419. (int)mHeader->stylesStart, (int)mHeader->header.size);
  420. return (mError=BAD_TYPE);
  421. }
  422. mStylePoolSize =
  423. (mHeader->header.size-mHeader->stylesStart)/sizeof(uint32_t);
  424. if (notDeviceEndian) {
  425. size_t i;
  426. uint32_t* e = const_cast<uint32_t*>(mEntryStyles);
  427. for (i=0; i<mHeader->styleCount; i++) {
  428. e[i] = dtohl(mEntryStyles[i]);
  429. }
  430. uint32_t* s = const_cast<uint32_t*>(mStyles);
  431. for (i=0; i<mStylePoolSize; i++) {
  432. s[i] = dtohl(mStyles[i]);
  433. }
  434. }
  435. const ResStringPool_span endSpan = {
  436. { htodl(ResStringPool_span::END) },
  437. htodl(ResStringPool_span::END), htodl(ResStringPool_span::END)
  438. };
  439. if (memcmp(&mStyles[mStylePoolSize-(sizeof(endSpan)/sizeof(uint32_t))],
  440. &endSpan, sizeof(endSpan)) != 0) {
  441. LOGW("Bad string block: last style is not 0xFFFFFFFF-terminated\n");
  442. return (mError=BAD_TYPE);
  443. }
  444. } else {
  445. mEntryStyles = NULL;
  446. mStyles = NULL;
  447. mStylePoolSize = 0;
  448. }
  449. return (mError=NO_ERROR);
  450. }
  451. status_t ResStringPool::getError() const
  452. {
  453. return mError;
  454. }
  455. void ResStringPool::uninit()
  456. {
  457. mError = NO_INIT;
  458. if (mOwnedData) {
  459. free(mOwnedData);
  460. mOwnedData = NULL;
  461. }
  462. if (mHeader != NULL && mCache != NULL) {
  463. for (size_t x = 0; x < mHeader->stringCount; x++) {
  464. if (mCache[x] != NULL) {
  465. free(mCache[x]);
  466. mCache[x] = NULL;
  467. }
  468. }
  469. free(mCache);
  470. mCache = NULL;
  471. }
  472. }
  473. /**
  474. * Strings in UTF-16 format have length indicated by a length encoded in the
  475. * stored data. It is either 1 or 2 characters of length data. This allows a
  476. * maximum length of 0x7FFFFFF (2147483647 bytes), but if you're storing that
  477. * much data in a string, you're abusing them.
  478. *
  479. * If the high bit is set, then there are two characters or 4 bytes of length
  480. * data encoded. In that case, drop the high bit of the first character and
  481. * add it together with the next character.
  482. */
  483. static inline size_t
  484. decodeLength(const char16_t** str)
  485. {
  486. size_t len = **str;
  487. if ((len & 0x8000) != 0) {
  488. (*str)++;
  489. len = ((len & 0x7FFF) << 16) | **str;
  490. }
  491. (*str)++;
  492. return len;
  493. }
  494. /**
  495. * Strings in UTF-8 format have length indicated by a length encoded in the
  496. * stored data. It is either 1 or 2 characters of length data. This allows a
  497. * maximum length of 0x7FFF (32767 bytes), but you should consider storing
  498. * text in another way if you're using that much data in a single string.
  499. *
  500. * If the high bit is set, then there are two characters or 2 bytes of length
  501. * data encoded. In that case, drop the high bit of the first character and
  502. * add it together with the next character.
  503. */
  504. static inline size_t
  505. decodeLength(const uint8_t** str)
  506. {
  507. size_t len = **str;
  508. if ((len & 0x80) != 0) {
  509. (*str)++;
  510. len = ((len & 0x7F) << 8) | **str;
  511. }
  512. (*str)++;
  513. return len;
  514. }
  515. const uint16_t* ResStringPool::stringAt(size_t idx, size_t* u16len) const
  516. {
  517. if (mError == NO_ERROR && idx < mHeader->stringCount) {
  518. const bool isUTF8 = (mHeader->flags&ResStringPool_header::UTF8_FLAG) != 0;
  519. const uint32_t off = mEntries[idx]/(isUTF8?sizeof(char):sizeof(char16_t));
  520. if (off < (mStringPoolSize-1)) {
  521. if (!isUTF8) {
  522. const char16_t* strings = (char16_t*)mStrings;
  523. const char16_t* str = strings+off;
  524. *u16len = decodeLength(&str);
  525. if ((uint32_t)(str+*u16len-strings) < mStringPoolSize) {
  526. return str;
  527. } else {
  528. LOGW("Bad string block: string #%d extends to %d, past end at %d\n",
  529. (int)idx, (int)(str+*u16len-strings), (int)mStringPoolSize);
  530. }
  531. } else {
  532. const uint8_t* strings = (uint8_t*)mStrings;
  533. const uint8_t* u8str = strings+off;
  534. *u16len = decodeLength(&u8str);
  535. size_t u8len = decodeLength(&u8str);
  536. // encLen must be less than 0x7FFF due to encoding.
  537. if ((uint32_t)(u8str+u8len-strings) < mStringPoolSize) {
  538. AutoMutex lock(mDecodeLock);
  539. if (mCache[idx] != NULL) {
  540. return mCache[idx];
  541. }
  542. ssize_t actualLen = utf8_to_utf16_length(u8str, u8len);
  543. if (actualLen < 0 || (size_t)actualLen != *u16len) {
  544. LOGW("Bad string block: string #%lld decoded length is not correct "
  545. "%lld vs %llu\n",
  546. (long long)idx, (long long)actualLen, (long long)*u16len);
  547. return NULL;
  548. }
  549. char16_t *u16str = (char16_t *)calloc(*u16len+1, sizeof(char16_t));
  550. if (!u16str) {
  551. LOGW("No memory when trying to allocate decode cache for string #%d\n",
  552. (int)idx);
  553. return NULL;
  554. }
  555. utf8_to_utf16(u8str, u8len, u16str);
  556. mCache[idx] = u16str;
  557. return u16str;
  558. } else {
  559. LOGW("Bad string block: string #%lld extends to %lld, past end at %lld\n",
  560. (long long)idx, (long long)(u8str+u8len-strings),
  561. (long long)mStringPoolSize);
  562. }
  563. }
  564. } else {
  565. LOGW("Bad string block: string #%d entry is at %d, past end at %d\n",
  566. (int)idx, (int)(off*sizeof(uint16_t)),
  567. (int)(mStringPoolSize*sizeof(uint16_t)));
  568. }
  569. }
  570. return NULL;
  571. }
  572. const char* ResStringPool::string8At(size_t idx, size_t* outLen) const
  573. {
  574. if (mError == NO_ERROR && idx < mHeader->stringCount) {
  575. const bool isUTF8 = (mHeader->flags&ResStringPool_header::UTF8_FLAG) != 0;
  576. const uint32_t off = mEntries[idx]/(isUTF8?sizeof(char):sizeof(char16_t));
  577. if (off < (mStringPoolSize-1)) {
  578. if (isUTF8) {
  579. const uint8_t* strings = (uint8_t*)mStrings;
  580. const uint8_t* str = strings+off;
  581. *outLen = decodeLength(&str);
  582. size_t encLen = decodeLength(&str);
  583. if ((uint32_t)(str+encLen-strings) < mStringPoolSize) {
  584. return (const char*)str;
  585. } else {
  586. LOGW("Bad string block: string #%d extends to %d, past end at %d\n",
  587. (int)idx, (int)(str+encLen-strings), (int)mStringPoolSize);
  588. }
  589. }
  590. } else {
  591. LOGW("Bad string block: string #%d entry is at %d, past end at %d\n",
  592. (int)idx, (int)(off*sizeof(uint16_t)),
  593. (int)(mStringPoolSize*sizeof(uint16_t)));
  594. }
  595. }
  596. return NULL;
  597. }
  598. const ResStringPool_span* ResStringPool::styleAt(const ResStringPool_ref& ref) const
  599. {
  600. return styleAt(ref.index);
  601. }
  602. const ResStringPool_span* ResStringPool::styleAt(size_t idx) const
  603. {
  604. if (mError == NO_ERROR && idx < mHeader->styleCount) {
  605. const uint32_t off = (mEntryStyles[idx]/sizeof(uint32_t));
  606. if (off < mStylePoolSize) {
  607. return (const ResStringPool_span*)(mStyles+off);
  608. } else {
  609. LOGW("Bad string block: style #%d entry is at %d, past end at %d\n",
  610. (int)idx, (int)(off*sizeof(uint32_t)),
  611. (int)(mStylePoolSize*sizeof(uint32_t)));
  612. }
  613. }
  614. return NULL;
  615. }
  616. ssize_t ResStringPool::indexOfString(const char16_t* str, size_t strLen) const
  617. {
  618. if (mError != NO_ERROR) {
  619. return mError;
  620. }
  621. size_t len;
  622. // TODO optimize searching for UTF-8 strings taking into account
  623. // the cache fill to determine when to convert the searched-for
  624. // string key to UTF-8.
  625. if (mHeader->flags&ResStringPool_header::SORTED_FLAG) {
  626. // Do a binary search for the string...
  627. ssize_t l = 0;
  628. ssize_t h = mHeader->stringCount-1;
  629. ssize_t mid;
  630. while (l <= h) {
  631. mid = l + (h - l)/2;
  632. const char16_t* s = stringAt(mid, &len);
  633. int c = s ? strzcmp16(s, len, str, strLen) : -1;
  634. POOL_NOISY(printf("Looking for %s, at %s, cmp=%d, l/mid/h=%d/%d/%d\n",
  635. String8(str).string(),
  636. String8(s).string(),
  637. c, (int)l, (int)mid, (int)h));
  638. if (c == 0) {
  639. return mid;
  640. } else if (c < 0) {
  641. l = mid + 1;
  642. } else {
  643. h = mid - 1;
  644. }
  645. }
  646. } else {
  647. // It is unusual to get the ID from an unsorted string block...
  648. // most often this happens because we want to get IDs for style
  649. // span tags; since those always appear at the end of the string
  650. // block, start searching at the back.
  651. for (int i=mHeader->stringCount-1; i>=0; i--) {
  652. const char16_t* s = stringAt(i, &len);
  653. POOL_NOISY(printf("Looking for %s, at %s, i=%d\n",
  654. String8(str, strLen).string(),
  655. String8(s).string(),
  656. i));
  657. if (s && strzcmp16(s, len, str, strLen) == 0) {
  658. return i;
  659. }
  660. }
  661. }
  662. return NAME_NOT_FOUND;
  663. }
  664. size_t ResStringPool::size() const
  665. {
  666. return (mError == NO_ERROR) ? mHeader->stringCount : 0;
  667. }
  668. #ifndef HAVE_ANDROID_OS
  669. bool ResStringPool::isUTF8() const
  670. {
  671. return (mHeader->flags&ResStringPool_header::UTF8_FLAG)!=0;
  672. }
  673. #endif
  674. // --------------------------------------------------------------------
  675. // --------------------------------------------------------------------
  676. // --------------------------------------------------------------------
  677. ResXMLParser::ResXMLParser(const ResXMLTree& tree)
  678. : mTree(tree), mEventCode(BAD_DOCUMENT)
  679. {
  680. }
  681. void ResXMLParser::restart()
  682. {
  683. mCurNode = NULL;
  684. mEventCode = mTree.mError == NO_ERROR ? START_DOCUMENT : BAD_DOCUMENT;
  685. }
  686. const ResStringPool& ResXMLParser::getStrings() const
  687. {
  688. return mTree.mStrings;
  689. }
  690. ResXMLParser::event_code_t ResXMLParser::getEventType() const
  691. {
  692. return mEventCode;
  693. }
  694. ResXMLParser::event_code_t ResXMLParser::next()
  695. {
  696. if (mEventCode == START_DOCUMENT) {
  697. mCurNode = mTree.mRootNode;
  698. mCurExt = mTree.mRootExt;
  699. return (mEventCode=mTree.mRootCode);
  700. } else if (mEventCode >= FIRST_CHUNK_CODE) {
  701. return nextNode();
  702. }
  703. return mEventCode;
  704. }
  705. int32_t ResXMLParser::getCommentID() const
  706. {
  707. return mCurNode != NULL ? dtohl(mCurNode->comment.index) : -1;
  708. }
  709. const uint16_t* ResXMLParser::getComment(size_t* outLen) const
  710. {
  711. int32_t id = getCommentID();
  712. return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
  713. }
  714. uint32_t ResXMLParser::getLineNumber() const
  715. {
  716. return mCurNode != NULL ? dtohl(mCurNode->lineNumber) : -1;
  717. }
  718. int32_t ResXMLParser::getTextID() const
  719. {
  720. if (mEventCode == TEXT) {
  721. return dtohl(((const ResXMLTree_cdataExt*)mCurExt)->data.index);
  722. }
  723. return -1;
  724. }
  725. const uint16_t* ResXMLParser::getText(size_t* outLen) const
  726. {
  727. int32_t id = getTextID();
  728. return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
  729. }
  730. ssize_t ResXMLParser::getTextValue(Res_value* outValue) const
  731. {
  732. if (mEventCode == TEXT) {
  733. outValue->copyFrom_dtoh(((const ResXMLTree_cdataExt*)mCurExt)->typedData);
  734. return sizeof(Res_value);
  735. }
  736. return BAD_TYPE;
  737. }
  738. int32_t ResXMLParser::getNamespacePrefixID() const
  739. {
  740. if (mEventCode == START_NAMESPACE || mEventCode == END_NAMESPACE) {
  741. return dtohl(((const ResXMLTree_namespaceExt*)mCurExt)->prefix.index);
  742. }
  743. return -1;
  744. }
  745. const uint16_t* ResXMLParser::getNamespacePrefix(size_t* outLen) const
  746. {
  747. int32_t id = getNamespacePrefixID();
  748. //printf("prefix=%d event=%p\n", id, mEventCode);
  749. return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
  750. }
  751. int32_t ResXMLParser::getNamespaceUriID() const
  752. {
  753. if (mEventCode == START_NAMESPACE || mEventCode == END_NAMESPACE) {
  754. return dtohl(((const ResXMLTree_namespaceExt*)mCurExt)->uri.index);
  755. }
  756. return -1;
  757. }
  758. const uint16_t* ResXMLParser::getNamespaceUri(size_t* outLen) const
  759. {
  760. int32_t id = getNamespaceUriID();
  761. //printf("uri=%d event=%p\n", id, mEventCode);
  762. return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
  763. }
  764. int32_t ResXMLParser::getElementNamespaceID() const
  765. {
  766. if (mEventCode == START_TAG) {
  767. return dtohl(((const ResXMLTree_attrExt*)mCurExt)->ns.index);
  768. }
  769. if (mEventCode == END_TAG) {
  770. return dtohl(((const ResXMLTree_endElementExt*)mCurExt)->ns.index);
  771. }
  772. return -1;
  773. }
  774. const uint16_t* ResXMLParser::getElementNamespace(size_t* outLen) const
  775. {
  776. int32_t id = getElementNamespaceID();
  777. return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
  778. }
  779. int32_t ResXMLParser::getElementNameID() const
  780. {
  781. if (mEventCode == START_TAG) {
  782. return dtohl(((const ResXMLTree_attrExt*)mCurExt)->name.index);
  783. }
  784. if (mEventCode == END_TAG) {
  785. return dtohl(((const ResXMLTree_endElementExt*)mCurExt)->name.index);
  786. }
  787. return -1;
  788. }
  789. const uint16_t* ResXMLParser::getElementName(size_t* outLen) const
  790. {
  791. int32_t id = getElementNameID();
  792. return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
  793. }
  794. size_t ResXMLParser::getAttributeCount() const
  795. {
  796. if (mEventCode == START_TAG) {
  797. return dtohs(((const ResXMLTree_attrExt*)mCurExt)->attributeCount);
  798. }
  799. return 0;
  800. }
  801. int32_t ResXMLParser::getAttributeNamespaceID(size_t idx) const
  802. {
  803. if (mEventCode == START_TAG) {
  804. const ResXMLTree_attrExt* tag = (const ResXMLTree_attrExt*)mCurExt;
  805. if (idx < dtohs(tag->attributeCount)) {
  806. const ResXMLTree_attribute* attr = (const ResXMLTree_attribute*)
  807. (((const uint8_t*)tag)
  808. + dtohs(tag->attributeStart)
  809. + (dtohs(tag->attributeSize)*idx));
  810. return dtohl(attr->ns.index);
  811. }
  812. }
  813. return -2;
  814. }
  815. const uint16_t* ResXMLParser::getAttributeNamespace(size_t idx, size_t* outLen) const
  816. {
  817. int32_t id = getAttributeNamespaceID(idx);
  818. //printf("attribute namespace=%d idx=%d event=%p\n", id, idx, mEventCode);
  819. //XML_NOISY(printf("getAttributeNamespace 0x%x=0x%x\n", idx, id));
  820. return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
  821. }
  822. int32_t ResXMLParser::getAttributeNameID(size_t idx) const
  823. {
  824. if (mEventCode == START_TAG) {
  825. const ResXMLTree_attrExt* tag = (const ResXMLTree_attrExt*)mCurExt;
  826. if (idx < dtohs(tag->attributeCount)) {
  827. const ResXMLTree_attribute* attr = (const ResXMLTree_attribute*)
  828. (((const uint8_t*)tag)
  829. + dtohs(tag->attributeStart)
  830. + (dtohs(tag->attributeSize)*idx));
  831. return dtohl(attr->name.index);
  832. }
  833. }
  834. return -1;
  835. }
  836. const uint16_t* ResXMLParser::getAttributeName(size_t idx, size_t* outLen) const
  837. {
  838. int32_t id = getAttributeNameID(idx);
  839. //printf("attribute name=%d idx=%d event=%p\n", id, idx, mEventCode);
  840. //XML_NOISY(printf("getAttributeName 0x%x=0x%x\n", idx, id));
  841. return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
  842. }
  843. uint32_t ResXMLParser::getAttributeNameResID(size_t idx) const
  844. {
  845. int32_t id = getAttributeNameID(idx);
  846. if (id >= 0 && (size_t)id < mTree.mNumResIds) {
  847. return dtohl(mTree.mResIds[id]);
  848. }
  849. return 0;
  850. }
  851. int32_t ResXMLParser::getAttributeValueStringID(size_t idx) const
  852. {
  853. if (mEventCode == START_TAG) {
  854. const ResXMLTree_attrExt* tag = (const ResXMLTree_attrExt*)mCurExt;
  855. if (idx < dtohs(tag->attributeCount)) {
  856. const ResXMLTree_attribute* attr = (const ResXMLTree_attribute*)
  857. (((const uint8_t*)tag)
  858. + dtohs(tag->attributeStart)
  859. + (dtohs(tag->attributeSize)*idx));
  860. return dtohl(attr->rawValue.index);
  861. }
  862. }
  863. return -1;
  864. }
  865. const uint16_t* ResXMLParser::getAttributeStringValue(size_t idx, size_t* outLen) const
  866. {
  867. int32_t id = getAttributeValueStringID(idx);
  868. //XML_NOISY(printf("getAttributeValue 0x%x=0x%x\n", idx, id));
  869. return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
  870. }
  871. int32_t ResXMLParser::getAttributeDataType(size_t idx) const
  872. {
  873. if (mEventCode == START_TAG) {
  874. const ResXMLTree_attrExt* tag = (const ResXMLTree_attrExt*)mCurExt;
  875. if (idx < dtohs(tag->attributeCount)) {
  876. const ResXMLTree_attribute* attr = (const ResXMLTree_attribute*)
  877. (((const uint8_t*)tag)
  878. + dtohs(tag->attributeStart)
  879. + (dtohs(tag->attributeSize)*idx));
  880. return attr->typedValue.dataType;
  881. }
  882. }
  883. return Res_value::TYPE_NULL;
  884. }
  885. int32_t ResXMLParser::getAttributeData(size_t idx) const
  886. {
  887. if (mEventCode == START_TAG) {
  888. const ResXMLTree_attrExt* tag = (const ResXMLTree_attrExt*)mCurExt;
  889. if (idx < dtohs(tag->attributeCount)) {
  890. const ResXMLTree_attribute* attr = (const ResXMLTree_attribute*)
  891. (((const uint8_t*)tag)
  892. + dtohs(tag->attributeStart)
  893. + (dtohs(tag->attributeSize)*idx));
  894. return dtohl(attr->typedValue.data);
  895. }
  896. }
  897. return 0;
  898. }
  899. ssize_t ResXMLParser::getAttributeValue(size_t idx, Res_value* outValue) const
  900. {
  901. if (mEventCode == START_TAG) {
  902. const ResXMLTree_attrExt* tag = (const ResXMLTree_attrExt*)mCurExt;
  903. if (idx < dtohs(tag->attributeCount)) {
  904. const ResXMLTree_attribute* attr = (const ResXMLTree_attribute*)
  905. (((const uint8_t*)tag)
  906. + dtohs(tag->attributeStart)
  907. + (dtohs(tag->attributeSize)*idx));
  908. outValue->copyFrom_dtoh(attr->typedValue);
  909. return sizeof(Res_value);
  910. }
  911. }
  912. return BAD_TYPE;
  913. }
  914. ssize_t ResXMLParser::indexOfAttribute(const char* ns, const char* attr) const
  915. {
  916. String16 nsStr(ns != NULL ? ns : "");
  917. String16 attrStr(attr);
  918. return indexOfAttribute(ns ? nsStr.string() : NULL, ns ? nsStr.size() : 0,
  919. attrStr.string(), attrStr.size());
  920. }
  921. ssize_t ResXMLParser::indexOfAttribute(const char16_t* ns, size_t nsLen,
  922. const char16_t* attr, size_t attrLen) const
  923. {
  924. if (mEventCode == START_TAG) {
  925. const size_t N = getAttributeCount();
  926. for (size_t i=0; i<N; i++) {
  927. size_t curNsLen, curAttrLen;
  928. const char16_t* curNs = getAttributeNamespace(i, &curNsLen);
  929. const char16_t* curAttr = getAttributeName(i, &curAttrLen);
  930. //printf("%d: ns=%p attr=%p curNs=%p curAttr=%p\n",
  931. // i, ns, attr, curNs, curAttr);
  932. //printf(" --> attr=%s, curAttr=%s\n",
  933. // String8(attr).string(), String8(curAttr).string());
  934. if (attr && curAttr && (strzcmp16(attr, attrLen, curAttr, curAttrLen) == 0)) {
  935. if (ns == NULL) {
  936. if (curNs == NULL) return i;
  937. } else if (curNs != NULL) {
  938. //printf(" --> ns=%s, curNs=%s\n",
  939. // String8(ns).string(), String8(curNs).string());
  940. if (strzcmp16(ns, nsLen, curNs, curNsLen) == 0) return i;
  941. }
  942. }
  943. }
  944. }
  945. return NAME_NOT_FOUND;
  946. }
  947. ssize_t ResXMLParser::indexOfID() const
  948. {
  949. if (mEventCode == START_TAG) {
  950. const ssize_t idx = dtohs(((const ResXMLTree_attrExt*)mCurExt)->idIndex);
  951. if (idx > 0) return (idx-1);
  952. }
  953. return NAME_NOT_FOUND;
  954. }
  955. ssize_t ResXMLParser::indexOfClass() const
  956. {
  957. if (mEventCode == START_TAG) {
  958. const ssize_t idx = dtohs(((const ResXMLTree_attrExt*)mCurExt)->classIndex);
  959. if (idx > 0) return (idx-1);
  960. }
  961. return NAME_NOT_FOUND;
  962. }
  963. ssize_t ResXMLParser::indexOfStyle() const
  964. {
  965. if (mEventCode == START_TAG) {
  966. const ssize_t idx = dtohs(((const ResXMLTree_attrExt*)mCurExt)->styleIndex);
  967. if (idx > 0) return (idx-1);
  968. }
  969. return NAME_NOT_FOUND;
  970. }
  971. ResXMLParser::event_code_t ResXMLParser::nextNode()
  972. {
  973. if (mEventCode < 0) {
  974. return mEventCode;
  975. }
  976. do {
  977. const ResXMLTree_node* next = (const ResXMLTree_node*)
  978. (((const uint8_t*)mCurNode) + dtohl(mCurNode->header.size));
  979. //LOGW("Next node: prev=%p, next=%p\n", mCurNode, next);
  980. if (((const uint8_t*)next) >= mTree.mDataEnd) {
  981. mCurNode = NULL;
  982. return (mEventCode=END_DOCUMENT);
  983. }
  984. if (mTree.validateNode(next) != NO_ERROR) {
  985. mCurNode = NULL;
  986. return (mEventCode=BAD_DOCUMENT);
  987. }
  988. mCurNode = next;
  989. const uint16_t headerSize = dtohs(next->header.headerSize);
  990. const uint32_t totalSize = dtohl(next->header.size);
  991. mCurExt = ((const uint8_t*)next) + headerSize;
  992. size_t minExtSize = 0;
  993. event_code_t eventCode = (event_code_t)dtohs(next->header.type);
  994. switch ((mEventCode=eventCode)) {
  995. case RES_XML_START_NAMESPACE_TYPE:
  996. case RES_XML_END_NAMESPACE_TYPE:
  997. minExtSize = sizeof(ResXMLTree_namespaceExt);
  998. break;
  999. case RES_XML_START_ELEMENT_TYPE:
  1000. minExtSize = sizeof(ResXMLTree_attrExt);
  1001. break;
  1002. case RES_XML_END_ELEMENT_TYPE:
  1003. minExtSize = sizeof(ResXMLTree_endElementExt);
  1004. break;
  1005. case RES_XML_CDATA_TYPE:
  1006. minExtSize = sizeof(ResXMLTree_cdataExt);
  1007. break;
  1008. default:
  1009. LOGW("Unknown XML block: header type %d in node at %d\n",
  1010. (int)dtohs(next->header.type),
  1011. (int)(((const uint8_t*)next)-((const uint8_t*)mTree.mHeader)));
  1012. continue;
  1013. }
  1014. if ((totalSize-headerSize) < minExtSize) {
  1015. LOGW("Bad XML block: header type 0x%x in node at 0x%x has size %d, need %d\n",
  1016. (int)dtohs(next->header.type),
  1017. (int)(((const uint8_t*)next)-((const uint8_t*)mTree.mHeader)),
  1018. (int)(totalSize-headerSize), (int)minExtSize);
  1019. return (mEventCode=BAD_DOCUMENT);
  1020. }
  1021. //printf("CurNode=%p, CurExt=%p, headerSize=%d, minExtSize=%d\n",
  1022. // mCurNode, mCurExt, headerSize, minExtSize);
  1023. return eventCode;
  1024. } while (true);
  1025. }
  1026. void ResXMLParser::getPosition(ResXMLParser::ResXMLPosition* pos) const
  1027. {
  1028. pos->eventCode = mEventCode;
  1029. pos->curNode = mCurNode;
  1030. pos->curExt = mCurExt;
  1031. }
  1032. void ResXMLParser::setPosition(const ResXMLParser::ResXMLPosition& pos)
  1033. {
  1034. mEventCode = pos.eventCode;
  1035. mCurNode = pos.curNode;
  1036. mCurExt = pos.curExt;
  1037. }
  1038. // --------------------------------------------------------------------
  1039. static volatile int32_t gCount = 0;
  1040. ResXMLTree::ResXMLTree()
  1041. : ResXMLParser(*this)
  1042. , mError(NO_INIT), mOwnedData(NULL)
  1043. {
  1044. //LOGI("Creating ResXMLTree %p #%d\n", this, android_atomic_inc(&gCount)+1);
  1045. restart();
  1046. }
  1047. ResXMLTree::ResXMLTree(const void* data, size_t size, bool copyData)
  1048. : ResXMLParser(*this)
  1049. , mError(NO_INIT), mOwnedData(NULL)
  1050. {
  1051. //LOGI("Creating ResXMLTree %p #%d\n", this, android_atomic_inc(&gCount)+1);
  1052. setTo(data, size, copyData);
  1053. }
  1054. ResXMLTree::~ResXMLTree()
  1055. {
  1056. //LOGI("Destroying ResXMLTree in %p #%d\n", this, android_atomic_dec(&gCount)-1);
  1057. uninit();
  1058. }
  1059. status_t ResXMLTree::setTo(const void* data, size_t size, bool copyData)
  1060. {
  1061. uninit();
  1062. mEventCode = START_DOCUMENT;
  1063. if (copyData) {
  1064. mOwnedData = malloc(size);
  1065. if (mOwnedData == NULL) {
  1066. return (mError=NO_MEMORY);
  1067. }
  1068. memcpy(mOwnedData, data, size);
  1069. data = mOwnedData;
  1070. }
  1071. mHeader = (const ResXMLTree_header*)data;
  1072. mSize = dtohl(mHeader->header.size);
  1073. if (dtohs(mHeader->header.headerSize) > mSize || mSize > size) {
  1074. LOGW("Bad XML block: header size %d or total size %d is larger than data size %d\n",
  1075. (int)dtohs(mHeader->header.headerSize),
  1076. (int)dtohl(mHeader->header.size), (int)size);
  1077. mError = BAD_TYPE;
  1078. restart();
  1079. return mError;
  1080. }
  1081. mDataEnd = ((const uint8_t*)mHeader) + mSize;
  1082. mStrings.uninit();
  1083. mRootNode = NULL;
  1084. mResIds = NULL;
  1085. mNumResIds = 0;
  1086. // First look for a couple interesting chunks: the string block
  1087. // and first XML node.
  1088. const ResChunk_header* chunk =
  1089. (const ResChunk_header*)(((const uint8_t*)mHeader) + dtohs(mHeader->header.headerSize));
  1090. const ResChunk_header* lastChunk = chunk;
  1091. while (((const uint8_t*)chunk) < (mDataEnd-sizeof(ResChunk_header)) &&
  1092. ((const uint8_t*)chunk) < (mDataEnd-dtohl(chunk->size))) {
  1093. status_t err = validate_chunk(chunk, sizeof(ResChunk_header), mDataEnd, "XML");
  1094. if (err != NO_ERROR) {
  1095. mError = err;
  1096. goto done;
  1097. }
  1098. const uint16_t type = dtohs(chunk->type);
  1099. const size_t size = dtohl(chunk->size);
  1100. XML_NOISY(printf("Scanning @ %p: type=0x%x, size=0x%x\n",
  1101. (void*)(((uint32_t)chunk)-((uint32_t)mHeader)), type, size));
  1102. if (type == RES_STRING_POOL_TYPE) {
  1103. mStrings.setTo(chunk, size);
  1104. } else if (type == RES_XML_RESOURCE_MAP_TYPE) {
  1105. mResIds = (const uint32_t*)
  1106. (((const uint8_t*)chunk)+dtohs(chunk->headerSize));
  1107. mNumResIds = (dtohl(chunk->size)-dtohs(chunk->headerSize))/sizeof(uint32_t);
  1108. } else if (type >= RES_XML_FIRST_CHUNK_TYPE
  1109. && type <= RES_XML_LAST_CHUNK_TYPE) {
  1110. if (validateNode((const ResXMLTree_node*)chunk) != NO_ERROR) {
  1111. mError = BAD_TYPE;
  1112. goto done;
  1113. }
  1114. mCurNode = (const ResXMLTree_node*)lastChunk;
  1115. if (nextNode() == BAD_DOCUMENT) {
  1116. mError = BAD_TYPE;
  1117. goto done;
  1118. }
  1119. mRootNode = mCurNode;
  1120. mRootExt = mCurExt;
  1121. mRootCode = mEventCode;
  1122. break;
  1123. } else {
  1124. XML_NOISY(printf("Skipping unknown chunk!\n"));
  1125. }
  1126. lastChunk = chunk;
  1127. chunk = (const ResChunk_header*)
  1128. (((const uint8_t*)chunk) + size);
  1129. }
  1130. if (mRootNode == NULL) {
  1131. LOGW("Bad XML block: no root element node found\n");
  1132. mError = BAD_TYPE;
  1133. goto done;
  1134. }
  1135. mError = mStrings.getError();
  1136. done:
  1137. restart();
  1138. return mError;
  1139. }
  1140. status_t ResXMLTree::getError() const
  1141. {
  1142. return mError;
  1143. }
  1144. void ResXMLTree::uninit()
  1145. {
  1146. mError = NO_INIT;
  1147. mStrings.uninit();
  1148. if (mOwnedData) {
  1149. free(mOwnedData);
  1150. mOwnedData = NULL;
  1151. }
  1152. restart();
  1153. }
  1154. status_t ResXMLTree::validateNode(const ResXMLTree_node* node) const
  1155. {
  1156. const uint16_t eventCode = dtohs(node->header.type);
  1157. status_t err = validate_chunk(
  1158. &node->header, sizeof(ResXMLTree_node),
  1159. mDataEnd, "ResXMLTree_node");
  1160. if (err >= NO_ERROR) {
  1161. // Only perform additional validation on START nodes
  1162. if (eventCode != RES_XML_START_ELEMENT_TYPE) {
  1163. return NO_ERROR;
  1164. }
  1165. const uint16_t headerSize = dtohs(node->header.headerSize);
  1166. const uint32_t size = dtohl(node->header.size);
  1167. const ResXMLTree_attrExt* attrExt = (const ResXMLTree_attrExt*)
  1168. (((const uint8_t*)node) + headerSize);
  1169. // check for sensical values pulled out of the stream so far...
  1170. if ((size >= headerSize + sizeof(ResXMLTree_attrExt))
  1171. && ((void*)attrExt > (void*)node)) {
  1172. const size_t attrSize = ((size_t)dtohs(attrExt->attributeSize))
  1173. * dtohs(attrExt->attributeCount);
  1174. if ((dtohs(attrExt->attributeStart)+attrSize) <= (size-headerSize)) {
  1175. return NO_ERROR;
  1176. }
  1177. LOGW("Bad XML block: node attributes use 0x%x bytes, only have 0x%x bytes\n",
  1178. (unsigned int)(dtohs(attrExt->attributeStart)+attrSize),
  1179. (unsigned int)(size-headerSize));
  1180. }
  1181. else {
  1182. LOGW("Bad XML start block: node header size 0x%x, size 0x%x\n",
  1183. (unsigned int)headerSize, (unsigned int)size);
  1184. }
  1185. return BAD_TYPE;
  1186. }
  1187. return err;
  1188. #if 0
  1189. const bool isStart = dtohs(node->header.type) == RES_XML_START_ELEMENT_TYPE;
  1190. const uint16_t headerSize = dtohs(node->header.headerSize);
  1191. const uint32_t size = dtohl(node->header.size);
  1192. if (headerSize >= (isStart ? sizeof(ResXMLTree_attrNode) : sizeof(ResXMLTree_node))) {
  1193. if (size >= headerSize) {
  1194. if (((const uint8_t*)node) <= (mDataEnd-size)) {
  1195. if (!isStart) {
  1196. return NO_ERROR;
  1197. }
  1198. if ((((size_t)dtohs(node->attributeSize))*dtohs(node->attributeCount))
  1199. <= (size-headerSize)) {
  1200. return NO_ERROR;
  1201. }
  1202. LOGW("Bad XML block: node attributes use 0x%x bytes, only have 0x%x bytes\n",
  1203. ((int)dtohs(node->attributeSize))*dtohs(node->attributeCount),
  1204. (int)(size-headerSize));
  1205. return BAD_TYPE;
  1206. }
  1207. LOGW("Bad XML block: node at 0x%x extends beyond data end 0x%x\n",
  1208. (int)(((const uint8_t*)node)-((const uint8_t*)mHeader)), (int)mSize);
  1209. return BAD_TYPE;
  1210. }
  1211. LOGW("Bad XML block: node at 0x%x header size 0x%x smaller than total size 0x%x\n",
  1212. (int)(((const uint8_t*)node)-((const uint8_t*)mHeader)),
  1213. (int)headerSize, (int)size);
  1214. return BAD_TYPE;
  1215. }
  1216. LOGW("Bad XML block: node at 0x%x header size 0x%x too small\n",
  1217. (int)(((const uint8_t*)node)-((const uint8_t*)mHeader)),
  1218. (int)headerSize);
  1219. return BAD_TYPE;
  1220. #endif
  1221. }
  1222. // --------------------------------------------------------------------
  1223. // --------------------------------------------------------------------
  1224. // --------------------------------------------------------------------
  1225. struct ResTable::Header
  1226. {
  1227. Header(ResTable* _owner) : owner(_owner), ownedData(NULL), header(NULL),
  1228. resourceIDMap(NULL), resourceIDMapSize(0) { }
  1229. ~Header()
  1230. {
  1231. free(resourceIDMap);
  1232. }
  1233. ResTable* const owner;
  1234. void* ownedData;
  1235. const ResTable_header* header;
  1236. size_t size;
  1237. const uint8_t* dataEnd;
  1238. size_t index;
  1239. void* cookie;
  1240. ResStringPool values;
  1241. uint32_t* resourceIDMap;
  1242. size_t resourceIDMapSize;
  1243. };
  1244. struct ResTable::Type
  1245. {
  1246. Type(const Header* _header, const Package* _package, size_t count)
  1247. : header(_header), package(_package), entryCount(count),
  1248. typeSpec(NULL), typeSpecFlags(NULL) { }
  1249. const Header* const header;
  1250. const Package* const package;
  1251. const size_t entryCount;
  1252. const ResTable_typeSpec* typeSpec;
  1253. const uint32_t* typeSpecFlags;
  1254. Vector<const ResTable_type*> configs;
  1255. };
  1256. struct ResTable::Package
  1257. {
  1258. Package(ResTable* _owner, const Header* _header, const ResTable_package* _package)
  1259. : owner(_owner), header(_header), package(_package) { }
  1260. ~Package()
  1261. {
  1262. size_t i = types.size();
  1263. while (i > 0) {
  1264. i--;
  1265. delete types[i];
  1266. }
  1267. }
  1268. ResTable* const owner;
  1269. const Header* const header;
  1270. const ResTable_package* const package;
  1271. Vector<Type*> types;
  1272. ResStringPool typeStrings;
  1273. ResStringPool keyStrings;
  1274. const Type* getType(size_t idx) const {
  1275. return idx < types.size() ? types[idx] : NULL;
  1276. }
  1277. };
  1278. // A group of objects describing a particular resource package.
  1279. // The first in 'package' is always the root object (from the resource
  1280. // table that defined the package); the ones after are skins on top of it.
  1281. struct ResTable::PackageGroup
  1282. {
  1283. PackageGroup(ResTable* _owner, const String16& _name, uint32_t _id)
  1284. : owner(_owner), name(_name), id(_id), typeCount(0), bags(NULL) { }
  1285. ~PackageGroup() {
  1286. clearBagCache();
  1287. const size_t N = packages.size();
  1288. for (size_t i=0; i<N; i++) {
  1289. Package* pkg = packages[i];
  1290. if (pkg->owner == owner) {
  1291. delete pkg;
  1292. }
  1293. }
  1294. }
  1295. void clearBagCache() {
  1296. if (bags) {
  1297. TABLE_NOISY(printf("bags=%p\n", bags));
  1298. Package* pkg = packages[0];
  1299. TABLE_NOISY(printf("typeCount=%x\n", typeCount));
  1300. for (size_t i=0; i<typeCount; i++) {
  1301. TABLE_NOISY(printf("type=%d\n", i));
  1302. const Type* type = pkg->getType(i);
  1303. if (type != NULL) {
  1304. bag_set** typeBags = bags[i];
  1305. TABLE_NOISY(printf("typeBags=%p\n", typeBags));
  1306. if (typeBags) {
  1307. TABLE_NOISY(printf("type->entryCount=%x\n", type->entryCount));
  1308. const size_t N = type->entryCount;
  1309. for (size_t j=0; j<N; j++) {
  1310. if (typeBags[j] && typeBags[j] != (bag_set*)