Project: tinyxml2 (leethomason/tinyxml2), language: c++
Vulnerability instance: tinyxml2.cve-2018-11210
Sanitizer: address

================= Bug Report (1/3) ==================
## Source: GitHub Issue
## URL: https://github.com/leethomason/tinyxml2/issues/675
## Description:
Issue: leethomason/tinyxml2#675
Title: heap-buffer-overflow Error In tinyxml2.cpp:2286::strlen()
State: closed
Created by: EnchantedJohn
Created at: 2018-05-16 02:05:16+00:00

Issue Body:
hello！I use libfuzzer to test XMLDocument::parse().then I meet heap-buffer-overflow Error.I think it is due to tinyxml2.cpp:2286 strlen().because function strlen() lead to heap-buffer-overflow.



Comments:
Comment by EnchantedJohn on 2018-05-16 02:06:25+00:00:
then I want to show my example of libfuzzer.
```
#include "tinyxml2.h"

#include <stdint.h>

extern "C" int LLVMFuzzerTestOneInput(const char *Data, size_t Size)
{
    tinyxml2::XMLDocument doc;
    doc.Parse(Data);
    return doc.ErrorID();
}
```

---

Comment by EnchantedJohn on 2018-05-16 02:07:08+00:00:
then this is the error information.
```
`INFO: Seed: 4187962468
INFO: Loaded 1 modules   (3 inline 8-bit counters): 3 [0x79ef60, 0x79ef63), 
INFO: Loaded 1 PC tables (3 PCs): 3 [0x57a7c0,0x57a7f0), 
INFO:        0 files found in corpus1/
=================================================================
==53936==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000051 at pc 0x00000049c574 bp 0x7fff76bae7c0 sp 0x7fff76badf70
READ of size 2 at 0x602000000051 thread T0
    #0 0x49c573 in strlen /home/lx/5_4/llvm/projects/compiler-rt/lib/asan/../sanitizer_common/sanitizer_common_interceptors.inc:343
    #1 0x7fa080dbecdf in tinyxml2::XMLDocument::Parse(char const*, unsigned long) (/usr/local/lib/libtinyxml2.so.6+0xccdf)
    #2 0x55d3e0 in LLVMFuzzerTestOneInput /home/lx/5_15/tinyxml2/tinyxml2-master/fuzz_test/fuzz_parse.cpp:8:9
    #3 0x42d3b7 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /home/lx/5_4/llvm/projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:515
    #4 0x4322b8 in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::vector<std::string, fuzzer::fuzzer_allocator<std::string> > const&) /home/lx/5_4/llvm/projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:701
    #5 0x432c62 in fuzzer::Fuzzer::Loop(std::vector<std::string, fuzzer::fuzzer_allocator<std::string> > const&) /home/lx/5_4/llvm/projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:739
    #6 0x427534 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /home/lx/5_4/llvm/projects/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:754
    #7 0x41d992 in main /home/lx/5_4/llvm/projects/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20
    #8 0x7fa07fec3f44 in __libc_start_main /build/eglibc-ripdx6/eglibc-2.19/csu/libc-start.c:287
    #9 0x41d9fb in _start (/home/lx/5_15/tinyxml2/tinyxml2-master/fuzz_test/fuzz_parse+0x41d9fb)

0x602000000051 is located 0 bytes to the right of 1-byte region [0x602000000050,0x602000000051)
allocated by thread T0 here:
    #0 0x559148 in operator new[](unsigned long) /home/lx/5_4/llvm/projects/compiler-rt/lib/asan/asan_new_delete.cc:95
    #1 0x42d2f9 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /home/lx/5_4/llvm/projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:506
    #2 0x4322b8 in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::vector<std::string, fuzzer::fuzzer_allocator<std::string> > const&) /home/lx/5_4/llvm/projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:701
    #3 0x432c62 in fuzzer::Fuzzer::Loop(std::vector<std::string, fuzzer::fuzzer_allocator<std::string> > const&) /home/lx/5_4/llvm/projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:739
    #4 0x427534 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /home/lx/5_4/llvm/projects/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:754
    #5 0x41d992 in main /home/lx/5_4/llvm/projects/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20
    #6 0x7fa07fec3f44 in __libc_start_main /build/eglibc-ripdx6/eglibc-2.19/csu/libc-start.c:287

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/lx/5_4/llvm/projects/compiler-rt/lib/asan/../sanitizer_common/sanitizer_common_interceptors.inc:343 in strlen
Shadow bytes around the buggy address:
  0x0c047fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c047fff8000: fa fa 00 fa fa fa 00 fa fa fa[01]fa fa fa fa fa
  0x0c047fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==53936==ABORTING
