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 void appendText(const char* txt, size_t len) { |
| 77 fBufferedText.append(txt, len); |
| 78 } |
| 79 |
| 80 SkXMLParser* fParser; |
| 81 SkAutoTCallVProc<skstd::remove_pointer_t<XML_Parser>, XML_ParserFree> fXMLPa
rser; |
| 82 |
| 83 private: |
| 84 SkString fBufferedText; |
| 85 }; |
| 86 |
| 87 #define HANDLER_CONTEXT(arg, name) ParsingContext* name = static_cast<ParsingCon
text*>(arg); |
| 88 |
62 void XMLCALL start_element_handler(void *data, const char* tag, const char** att
ributes) { | 89 void XMLCALL start_element_handler(void *data, const char* tag, const char** att
ributes) { |
63 SkXMLParser* parser = static_cast<SkXMLParser*>(data); | 90 HANDLER_CONTEXT(data, ctx); |
| 91 ctx->flushText(); |
64 | 92 |
65 parser->startElement(tag); | 93 ctx->fParser->startElement(tag); |
66 | 94 |
67 for (size_t i = 0; attributes[i]; i += 2) { | 95 for (size_t i = 0; attributes[i]; i += 2) { |
68 parser->addAttribute(attributes[i], attributes[i + 1]); | 96 ctx->fParser->addAttribute(attributes[i], attributes[i + 1]); |
69 } | 97 } |
70 } | 98 } |
71 | 99 |
72 void XMLCALL end_element_handler(void* data, const char* tag) { | 100 void XMLCALL end_element_handler(void* data, const char* tag) { |
73 static_cast<SkXMLParser*>(data)->endElement(tag); | 101 HANDLER_CONTEXT(data, ctx); |
| 102 ctx->flushText(); |
| 103 |
| 104 ctx->fParser->endElement(tag); |
| 105 } |
| 106 |
| 107 void XMLCALL text_handler(void *data, const char* txt, int len) { |
| 108 HANDLER_CONTEXT(data, ctx); |
| 109 |
| 110 ctx->appendText(txt, SkTo<size_t>(len)); |
| 111 } |
| 112 |
| 113 void XMLCALL entity_decl_handler(void *data, |
| 114 const XML_Char *entityName, |
| 115 int is_parameter_entity, |
| 116 const XML_Char *value, |
| 117 int value_length, |
| 118 const XML_Char *base, |
| 119 const XML_Char *systemId, |
| 120 const XML_Char *publicId, |
| 121 const XML_Char *notationName) { |
| 122 HANDLER_CONTEXT(data, ctx); |
| 123 |
| 124 SkDebugf("'%s' entity declaration found, stopping processing", entityName); |
| 125 XML_StopParser(ctx->fXMLParser, XML_FALSE); |
74 } | 126 } |
75 | 127 |
76 } // anonymous namespace | 128 } // anonymous namespace |
77 | 129 |
78 SkXMLParser::SkXMLParser(SkXMLParserError* parserError) : fParser(nullptr), fErr
or(parserError) | 130 SkXMLParser::SkXMLParser(SkXMLParserError* parserError) : fParser(nullptr), fErr
or(parserError) |
79 { | 131 { |
80 } | 132 } |
81 | 133 |
82 SkXMLParser::~SkXMLParser() | 134 SkXMLParser::~SkXMLParser() |
83 { | 135 { |
84 } | 136 } |
85 | 137 |
86 bool SkXMLParser::parse(SkStream& docStream) | 138 bool SkXMLParser::parse(SkStream& docStream) |
87 { | 139 { |
88 SkAutoTCallVProc<skstd::remove_pointer_t<XML_Parser>, XML_ParserFree> | 140 ParsingContext ctx(this); |
89 parser(XML_ParserCreate_MM(nullptr, &sk_XML_alloc, nullptr)); | 141 if (!ctx.fXMLParser) { |
90 if (!parser) { | |
91 SkDebugf("could not create XML parser\n"); | 142 SkDebugf("could not create XML parser\n"); |
92 return false; | 143 return false; |
93 } | 144 } |
94 | 145 |
95 XML_SetUserData(parser, this); | 146 XML_SetUserData(ctx.fXMLParser, &ctx); |
96 XML_SetElementHandler(parser, start_element_handler, end_element_handler); | 147 XML_SetElementHandler(ctx.fXMLParser, start_element_handler, end_element_han
dler); |
| 148 XML_SetCharacterDataHandler(ctx.fXMLParser, text_handler); |
| 149 |
| 150 // Disable entity processing, to inhibit internal entity expansion. See expa
t CVE-2013-0340. |
| 151 XML_SetEntityDeclHandler(ctx.fXMLParser, entity_decl_handler); |
97 | 152 |
98 static const int kBufferSize = 512 SkDEBUGCODE( - 507); | 153 static const int kBufferSize = 512 SkDEBUGCODE( - 507); |
99 bool done = false; | 154 bool done = false; |
100 do { | 155 do { |
101 void* buffer = XML_GetBuffer(parser, kBufferSize); | 156 void* buffer = XML_GetBuffer(ctx.fXMLParser, kBufferSize); |
102 if (!buffer) { | 157 if (!buffer) { |
103 SkDebugf("could not buffer enough to continue\n"); | 158 SkDebugf("could not buffer enough to continue\n"); |
104 return false; | 159 return false; |
105 } | 160 } |
106 | 161 |
107 size_t len = docStream.read(buffer, kBufferSize); | 162 size_t len = docStream.read(buffer, kBufferSize); |
108 done = docStream.isAtEnd(); | 163 done = docStream.isAtEnd(); |
109 XML_Status status = XML_ParseBuffer(parser, SkToS32(len), done); | 164 XML_Status status = XML_ParseBuffer(ctx.fXMLParser, SkToS32(len), done); |
110 if (XML_STATUS_ERROR == status) { | 165 if (XML_STATUS_ERROR == status) { |
111 XML_Error error = XML_GetErrorCode(parser); | 166 XML_Error error = XML_GetErrorCode(ctx.fXMLParser); |
112 int line = XML_GetCurrentLineNumber(parser); | 167 int line = XML_GetCurrentLineNumber(ctx.fXMLParser); |
113 int column = XML_GetCurrentColumnNumber(parser); | 168 int column = XML_GetCurrentColumnNumber(ctx.fXMLParser); |
114 const XML_LChar* errorString = XML_ErrorString(error); | 169 const XML_LChar* errorString = XML_ErrorString(error); |
115 SkDebugf("parse error @%d:%d: %d (%s).\n", line, column, error, erro
rString); | 170 SkDebugf("parse error @%d:%d: %d (%s).\n", line, column, error, erro
rString); |
116 return false; | 171 return false; |
117 } | 172 } |
118 } while (!done); | 173 } while (!done); |
119 | 174 |
120 return true; | 175 return true; |
121 } | 176 } |
122 | 177 |
123 bool SkXMLParser::parse(const char doc[], size_t len) | 178 bool SkXMLParser::parse(const char doc[], size_t len) |
(...skipping 26 matching lines...) Expand all Loading... |
150 { | 205 { |
151 return this->onText(text, len); | 206 return this->onText(text, len); |
152 } | 207 } |
153 | 208 |
154 //////////////////////////////////////////////////////////////////////////////// | 209 //////////////////////////////////////////////////////////////////////////////// |
155 | 210 |
156 bool SkXMLParser::onStartElement(const char elem[]) {return false; } | 211 bool SkXMLParser::onStartElement(const char elem[]) {return false; } |
157 bool SkXMLParser::onAddAttribute(const char name[], const char value[]) {return
false; } | 212 bool SkXMLParser::onAddAttribute(const char name[], const char value[]) {return
false; } |
158 bool SkXMLParser::onEndElement(const char elem[]) { return false; } | 213 bool SkXMLParser::onEndElement(const char elem[]) { return false; } |
159 bool SkXMLParser::onText(const char text[], int len) {return false; } | 214 bool SkXMLParser::onText(const char text[], int len) {return false; } |
OLD | NEW |