OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "expat.h" | 8 #include "expat.h" |
9 | 9 |
10 #include "SkStream.h" | 10 #include "SkStream.h" |
11 #include "SkString.h" | |
12 #include "SkTypes.h" | |
11 #include "SkXMLParser.h" | 13 #include "SkXMLParser.h" |
12 | 14 |
13 static char const* const gErrorStrings[] = { | 15 static char const* const gErrorStrings[] = { |
14 "empty or missing file ", | 16 "empty or missing file ", |
15 "unknown element ", | 17 "unknown element ", |
16 "unknown attribute name ", | 18 "unknown attribute name ", |
17 "error in attribute value ", | 19 "error in attribute value ", |
18 "duplicate ID ", | 20 "duplicate ID ", |
19 "unknown error " | 21 "unknown error " |
20 }; | 22 }; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
52 //////////////// | 54 //////////////// |
53 | 55 |
54 namespace { | 56 namespace { |
55 | 57 |
56 const XML_Memory_Handling_Suite sk_XML_alloc = { | 58 const XML_Memory_Handling_Suite sk_XML_alloc = { |
57 sk_malloc_throw, | 59 sk_malloc_throw, |
58 sk_realloc_throw, | 60 sk_realloc_throw, |
59 sk_free | 61 sk_free |
60 }; | 62 }; |
61 | 63 |
64 struct ParsingContext { | |
65 ParsingContext(SkXMLParser* parser) | |
66 : fParser(parser) | |
67 , fXMLParser(XML_ParserCreate_MM(nullptr, &sk_XML_alloc, nullptr)) { } | |
68 | |
69 void flushText() { | |
70 if (!fBufferedText.isEmpty()) { | |
71 fParser->text(fBufferedText.c_str(), SkTo<int>(fBufferedText.size()) ); | |
72 fBufferedText.reset(); | |
73 } | |
74 } | |
75 | |
76 SkXMLParser* fParser; | |
77 SkAutoTCallVProc<skstd::remove_pointer_t<XML_Parser>, XML_ParserFree> fXMLPa rser; | |
robertphillips
2016/07/18 15:29:18
private: ?
f(malita)
2016/07/18 17:36:32
Done.
| |
78 SkString fBufferedText; | |
79 }; | |
80 | |
62 void XMLCALL start_element_handler(void *data, const char* tag, const char** att ributes) { | 81 void XMLCALL start_element_handler(void *data, const char* tag, const char** att ributes) { |
63 SkXMLParser* parser = static_cast<SkXMLParser*>(data); | 82 ParsingContext* ctx = static_cast<ParsingContext*>(data); |
83 ctx->flushText(); | |
64 | 84 |
65 parser->startElement(tag); | 85 ctx->fParser->startElement(tag); |
66 | 86 |
67 for (size_t i = 0; attributes[i]; i += 2) { | 87 for (size_t i = 0; attributes[i]; i += 2) { |
68 parser->addAttribute(attributes[i], attributes[i + 1]); | 88 ctx->fParser->addAttribute(attributes[i], attributes[i + 1]); |
69 } | 89 } |
70 } | 90 } |
71 | 91 |
72 void XMLCALL end_element_handler(void* data, const char* tag) { | 92 void XMLCALL end_element_handler(void* data, const char* tag) { |
73 static_cast<SkXMLParser*>(data)->endElement(tag); | 93 ParsingContext* ctx = static_cast<ParsingContext*>(data); |
94 ctx->flushText(); | |
95 ctx->fParser->endElement(tag); | |
96 } | |
97 | |
98 void XMLCALL text_handler(void *data, const char* txt, int len) { | |
robertphillips
2016/07/18 15:29:18
Should be have a macro like "HANDLER_PREAMBLE(ctx)
f(malita)
2016/07/18 17:36:32
Done.
| |
99 ParsingContext* ctx = static_cast<ParsingContext*>(data); | |
100 ctx->fBufferedText.append(txt, len); | |
101 } | |
102 | |
103 void XMLCALL entity_decl_handler(void *data, | |
104 const XML_Char *entityName, | |
105 int is_parameter_entity, | |
106 const XML_Char *value, | |
107 int value_length, | |
108 const XML_Char *base, | |
109 const XML_Char *systemId, | |
110 const XML_Char *publicId, | |
111 const XML_Char *notationName) { | |
112 ParsingContext* ctx = static_cast<ParsingContext*>(data); | |
113 | |
114 SkDebugf("'%s' entity declaration found, stopping processing", entityName); | |
115 XML_StopParser(ctx->fXMLParser, XML_FALSE); | |
74 } | 116 } |
75 | 117 |
76 } // anonymous namespace | 118 } // anonymous namespace |
77 | 119 |
78 SkXMLParser::SkXMLParser(SkXMLParserError* parserError) : fParser(nullptr), fErr or(parserError) | 120 SkXMLParser::SkXMLParser(SkXMLParserError* parserError) : fParser(nullptr), fErr or(parserError) |
79 { | 121 { |
80 } | 122 } |
81 | 123 |
82 SkXMLParser::~SkXMLParser() | 124 SkXMLParser::~SkXMLParser() |
83 { | 125 { |
84 } | 126 } |
85 | 127 |
86 bool SkXMLParser::parse(SkStream& docStream) | 128 bool SkXMLParser::parse(SkStream& docStream) |
87 { | 129 { |
88 SkAutoTCallVProc<skstd::remove_pointer_t<XML_Parser>, XML_ParserFree> | 130 ParsingContext ctx(this); |
89 parser(XML_ParserCreate_MM(nullptr, &sk_XML_alloc, nullptr)); | 131 if (!ctx.fXMLParser) { |
90 if (!parser) { | |
91 SkDebugf("could not create XML parser\n"); | 132 SkDebugf("could not create XML parser\n"); |
92 return false; | 133 return false; |
93 } | 134 } |
94 | 135 |
95 XML_SetUserData(parser, this); | 136 XML_SetUserData(ctx.fXMLParser, &ctx); |
96 XML_SetElementHandler(parser, start_element_handler, end_element_handler); | 137 XML_SetElementHandler(ctx.fXMLParser, start_element_handler, end_element_han dler); |
138 XML_SetCharacterDataHandler(ctx.fXMLParser, text_handler); | |
139 | |
140 // Disable entity processing, to inhibit internal entity expansion. See expa t CVE-2013-0340. | |
141 XML_SetEntityDeclHandler(ctx.fXMLParser, entity_decl_handler); | |
97 | 142 |
98 static const int kBufferSize = 512 SkDEBUGCODE( - 507); | 143 static const int kBufferSize = 512 SkDEBUGCODE( - 507); |
99 bool done = false; | 144 bool done = false; |
100 do { | 145 do { |
101 void* buffer = XML_GetBuffer(parser, kBufferSize); | 146 void* buffer = XML_GetBuffer(ctx.fXMLParser, kBufferSize); |
102 if (!buffer) { | 147 if (!buffer) { |
103 SkDebugf("could not buffer enough to continue\n"); | 148 SkDebugf("could not buffer enough to continue\n"); |
104 return false; | 149 return false; |
105 } | 150 } |
106 | 151 |
107 size_t len = docStream.read(buffer, kBufferSize); | 152 size_t len = docStream.read(buffer, kBufferSize); |
108 done = docStream.isAtEnd(); | 153 done = docStream.isAtEnd(); |
109 XML_Status status = XML_ParseBuffer(parser, SkToS32(len), done); | 154 XML_Status status = XML_ParseBuffer(ctx.fXMLParser, SkToS32(len), done); |
110 if (XML_STATUS_ERROR == status) { | 155 if (XML_STATUS_ERROR == status) { |
111 XML_Error error = XML_GetErrorCode(parser); | 156 XML_Error error = XML_GetErrorCode(ctx.fXMLParser); |
112 int line = XML_GetCurrentLineNumber(parser); | 157 int line = XML_GetCurrentLineNumber(ctx.fXMLParser); |
113 int column = XML_GetCurrentColumnNumber(parser); | 158 int column = XML_GetCurrentColumnNumber(ctx.fXMLParser); |
114 const XML_LChar* errorString = XML_ErrorString(error); | 159 const XML_LChar* errorString = XML_ErrorString(error); |
115 SkDebugf("parse error @%d:%d: %d (%s).\n", line, column, error, erro rString); | 160 SkDebugf("parse error @%d:%d: %d (%s).\n", line, column, error, erro rString); |
116 return false; | 161 return false; |
117 } | 162 } |
118 } while (!done); | 163 } while (!done); |
119 | 164 |
120 return true; | 165 return true; |
121 } | 166 } |
122 | 167 |
123 bool SkXMLParser::parse(const char doc[], size_t len) | 168 bool SkXMLParser::parse(const char doc[], size_t len) |
(...skipping 26 matching lines...) Expand all Loading... | |
150 { | 195 { |
151 return this->onText(text, len); | 196 return this->onText(text, len); |
152 } | 197 } |
153 | 198 |
154 //////////////////////////////////////////////////////////////////////////////// | 199 //////////////////////////////////////////////////////////////////////////////// |
155 | 200 |
156 bool SkXMLParser::onStartElement(const char elem[]) {return false; } | 201 bool SkXMLParser::onStartElement(const char elem[]) {return false; } |
157 bool SkXMLParser::onAddAttribute(const char name[], const char value[]) {return false; } | 202 bool SkXMLParser::onAddAttribute(const char name[], const char value[]) {return false; } |
158 bool SkXMLParser::onEndElement(const char elem[]) { return false; } | 203 bool SkXMLParser::onEndElement(const char elem[]) { return false; } |
159 bool SkXMLParser::onText(const char text[], int len) {return false; } | 204 bool SkXMLParser::onText(const char text[], int len) {return false; } |
OLD | NEW |