MS: 0 ; base unit: 0000000000000000000000000000000000000000


artifact_prefix='./'; Test unit written to ./crash-da39a3ee5e6b4b0d3255bfef95601890afd80709
Base64:`
```

---

Comment by EnchantedJohn on 2018-05-16 02:09:08+00:00:
the strlen() in tinyxml2.cpp:

```
XMLError XMLDocument::Parse( const char* p, size_t len )
{
    Clear();

    if ( len == 0 || !p || !*p ) {
        SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); 
        return _errorID;
    }    
    if ( len == (size_t)(-1) ) {
        len = strlen( p ); 
    }    
    TIXMLASSERT( _charBuffer == 0 ); 
    _charBuffer = new char[ len+1 ];
    memcpy( _charBuffer, p, len );
    _charBuffer[len] = 0; 

    Parse();
    if ( Error() ) {
        // clean up now essentially dangling memory.
        // and the parse fail can put objects in the
        // pools that are dead and inaccessible.
        DeleteChildren();
        _elementPool.Clear();
        _attributePool.Clear();
        _textPool.Clear();
        _commentPool.Clear();
    }    
    return _errorID;
}
```

---

Comment by carnil on 2018-05-16 20:20:27+00:00:
This issue has been assigned CVE-2018-11210

---

Comment by EnchantedJohn on 2018-05-17 02:12:15+00:00:
OK,I will close this Issues.

---

Comment by kbabioch on 2018-05-17 08:43:57+00:00:
Why was the issue closed? What is the fixing commit?

---

Comment by leethomason on 2018-05-17 23:21:36+00:00:
Re-opening. I don't track all the external bug sites, so it's better to have here.

---

Comment by leethomason on 2018-05-17 23:22:07+00:00:
Although an actual test case would be great.

---

Comment by leethomason on 2018-05-17 23:24:23+00:00:
But that is a bug; strlen() search should be bound by the buffer length.

---

Comment by leethomason on 2018-05-17 23:45:19+00:00:
This one worries me; initial patch here: https://github.com/leethomason/tinyxml2/compare/strlen
Note that my current editor is trimming whitespace, so some extra lines get picked up.

---

Comment by leethomason on 2018-05-18 21:50:31+00:00:
Despite some misguided hacking on my part, I'm pretty sure there is no fixing this. I suspect it comes from passing a bad `len` to the parse - which the underlying code can't handle - or a -1 for length and a string that isn't null terminated - which the underlying code can't handle.

If there is a crash here that isn't an incorrect use of the API, I'd like a test case, else it isn't technically a bug.

---

Comment by VictorRodriguez on 2018-08-02 16:01:59+00:00:
@leethomason due to the severity of CVE-2018-11210 can we take your patches from https://github.com/leethomason/tinyxml2/compare/strlen ? 

---

Comment by leethomason on 2018-08-02 16:15:15+00:00:
The patches don't fix the issue. If there are correct inputs, I never found a bug. (Or a practical way to defend against bad inputs.) I don't think there's a bug if the 'len' is correctly specified.

---

Comment by dodjiseketeli on 2018-11-16 16:18:55+00:00:
Hello,

> The patches don't fix the issue. If there are correct inputs, I never found a bug. (Or a practical way to defend against bad inputs.) I don't think there's a bug if the 'len' is correctly specified.

Would you accept a patch that uses strnlen to read a maximum of 4K bytes when no size is specified for XMLDocument::parse()?  The 4K bytes size comes from the fact that it's the default virtual memory page size on GNU/Linux.   Of course, when the user wants to read more that a maximum of 4K, she can specify the size she wants.

The patch would be this one: https://github.com/dodjiseketeli/tinyxml2/commit/665535a022013ea3ead3c0fae15f0bc8ca46b24c

---

Comment by Dmitry-Me on 2018-11-18 09:08:21+00:00:
This 4K limitation makes no sense either. What if the user wants to parse a string tail only? Then the substring to parse will not start at page length.

---

Comment by leethomason on 2018-11-19 01:28:25+00:00:
I agree with @Dmitry-Me that the limit doesn't make sense. 
@dodjiseketeli this is C++, if you pass bad inputs, it will crash, like any library in C++. What are you trying to solve?

---

Comment by dodjiseketeli on 2018-11-19 06:42:14+00:00:
I am not trying to prevent the program from crashing in case if bad input.
I am trying to avoid the program from *reading* an undetermined length of
data, just because the *end user* (not the programmer who used tinyxml)
passed unexpected input data: for instance, a small buffer that contains no
zero.  In that case tinyxml should stop its execution in a predictable way
and not read data that it should not read.  Otherwise it's not just a crash
it's a security issue that can be used for a buffer read overflow attack.

