1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2006 The Android Open Source Project 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/core/SkStream.h" 9cb93a386Sopenharmony_ci#include "include/core/SkString.h" 10cb93a386Sopenharmony_ci#include "include/core/SkTypes.h" 11cb93a386Sopenharmony_ci#include "include/private/SkTemplates.h" 12cb93a386Sopenharmony_ci#include "include/private/SkTo.h" 13cb93a386Sopenharmony_ci#include "src/xml/SkXMLParser.h" 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_ci#include <expat.h> 16cb93a386Sopenharmony_ci 17cb93a386Sopenharmony_ci#include <vector> 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_cistatic char const* const gErrorStrings[] = { 20cb93a386Sopenharmony_ci "empty or missing file ", 21cb93a386Sopenharmony_ci "unknown element ", 22cb93a386Sopenharmony_ci "unknown attribute name ", 23cb93a386Sopenharmony_ci "error in attribute value ", 24cb93a386Sopenharmony_ci "duplicate ID ", 25cb93a386Sopenharmony_ci "unknown error " 26cb93a386Sopenharmony_ci}; 27cb93a386Sopenharmony_ci 28cb93a386Sopenharmony_ciSkXMLParserError::SkXMLParserError() : fCode(kNoError), fLineNumber(-1), 29cb93a386Sopenharmony_ci fNativeCode(-1) 30cb93a386Sopenharmony_ci{ 31cb93a386Sopenharmony_ci reset(); 32cb93a386Sopenharmony_ci} 33cb93a386Sopenharmony_ci 34cb93a386Sopenharmony_ciSkXMLParserError::~SkXMLParserError() 35cb93a386Sopenharmony_ci{ 36cb93a386Sopenharmony_ci // need a virtual destructor for our subclasses 37cb93a386Sopenharmony_ci} 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_civoid SkXMLParserError::getErrorString(SkString* str) const 40cb93a386Sopenharmony_ci{ 41cb93a386Sopenharmony_ci SkASSERT(str); 42cb93a386Sopenharmony_ci SkString temp; 43cb93a386Sopenharmony_ci if (fCode != kNoError) { 44cb93a386Sopenharmony_ci if ((unsigned)fCode < SK_ARRAY_COUNT(gErrorStrings)) 45cb93a386Sopenharmony_ci temp.set(gErrorStrings[fCode - 1]); 46cb93a386Sopenharmony_ci temp.append(fNoun); 47cb93a386Sopenharmony_ci } else 48cb93a386Sopenharmony_ci SkXMLParser::GetNativeErrorString(fNativeCode, &temp); 49cb93a386Sopenharmony_ci str->append(temp); 50cb93a386Sopenharmony_ci} 51cb93a386Sopenharmony_ci 52cb93a386Sopenharmony_civoid SkXMLParserError::reset() { 53cb93a386Sopenharmony_ci fCode = kNoError; 54cb93a386Sopenharmony_ci fLineNumber = -1; 55cb93a386Sopenharmony_ci fNativeCode = -1; 56cb93a386Sopenharmony_ci} 57cb93a386Sopenharmony_ci 58cb93a386Sopenharmony_ci//////////////// 59cb93a386Sopenharmony_ci 60cb93a386Sopenharmony_cinamespace { 61cb93a386Sopenharmony_ci 62cb93a386Sopenharmony_ciconst XML_Memory_Handling_Suite sk_XML_alloc = { 63cb93a386Sopenharmony_ci sk_malloc_throw, 64cb93a386Sopenharmony_ci sk_realloc_throw, 65cb93a386Sopenharmony_ci sk_free 66cb93a386Sopenharmony_ci}; 67cb93a386Sopenharmony_ci 68cb93a386Sopenharmony_cistruct ParsingContext { 69cb93a386Sopenharmony_ci ParsingContext(SkXMLParser* parser) 70cb93a386Sopenharmony_ci : fParser(parser) 71cb93a386Sopenharmony_ci , fXMLParser(XML_ParserCreate_MM(nullptr, &sk_XML_alloc, nullptr)) { } 72cb93a386Sopenharmony_ci 73cb93a386Sopenharmony_ci void flushText() { 74cb93a386Sopenharmony_ci if (!fBufferedText.empty()) { 75cb93a386Sopenharmony_ci fParser->text(fBufferedText.data(), SkTo<int>(fBufferedText.size())); 76cb93a386Sopenharmony_ci fBufferedText.clear(); 77cb93a386Sopenharmony_ci } 78cb93a386Sopenharmony_ci } 79cb93a386Sopenharmony_ci 80cb93a386Sopenharmony_ci void appendText(const char* txt, size_t len) { 81cb93a386Sopenharmony_ci fBufferedText.insert(fBufferedText.end(), txt, &txt[len]); 82cb93a386Sopenharmony_ci } 83cb93a386Sopenharmony_ci 84cb93a386Sopenharmony_ci SkXMLParser* fParser; 85cb93a386Sopenharmony_ci SkAutoTCallVProc<std::remove_pointer_t<XML_Parser>, XML_ParserFree> fXMLParser; 86cb93a386Sopenharmony_ci 87cb93a386Sopenharmony_ciprivate: 88cb93a386Sopenharmony_ci std::vector<char> fBufferedText; 89cb93a386Sopenharmony_ci}; 90cb93a386Sopenharmony_ci 91cb93a386Sopenharmony_ci#define HANDLER_CONTEXT(arg, name) ParsingContext* name = static_cast<ParsingContext*>(arg) 92cb93a386Sopenharmony_ci 93cb93a386Sopenharmony_civoid XMLCALL start_element_handler(void *data, const char* tag, const char** attributes) { 94cb93a386Sopenharmony_ci HANDLER_CONTEXT(data, ctx); 95cb93a386Sopenharmony_ci ctx->flushText(); 96cb93a386Sopenharmony_ci 97cb93a386Sopenharmony_ci ctx->fParser->startElement(tag); 98cb93a386Sopenharmony_ci 99cb93a386Sopenharmony_ci for (size_t i = 0; attributes[i]; i += 2) { 100cb93a386Sopenharmony_ci ctx->fParser->addAttribute(attributes[i], attributes[i + 1]); 101cb93a386Sopenharmony_ci } 102cb93a386Sopenharmony_ci} 103cb93a386Sopenharmony_ci 104cb93a386Sopenharmony_civoid XMLCALL end_element_handler(void* data, const char* tag) { 105cb93a386Sopenharmony_ci HANDLER_CONTEXT(data, ctx); 106cb93a386Sopenharmony_ci ctx->flushText(); 107cb93a386Sopenharmony_ci 108cb93a386Sopenharmony_ci ctx->fParser->endElement(tag); 109cb93a386Sopenharmony_ci} 110cb93a386Sopenharmony_ci 111cb93a386Sopenharmony_civoid XMLCALL text_handler(void *data, const char* txt, int len) { 112cb93a386Sopenharmony_ci HANDLER_CONTEXT(data, ctx); 113cb93a386Sopenharmony_ci 114cb93a386Sopenharmony_ci ctx->appendText(txt, SkTo<size_t>(len)); 115cb93a386Sopenharmony_ci} 116cb93a386Sopenharmony_ci 117cb93a386Sopenharmony_civoid XMLCALL entity_decl_handler(void *data, 118cb93a386Sopenharmony_ci const XML_Char *entityName, 119cb93a386Sopenharmony_ci int is_parameter_entity, 120cb93a386Sopenharmony_ci const XML_Char *value, 121cb93a386Sopenharmony_ci int value_length, 122cb93a386Sopenharmony_ci const XML_Char *base, 123cb93a386Sopenharmony_ci const XML_Char *systemId, 124cb93a386Sopenharmony_ci const XML_Char *publicId, 125cb93a386Sopenharmony_ci const XML_Char *notationName) { 126cb93a386Sopenharmony_ci HANDLER_CONTEXT(data, ctx); 127cb93a386Sopenharmony_ci 128cb93a386Sopenharmony_ci SkDebugf("'%s' entity declaration found, stopping processing", entityName); 129cb93a386Sopenharmony_ci XML_StopParser(ctx->fXMLParser, XML_FALSE); 130cb93a386Sopenharmony_ci} 131cb93a386Sopenharmony_ci 132cb93a386Sopenharmony_ci} // anonymous namespace 133cb93a386Sopenharmony_ci 134cb93a386Sopenharmony_ciSkXMLParser::SkXMLParser(SkXMLParserError* parserError) : fParser(nullptr), fError(parserError) 135cb93a386Sopenharmony_ci{ 136cb93a386Sopenharmony_ci} 137cb93a386Sopenharmony_ci 138cb93a386Sopenharmony_ciSkXMLParser::~SkXMLParser() 139cb93a386Sopenharmony_ci{ 140cb93a386Sopenharmony_ci} 141cb93a386Sopenharmony_ci 142cb93a386Sopenharmony_cibool SkXMLParser::parse(SkStream& docStream) 143cb93a386Sopenharmony_ci{ 144cb93a386Sopenharmony_ci ParsingContext ctx(this); 145cb93a386Sopenharmony_ci if (!ctx.fXMLParser) { 146cb93a386Sopenharmony_ci SkDebugf("could not create XML parser\n"); 147cb93a386Sopenharmony_ci return false; 148cb93a386Sopenharmony_ci } 149cb93a386Sopenharmony_ci 150cb93a386Sopenharmony_ci XML_SetUserData(ctx.fXMLParser, &ctx); 151cb93a386Sopenharmony_ci XML_SetElementHandler(ctx.fXMLParser, start_element_handler, end_element_handler); 152cb93a386Sopenharmony_ci XML_SetCharacterDataHandler(ctx.fXMLParser, text_handler); 153cb93a386Sopenharmony_ci 154cb93a386Sopenharmony_ci // Disable entity processing, to inhibit internal entity expansion. See expat CVE-2013-0340. 155cb93a386Sopenharmony_ci XML_SetEntityDeclHandler(ctx.fXMLParser, entity_decl_handler); 156cb93a386Sopenharmony_ci 157cb93a386Sopenharmony_ci static constexpr int kBufferSize = 4096; 158cb93a386Sopenharmony_ci bool done = false; 159cb93a386Sopenharmony_ci do { 160cb93a386Sopenharmony_ci void* buffer = XML_GetBuffer(ctx.fXMLParser, kBufferSize); 161cb93a386Sopenharmony_ci if (!buffer) { 162cb93a386Sopenharmony_ci SkDebugf("could not buffer enough to continue\n"); 163cb93a386Sopenharmony_ci return false; 164cb93a386Sopenharmony_ci } 165cb93a386Sopenharmony_ci 166cb93a386Sopenharmony_ci size_t len = docStream.read(buffer, kBufferSize); 167cb93a386Sopenharmony_ci done = docStream.isAtEnd(); 168cb93a386Sopenharmony_ci XML_Status status = XML_ParseBuffer(ctx.fXMLParser, SkToS32(len), done); 169cb93a386Sopenharmony_ci if (XML_STATUS_ERROR == status) { 170cb93a386Sopenharmony_ci XML_Error error = XML_GetErrorCode(ctx.fXMLParser); 171cb93a386Sopenharmony_ci int line = XML_GetCurrentLineNumber(ctx.fXMLParser); 172cb93a386Sopenharmony_ci int column = XML_GetCurrentColumnNumber(ctx.fXMLParser); 173cb93a386Sopenharmony_ci const XML_LChar* errorString = XML_ErrorString(error); 174cb93a386Sopenharmony_ci SkDebugf("parse error @%d:%d: %d (%s).\n", line, column, error, errorString); 175cb93a386Sopenharmony_ci return false; 176cb93a386Sopenharmony_ci } 177cb93a386Sopenharmony_ci } while (!done); 178cb93a386Sopenharmony_ci 179cb93a386Sopenharmony_ci return true; 180cb93a386Sopenharmony_ci} 181cb93a386Sopenharmony_ci 182cb93a386Sopenharmony_cibool SkXMLParser::parse(const char doc[], size_t len) 183cb93a386Sopenharmony_ci{ 184cb93a386Sopenharmony_ci SkMemoryStream docStream(doc, len); 185cb93a386Sopenharmony_ci return this->parse(docStream); 186cb93a386Sopenharmony_ci} 187cb93a386Sopenharmony_ci 188cb93a386Sopenharmony_civoid SkXMLParser::GetNativeErrorString(int error, SkString* str) 189cb93a386Sopenharmony_ci{ 190cb93a386Sopenharmony_ci 191cb93a386Sopenharmony_ci} 192cb93a386Sopenharmony_ci 193cb93a386Sopenharmony_cibool SkXMLParser::startElement(const char elem[]) 194cb93a386Sopenharmony_ci{ 195cb93a386Sopenharmony_ci return this->onStartElement(elem); 196cb93a386Sopenharmony_ci} 197cb93a386Sopenharmony_ci 198cb93a386Sopenharmony_cibool SkXMLParser::addAttribute(const char name[], const char value[]) 199cb93a386Sopenharmony_ci{ 200cb93a386Sopenharmony_ci return this->onAddAttribute(name, value); 201cb93a386Sopenharmony_ci} 202cb93a386Sopenharmony_ci 203cb93a386Sopenharmony_cibool SkXMLParser::endElement(const char elem[]) 204cb93a386Sopenharmony_ci{ 205cb93a386Sopenharmony_ci return this->onEndElement(elem); 206cb93a386Sopenharmony_ci} 207cb93a386Sopenharmony_ci 208cb93a386Sopenharmony_cibool SkXMLParser::text(const char text[], int len) 209cb93a386Sopenharmony_ci{ 210cb93a386Sopenharmony_ci return this->onText(text, len); 211cb93a386Sopenharmony_ci} 212cb93a386Sopenharmony_ci 213cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 214cb93a386Sopenharmony_ci 215cb93a386Sopenharmony_cibool SkXMLParser::onStartElement(const char elem[]) {return false; } 216cb93a386Sopenharmony_cibool SkXMLParser::onAddAttribute(const char name[], const char value[]) {return false; } 217cb93a386Sopenharmony_cibool SkXMLParser::onEndElement(const char elem[]) { return false; } 218cb93a386Sopenharmony_cibool SkXMLParser::onText(const char text[], int len) {return false; } 219