libxml2_xml_pushparser_fuzzer.cc
1 // Copyright 2015 The Chromium Authors. All rights reserved. 2 // Copyright 2017 Apple Inc. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 6 #include <cassert> 7 #include <cstddef> 8 #include <cstdint> 9 10 #include <functional> 11 #include <limits> 12 #include <string> 13 14 #include "libxml/parser.h" 15 #include "libxml/xmlsave.h" 16 17 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size); 18 19 static void ignore (void* ctx, const char* msg, ...) { 20 // Error handler to avoid spam of error messages from libxml parser. 21 } 22 23 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { 24 xmlSetGenericErrorFunc(NULL, &ignore); 25 26 assert(size < std::numeric_limits<int>::max()); 27 int intSize = static_cast<int>(size); 28 29 // Test default empty options value and some random combination. 30 std::string data_string(reinterpret_cast<const char*>(data), size); 31 const std::size_t data_hash = std::hash<std::string>()(data_string); 32 const int max_option_value = std::numeric_limits<int>::max(); 33 const int random_option_value = data_hash % max_option_value; 34 const int options[] = {0, random_option_value}; 35 36 int initialChunkSize = std::min<int>(4, intSize); 37 int chunkSize = std::max<int>(100, std::min<int>(data_hash % 1024, intSize)); 38 39 for (const auto option_value : options) { 40 if (auto ctxt = xmlCreatePushParserCtxt(NULL, NULL, (const char *)data, initialChunkSize, "noname.xml")) { 41 xmlCtxtUseOptions(ctxt, option_value | XML_PARSE_NONET); 42 int cur = initialChunkSize; 43 do { 44 if (cur + chunkSize >= size) { 45 xmlParseChunk(ctxt, (const char *)data + cur, intSize - cur, 1); 46 break; 47 } else { 48 xmlParseChunk(ctxt, (const char *)data + cur, chunkSize, 0); 49 cur += chunkSize; 50 } 51 } while (cur < size); 52 auto doc = ctxt->myDoc; 53 xmlFreeParserCtxt(ctxt); 54 55 auto buf = xmlBufferCreate(); 56 assert(buf); 57 auto ctxtSave = xmlSaveToBuffer(buf, NULL, 0); 58 xmlSaveDoc(ctxtSave, doc); 59 xmlSaveClose(ctxtSave); 60 xmlFreeDoc(doc); 61 xmlBufferFree(buf); 62 } 63 } 64 65 return 0; 66 }