Said otherwise, I think that the parse method should always require a
length and never assume that there is going to be a zero in the input
string. Otherwise it's "easy" for the programmer using tinyxml to misuse it
by calling it with the -1 length argument, thinking "tinyxml will figure
out the length".  And yet the end user passing an unexpected buffer (that
is obviously not proper xml) would cause that strlen to read an
unexpectedly long amount of data.

My problem is that I cannot change the API today to avoid the -1 case that
requires the buffer to end with zero.  *You* can do that in the future
versions.  Would you agree to do that?

So I am proposing a middle ground where programmers using tinyxml still use
the api with the -1 length (for now), but where the amount of unexpected
data read in case the end user providing unexpected input is bounded, if
not very small.

In any case I think we should do something.  An unexpected end-user input
should never cause a buffer overflow, IMHO.





Le 19 nov. 2018 02:33, "Lee Thomason" <notifications@github.com> a écrit :

I agree with @Dmitry-Me <https://github.com/Dmitry-Me> that the limit
doesn't make sense.
@dodjiseketeli <https://github.com/dodjiseketeli> this is C++, if you pass
bad inputs, it will crash, like any library in C++. What are you trying to
solve?

—
You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub
<https://github.com/leethomason/tinyxml2/issues/675#issuecomment-439745816>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AL6n10Qqn_YKiicQC2sMNRG3pGPobxrqks5uwglAgaJpZM4UAiQp>
.


---

Comment by Dmitry-Me on 2018-11-19 11:48:36+00:00:
@dodjiseketeli This is something unreasonable. A user passing a `const char*` into a C++ function and expecting the function to figure out the length is expecting too much. The contract is clear - either specify the length yourself or ensure that the data is properly null-terminated. Failing to null-terminate the data is the same as specifying too much of length - that's just malformed data being passed.

---

Comment by dodjiseketeli on 2018-11-19 14:03:37+00:00:
Just so I am sure to understand: Do you find it OK that just because the
end-user of a program invokes the program with unexpected data, the program
ends up reading *more* than said data in a undefined manner, (Read buffer
overflow) and thus causes a security issue?

Le lun. 19 nov. 2018 à 12:48, Dmitry-Me <notifications@github.com> a écrit :

> @dodjiseketeli <https://github.com/dodjiseketeli> This is something
> unreasonable. A user passing a const char* into a C++ function and
> expecting the function to figure out the length is expecting too much. The
> contract is clear - either specify the length yourself and ensure that the
> data is properly null-terminated. Failing to null-terminate the data is the
> same as specifying too much of length - that's just malformed data being
> passed.
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <https://github.com/leethomason/tinyxml2/issues/675#issuecomment-439867003>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AL6n1-oMhcLO0iUQ3xea1a97q2tzmsPxks5uwpqcgaJpZM4UAiQp>
> .
>


---

Comment by dodjiseketeli on 2018-11-19 15:32:23+00:00:
Anyway, I don't feel strong about this.  I just thought I'd ask you guys if you'd agree to tighten the API a little more.

I agree that in principle, the author of the fuzzing input test did mis-use the API.  She or he should have forced the fuzzing program to pass in the size of the input buffer.  My gut feeling is that the default argument -1 (for the size) makes it a little too easy to mis-use the API, as opposed to forcing the caller to always specify the size, but hey, that is just a design decision and I agree that stricto sensu, the test is failing because of a pre-condition violation.

So please do not feel to strong about this either.  If you feel like you don't want to change the API in the future, then I am fine with your decision.  I just wanted to make sure.

Thanks for your time!

---

Comment by Dmitry-Me on 2018-11-19 19:59:15+00:00:
It's the same as passing a buffer and a positive length which is "too large". 30 bytes data buffer and `41` as length for example. Do this and you face undefined behavior.

---

Comment by ghost on 2019-02-11 00:00:09+00:00:
I agree with @leethomason and @Dmitry-Me. The fuzzing test was the buggy "program" that allowed "end user" (libfuzzer in this instance) to cause the buffer to be over read. If instead of the Parse function there would be direct invocation of the strlen function with the otherwise same implementation of the test, would it lead to the CVE being filled for the C standard library?

