bool readString(const char*& data, const char* end, String& result, const char* dbgLabel) { unsigned stringLength; if (!readUnsigned(data, end, stringLength)) { ALOGW("Not enough data to read string length; tag=\"%s\" end=%p data=%p", dbgLabel ? dbgLabel : "<no tag>", end, data); return false; } if (dbgLabel) ALOGV("Reading %-16s %d %.*s", dbgLabel, stringLength, stringLength, data); // If length was 0, there will be no string content, but still return true if (!stringLength) { result = String(); return true; } if ((end < data) || ((unsigned)(end - data) < stringLength)) { ALOGW("Not enough data to read content; tag=\"%s\" end=%p data=%p stringLength=%u", dbgLabel ? dbgLabel : "<no tag>", end, data, stringLength); return false; } const unsigned MAX_REASONABLE_STRING_LENGTH = 10000; if (stringLength > MAX_REASONABLE_STRING_LENGTH) { ALOGW("String length is suspiciously large (>%d); tag=\"%s\" end=%p data=%p stringLength=%u", MAX_REASONABLE_STRING_LENGTH, dbgLabel ? dbgLabel : "<no tag>", end, data, stringLength); } bool decodeFailed = false; static const WebCore::TextEncoding& encoding = WebCore::UTF8Encoding(); result = encoding.decode(data, stringLength, true, decodeFailed); if (decodeFailed) { ALOGW("Decode failed, tag=\"%s\" end=%p data=%p stringLength=%u content=\"%s\"", dbgLabel ? dbgLabel : "<no tag>", end, data, stringLength, result.utf8().data()); return false; } if (stringLength > MAX_REASONABLE_STRING_LENGTH) { ALOGW("\tdecodeFailed=%d (flag is ignored) content=\"%s\"", decodeFailed, result.utf8().data()); } data += stringLength; return true; }
bool Bitmap::getImageSize(const io::Producer &file, size_t &width, size_t &height) { StackBuffer<256> data; if (file.seekAndRead(0, data, 30) < 30) { return false; } if (isPng(data.data(), data.size()) && data.size() >= 24) { auto reader = DataReader<ByteOrder::Network>(data.data() + 16, 8); width = reader.readUnsigned32(); height = reader.readUnsigned32(); return true; } else if(isJpg(data.data(), data.size())) { size_t offset = 2; uint16_t len = 0; uint8_t marker = 0; auto reader = DataReader<ByteOrder::Network>(data.data() + 2, data.size() - 2); while (reader.is((uint8_t)0xFF)) { ++ reader; } marker = reader.readUnsigned(); len = reader.readUnsigned16(); while (marker < 0xC0 || marker > 0xCF) { offset += 2 + len; data.clear(); if (file.seekAndRead(offset, data, 12) != 12) { return false; } if (data.size() >= 12) { reader = data.get<DataReader<ByteOrder::Network>>(); while (reader.is((uint8_t)0xFF)) { ++ reader; } marker = reader.readUnsigned(); len = reader.readUnsigned16(); } else { reader.clear(); break; } } if (reader >= 5 && marker >= 0xC0 && marker <= 0xCF) { ++ reader; height = reader.readUnsigned16(); width = reader.readUnsigned16(); return true; } return false; } else if (isGif(data.data(), data.size())) { auto reader = DataReader<ByteOrder::Little>(data.data() + 6, 4); width = reader.readUnsigned16(); height = reader.readUnsigned16(); return true; } else if (isWebp(data.data(), data.size())) { auto reader = DataReader<ByteOrder::Little>(data.data() + 26, 4); width = reader.readUnsigned16(); height = reader.readUnsigned16(); return true; } else if (isTiff(data.data(), data.size())) { if (memcmp(data.data(), "II", 2) == 0) { if (Bitmap_getTiffImageSize<DataReader<ByteOrder::Little>>(data, file, width, height)) { return true; } } else { if (Bitmap_getTiffImageSize<DataReader<ByteOrder::Big>>(data, file, width, height)) { return true; } } } return false; }
static bool readItemRecursive(WebCore::HistoryItem* newItem, const char** pData, int length) { if (!pData || length < HISTORY_MIN_SIZE) { ALOGW("readItemRecursive() bad params; pData=%p length=%d", pData, length); return false; } const char* data = *pData; const char* end = data + length; String content; // Read the original url if (readString(data, end, content, "Original url")) newItem->setOriginalURLString(content); else return false; // Read the url if (readString(data, end, content, "Url")) newItem->setURLString(content); else return false; // Read the title if (readString(data, end, content, "Title")) newItem->setTitle(content); else return false; // Generate a new ResourceRequest object for populating form information. // Read the form content type WTF::String formContentType; if (!readString(data, end, formContentType, "Content type")) return false; // Read the form data size unsigned formDataSize; if (!readUnsigned(data, end, formDataSize, "Form data size")) return false; // Read the form data WTF::RefPtr<WebCore::FormData> formData; if (formDataSize) { ALOGV("Reading Form data %d %.*s", formDataSize, formDataSize, data); if ((end < data) || ((size_t)(end - data) < formDataSize)) { ALOGW("\tNot enough data to read form data; returning"); return false; } formData = WebCore::FormData::create(data, formDataSize); data += formDataSize; // Read the identifier int64_t id; if (!readInt64(data, end, id, "Form id")) return false; if (id) formData->setIdentifier(id); } // Set up the form info if (formData != NULL) { WebCore::ResourceRequest r; r.setHTTPMethod("POST"); r.setHTTPContentType(formContentType); r.setHTTPBody(formData); newItem->setFormInfoFromRequest(r); } // Read the target if (readString(data, end, content, "Target")) newItem->setTarget(content); else return false; AndroidWebHistoryBridge* bridge = newItem->bridge(); ALOG_ASSERT(bridge, "There should be a bridge object during inflate"); // Read the screen scale float fValue; if (readFloat(data, end, fValue, "Screen scale")) bridge->setScale(fValue); else return false; // Read the text wrap scale if (readFloat(data, end, fValue, "Text wrap scale")) bridge->setTextWrapScale(fValue); else return false; // Read scroll position. int scrollX; if (!readInt(data, end, scrollX, "Scroll pos x")) return false; int scrollY; if (!readInt(data, end, scrollY, "Scroll pos y")) return false; newItem->setScrollPoint(IntPoint(scrollX, scrollY)); // Read the document state unsigned docStateCount; if (!readUnsigned(data, end, docStateCount, "Doc state count")) return false; if (docStateCount) { // Create a new vector and reserve enough space for the document state. WTF::Vector<WTF::String> docState; docState.reserveCapacity(docStateCount); while (docStateCount--) { // Read a document state string if (readString(data, end, content, "Document state")) docState.append(content); else return false; } newItem->setDocumentState(docState); } // Read is target item bool c; if (readBool(data, end, c, "Target item")) newItem->setIsTargetItem(c); else return false; // Read the child count unsigned count; if (!readUnsigned(data, end, count, "Child count")) return false; *pData = data; if (count) { while (count--) { // No need to check the length each time because read_item_recursive // will return null if there isn't enough data left to parse. WTF::RefPtr<WebCore::HistoryItem> child = WebCore::HistoryItem::create(); // Set a bridge that will not call into java. child->setBridge(new WebHistoryItem(static_cast<WebHistoryItem*>(bridge))); // Read the child item. if (!readItemRecursive(child.get(), pData, end - data)) return false; child->bridge()->setActive(); newItem->addChildItem(child); } } return true; }