| 122 | XMLParser::~XMLParser() = default; |
| 123 | |
| 124 | bool XMLParser::parse(Stream& stream) { |
| 125 | ParsingContext parsingContext(this); |
| 126 | if (!parsingContext._XMLParser) { |
| 127 | LOGE("could not create XML parser\n"); |
| 128 | return false; |
| 129 | } |
| 130 | |
| 131 | // Avoid calls to rand_s if this is not set. This seed helps prevent DOS |
| 132 | // with a known hash sequence so an address is sufficient. The provided |
| 133 | // seed should not be zero as that results in a call to rand_s. |
| 134 | auto seed = static_cast<unsigned long>(reinterpret_cast<size_t>(HASH_SEED) & 0xFFFFFFFF); |
| 135 | XML_SetHashSalt(parsingContext._XMLParser, seed ? seed : 1); |
| 136 | |
| 137 | XML_SetUserData(parsingContext._XMLParser, &parsingContext); |
| 138 | XML_SetElementHandler(parsingContext._XMLParser, start_element_handler, end_element_handler); |
| 139 | XML_SetCharacterDataHandler(parsingContext._XMLParser, text_handler); |
| 140 | |
| 141 | // Disable entity processing, to inhibit internal entity expansion. See expat CVE-2013-0340. |
| 142 | XML_SetEntityDeclHandler(parsingContext._XMLParser, entity_decl_handler); |
| 143 | |
| 144 | XML_Status status = XML_STATUS_OK; |
| 145 | if (stream.getMemoryBase() && stream.size() != 0) { |
| 146 | const char* base = reinterpret_cast<const char*>(stream.getMemoryBase()); |
| 147 | status = XML_Parse(parsingContext._XMLParser, base, static_cast<int>(stream.size()), true); |
| 148 | } else { |
| 149 | static constexpr int BUFFER_SIZE = 4096; |
| 150 | bool done = false; |
| 151 | size_t length = stream.size(); |
| 152 | size_t currentPos = 0; |
| 153 | do { |
| 154 | void* buffer = XML_GetBuffer(parsingContext._XMLParser, BUFFER_SIZE); |
| 155 | if (!buffer) { |
| 156 | return false; |
| 157 | } |
| 158 | |
| 159 | size_t readLength = stream.read(buffer, BUFFER_SIZE); |
| 160 | currentPos += readLength; |
| 161 | done = currentPos >= length; |
| 162 | status = XML_ParseBuffer(parsingContext._XMLParser, static_cast<int>(readLength), done); |
| 163 | if (XML_STATUS_ERROR == status) { |
| 164 | break; |
| 165 | } |
| 166 | } while (!done); |
| 167 | } |
| 168 | return XML_STATUS_ERROR != status; |
| 169 | } |
| 170 | |
| 171 | bool XMLParser::startElement(const std::string& element) { |
| 172 | return this->onStartElement(element); |
no test coverage detected