There is this thread about writing fuzzer test for the APIs that require C string in the buffer: [libFuzzer: add an option to always null-terminate?](http://lists.llvm.org/pipermail/llvm-dev/2017-August/116114.html) The test program should have either use the suggested in this llvm thread aproach to update the buffer to be NULL terminated or call the Parse with 2 parameters.

If any change on the tinyxml2 side I might tend to suggest removing optional parameter and instead providing 2 functions Parse(const char* c_string) and Parse(const char* data, size_t size). It would provide the same flexibility but would indicate (more strongly - because the API description is already clear) what is expected when calling the Parse with either one or two parameters.



---

Comment by ghost on 2019-02-11 12:11:05+00:00:
Just for reference fixed fuzzer tests would look like this:

```C++
#include "tinyxml2.h"

#include <stdint.h>

extern "C" int LLVMFuzzerTestOneInput(const char *Data, size_t Size)
{
    tinyxml2::XMLDocument doc;
    doc.Parse(Data, Size);
    return doc.ErrorID();
}
```
OR

```C++
#include "tinyxml2.h"

#include <stdint.h>
#include <string>

extern "C" int LLVMFuzzerTestOneInput(const char *Data, size_t Size)
{
    tinyxml2::XMLDocument doc;
    std::string data_string(Data, Size);
    doc.Parse(data_string.c_str());
    return doc.ErrorID();
}
```
On a side note I have submitted request to reject the CVE-2018-11210.


---

Comment by chennyu on 2019-03-05 09:39:55+00:00:
> Just for reference fixed fuzzer tests would look like this:
> 
> ```c++
> #include "tinyxml2.h"
> 
> #include <stdint.h>
> 
> extern "C" int LLVMFuzzerTestOneInput(const char *Data, size_t Size)
> {
>     tinyxml2::XMLDocument doc;
>     doc.Parse(Data, Size);
>     return doc.ErrorID();
> }
> ```
> 
> OR
> 
> ```c++
> #include "tinyxml2.h"
> 
> #include <stdint.h>
> #include <string>
> 
> extern "C" int LLVMFuzzerTestOneInput(const char *Data, size_t Size)
> {
>     tinyxml2::XMLDocument doc;
>     std::string data_string(Data, Size);
>     doc.Parse(data_string.c_str());
>     return doc.ErrorID();
> }
> ```
> 
> On a side note I have submitted request to reject the CVE-2018-11210.

Hi, has CVE-2018-11210 beed cancelled? I found it still exist in NVD.

---

Comment by mssalvatore on 2019-07-30 13:36:21+00:00:
> On a side note I have submitted request to reject the CVE-2018-11210.

@kurylo, have you received any response from MITRE?

---

Comment by ghost on 2019-08-08 12:38:21+00:00:
No response from MITRE.

---

Comment by mssalvatore on 2019-08-09 16:54:55+00:00:
@kurylo, I was able to get MITRE to mark this CVE as "[disputed](https://cve.mitre.org/about/faqs.html#disputed_signify_in_cve_entry)". The CVE in entry in MITRE should be updated to reflect this within the next few hours.

Commit References:
da39a3ee5e6b4b0d3255bfef95601890afd80709
0000000000000000000000000000000000000000
665535a022013ea3ead3c0fae15f0bc8ca46b24c

================= Bug Report (2/3) ==================
## Source: GitHub Issue
## URL: https://github.com/leethomason/tinyxml2/issues/675#issuecomment-439933437
## Description:
Issue: leethomason/tinyxml2#675
Title: heap-buffer-overflow Error In tinyxml2.cpp:2286::strlen()
Referenced comment by dodjiseketeli on 2018-11-19 15:32:23+00:00:

Anyway, I don't feel strong about this.  I just thought I'd ask you guys if you'd agree to tighten the API a little more.

I agree that in principle, the author of the fuzzing input test did mis-use the API.  She or he should have forced the fuzzing program to pass in the size of the input buffer.  My gut feeling is that the default argument -1 (for the size) makes it a little too easy to mis-use the API, as opposed to forcing the caller to always specify the size, but hey, that is just a design decision and I agree that stricto sensu, the test is failing because of a pre-condition violation.

So please do not feel to strong about this either.  If you feel like you don't want to change the API in the future, then I am fine with your decision.  I just wanted to make sure.

Thanks for your time!

================= Bug Report (3/3) ==================
## Source: GitHub Issue
## URL: https://github.com/leethomason/tinyxml2/issues/675#issuecomment-462194018
## Description:
Issue: leethomason/tinyxml2#675
Title: heap-buffer-overflow Error In tinyxml2.cpp:2286::strlen()
Referenced comment by ghost on 2019-02-11 00:00:09+00:00:

I agree with @leethomason and @Dmitry-Me. The fuzzing test was the buggy "program" that allowed "end user" (libfuzzer in this instance) to cause the buffer to be over read. If instead of the Parse function there would be direct invocation of the strlen function with the otherwise same implementation of the test, would it lead to the CVE being filled for the C standard library?

There is this thread about writing fuzzer test for the APIs that require C string in the buffer: [libFuzzer: add an option to always null-terminate?](http://lists.llvm.org/pipermail/llvm-dev/2017-August/116114.html) The test program should have either use the suggested in this llvm thread aproach to update the buffer to be NULL terminated or call the Parse with 2 parameters.

If any change on the tinyxml2 side I might tend to suggest removing optional parameter and instead providing 2 functions Parse(const char* c_string) and Parse(const char* data, size_t size). It would provide the same flexibility but would indicate (more strongly - because the API description is already clear) what is expected when calling the Parse with either one or two parameters.



Build script:
#!/bin/bash
# Minimized build script with only core build commands
set -eu
make -j$(nproc) clean
make -j$(nproc) all

Dockerfile:
FROM hwiwonlee/secb.base:latest
RUN apt-get update && apt-get install -y make autoconf automake libtool pkg-config
RUN git clone https://github.com/leethomason/tinyxml2 tinyxml2
RUN git -C tinyxml2 checkout c1424ee4e1c1ed8129d9147ccc920ab92dd9ef86
WORKDIR $SRC/tinyxml2
COPY build.sh $SRC/

Additional files:
filename: xml.dict
content: # Copyright 2016 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
################################################################################
#
# AFL dictionary for XML
# ----------------------
#
# Several basic syntax elements and attributes, modeled on libxml2.
#
# Created by Michal Zalewski <lcamtuf@google.com>
#

attr_encoding=" encoding=\"1\""
attr_generic=" a=\"1\""
attr_href=" href=\"1\""
attr_standalone=" standalone=\"no\""
attr_version=" version=\"1\""
attr_xml_base=" xml:base=\"1\""
attr_xml_id=" xml:id=\"1\""
attr_xml_lang=" xml:lang=\"1\""
attr_xml_space=" xml:space=\"1\""
attr_xmlns=" xmlns=\"1\""

entity_builtin="&lt;"
entity_decimal="&#1;"
entity_external="&a;"
entity_hex="&#x1;"

string_any="ANY"
string_brackets="[]"
string_cdata="CDATA"
string_col_fallback=":fallback"
string_col_generic=":a"
string_col_include=":include"
string_dashes="--"
string_empty="EMPTY"
string_empty_dblquotes="\"\""
string_empty_quotes="''"
string_entities="ENTITIES"
string_entity="ENTITY"
string_fixed="#FIXED"
string_id="ID"
string_idref="IDREF"
string_idrefs="IDREFS"
string_implied="#IMPLIED"
string_nmtoken="NMTOKEN"
string_nmtokens="NMTOKENS"
string_notation="NOTATION"
string_parentheses="()"
string_pcdata="#PCDATA"
string_percent="%a"
string_public="PUBLIC"
string_required="#REQUIRED"
string_schema=":schema"
string_system="SYSTEM"
string_ucs4="UCS-4"
string_utf16="UTF-16"
string_utf8="UTF-8"
string_xmlns="xmlns:"

tag_attlist="<!ATTLIST"
tag_cdata="<![CDATA["
tag_close="</a>"
tag_doctype="<!DOCTYPE"
tag_element="<!ELEMENT"
tag_entity="<!ENTITY"
tag_ignore="<![IGNORE["
tag_include="<![INCLUDE["
tag_notation="<!NOTATION"
tag_open="<a>"
tag_open_close="<a />"
tag_open_exclamation="<!"
tag_open_q="<?"
tag_sq2_close="]]>"
tag_xml_q="<?xml?>"

filename: xmltest.cpp
content: #if defined( _MSC_VER )
	#if !defined( _CRT_SECURE_NO_WARNINGS )
		#define _CRT_SECURE_NO_WARNINGS		// This test file is not intended to be secure.
	#endif
#endif

#include "tinyxml2/tinyxml2.h"
#include <string>
#include <stddef.h>
#include <stdint.h>

#if defined( _MSC_VER ) || defined (WIN32)
	#include <crtdbg.h>
	#define WIN32_LEAN_AND_MEAN
	#include <windows.h>
	_CrtMemState startMemState;
	_CrtMemState endMemState;
#else
	#include <sys/stat.h>
	#include <sys/types.h>
#endif

using namespace tinyxml2;
using namespace std;

// Entry point for LibFuzzer.
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
	std::string data_string(reinterpret_cast<const char*>(data), size);
	XMLDocument doc;
	doc.Parse( data_string.c_str() );

	return 0;
}

filename: xmltest.options
content: [libfuzzer]
dict = xml.dict