GNOME Bugzilla – Bug 512131
crash in libxml2 xmlReader with RNG validation
Last modified: 2017-06-12 19:06:42 UTC
Steps to reproduce: 1. wget http://ufal.mff.cuni.cz/~pajas/bug.zip 2. unzip bug.zip 3. # examine the files (test*.{xml,rng} and bug.sh) 4. sh bug.sh # to see the segfault Briefly: there are 3 Relax NG schemas that refer to each other in the following way: test.rng -> test2.rng -> test3.rng. Validation with xmllint --stream --relaxng test.rng test.xml causes a segmentation fault and the valgrind report below. The samples schemas and a test file are as small as I could manage (two elements and one attribute in the test.xml). It seems however important that the validator backtracks during the validation. Make a slight modification to the schemas (e.g. swap two elements in a <group>) and all goes well. I also copy/paste the four files below. My system is SuSE 10.3 64bit, libxml2 2.6.30 from RPM, running on a notebook with x86_64 architecture (Intel(R) Core(TM)2 Duo CPU T7700 @ 2.40GHz). Stack trace: xmllint: using libxml version 20630 compiled with: Threads Tree Output Push Reader Patterns Writer SAXv1 FTP HTTP DTDValid HTML Legacy C14N Catalog XPath XPointer XInclude Iconv ISO8859X Unicode Regexps Automata Expr Schemas Schematron Modules Debug Zlib ==16990== Memcheck, a memory error detector. ==16990== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al. ==16990== Using LibVEX rev 1732, a library for dynamic binary translation. ==16990== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP. ==16990== Using valgrind-3.2.3, a dynamic binary instrumentation framework. ==16990== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al. ==16990== For more details, rerun with: -v ==16990== test.xml validates ==16990== Invalid read of size 8 ==16990== at 0x559CDC0: (within /usr/lib64/libxml2.so.2.6.30) ==16990== by 0x559D7AA: xmlRelaxNGFreeValidCtxt (in /usr/lib64/libxml2.so.2.6.30) ==16990== by 0x55996EE: xmlFreeTextReader (in /usr/lib64/libxml2.so.2.6.30) ==16990== by 0x405C0C: (within /usr/bin/xmllint) ==16990== by 0x409128: (within /usr/bin/xmllint) ==16990== by 0x5E8CB53: (below main) (in /lib64/libc-2.6.1.so) ==16990== Address 0x40800D0 is 48 bytes inside a block of size 56 free'd ==16990== at 0x4C2191B: free (in /usr/lib64/valgrind/amd64-linux/vgpreload_memcheck.so) ==16990== by 0x559D7AA: xmlRelaxNGFreeValidCtxt (in /usr/lib64/libxml2.so.2.6.30) ==16990== by 0x55996EE: xmlFreeTextReader (in /usr/lib64/libxml2.so.2.6.30) ==16990== by 0x405C0C: (within /usr/bin/xmllint) ==16990== by 0x409128: (within /usr/bin/xmllint) ==16990== by 0x5E8CB53: (below main) (in /lib64/libc-2.6.1.so) ==16990== ==16990== Invalid free() / delete / delete[] ==16990== at 0x4C2191B: free (in /usr/lib64/valgrind/amd64-linux/vgpreload_memcheck.so) ==16990== by 0x559D7AA: xmlRelaxNGFreeValidCtxt (in /usr/lib64/libxml2.so.2.6.30) ==16990== by 0x55996EE: xmlFreeTextReader (in /usr/lib64/libxml2.so.2.6.30) ==16990== by 0x405C0C: (within /usr/bin/xmllint) ==16990== by 0x409128: (within /usr/bin/xmllint) ==16990== by 0x5E8CB53: (below main) (in /lib64/libc-2.6.1.so) ==16990== Address 0x40800A0 is 0 bytes inside a block of size 56 free'd ==16990== at 0x4C2191B: free (in /usr/lib64/valgrind/amd64-linux/vgpreload_memcheck.so) ==16990== by 0x559D7AA: xmlRelaxNGFreeValidCtxt (in /usr/lib64/libxml2.so.2.6.30) ==16990== by 0x55996EE: xmlFreeTextReader (in /usr/lib64/libxml2.so.2.6.30) ==16990== by 0x405C0C: (within /usr/bin/xmllint) ==16990== by 0x409128: (within /usr/bin/xmllint) ==16990== by 0x5E8CB53: (below main) (in /lib64/libc-2.6.1.so) ==16990== ==16990== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 2 from 1) ==16990== malloc/free: in use at exit: 56 bytes in 1 blocks. ==16990== malloc/free: 529 allocs, 529 frees, 210,951 bytes allocated. ==16990== For counts of detected errors, rerun with: -v ==16990== searching for pointers to 1 not-freed blocks. ==16990== checked 266,696 bytes. ==16990== ==16990== LEAK SUMMARY: ==16990== definitely lost: 56 bytes in 1 blocks. ==16990== possibly lost: 0 bytes in 0 blocks. ==16990== still reachable: 0 bytes in 0 blocks. ==16990== suppressed: 0 bytes in 0 blocks. ==16990== Rerun with --leak-check=full to see details of leaked memory. Other information: ### test.xml <?xml version="1.0"?> <data> <foo xmlns="http://foo.cz/" version="1.2"/> </data> ### test.rng <?xml version="1.0"?> <grammar xmlns="http://relaxng.org/ns/structure/1.0"> <start> <ref name="any.element"/> </start> <define name="any.element"> <choice> <!-- the error only occurs if this externalRef is first and the data are reversed --> <externalRef href="test2.rng"/> <element> <anyName> <except> <name>foo</name> </except> </anyName> <optional> <ref name="any.element"/> </optional> </element> </choice> </define> </grammar> ### test2.rng <?xml version="1.0"?> <grammar xmlns="http://relaxng.org/ns/structure/1.0"> <start combine="choice"> <ref name="foo.element"/> </start> <include href="test3.rng"> <define name="version"> <value>1.2</value> </define> </include> </grammar> ### test3.rng <?xml version="1.0"?> <grammar xmlns="http://relaxng.org/ns/structure/1.0"> <start> <ref name="foo.element"/> </start> <define name="version"> <value>1.1</value> </define> <define name="foo.element"> <element name="foo" ns="http://foo.cz/"> <attribute name="version"> <ref name="version"/> </attribute> <empty/> </element> </define> </grammar>
Maybe this error is related (simpler to reproduce): t.xml: <t v="a"/> t.rnc: start = element t { external "a.rnc" } a.rnc: # dumps core: attribute v { key } # works: #attribute v { text } Generating rng files with trang and running xmllint dumps core: xmllint --relaxng t.rng t.xml below are the generated files: t.rng: ---------------------- <?xml version="1.0" encoding="UTF-8"?> <grammar xmlns="http://relaxng.org/ns/structure/1.0"> <start> <element name="t"> <externalRef href="a.rng"/> </element> </start> <define name="key"> <value>a</value> </define> </grammar> ---------------------- a.rng: ---------------------- <attribute name="v" xmlns="http://relaxng.org/ns/structure/1.0"> <ref name="key"/> </attribute> ----------------------
case #1 completely unrelated to the original problem. Original problem fixed in git, it was a nasty free problem, thanks Petr ! Daniel
For #1 it's different it seems the ref->define link is missing even after compilation of the schemas. I fixed the internal code to not crash if there is such a schemas build error (it was an oversight), fix the schemas compilation code to fail with an internal error too, and then fix the core of the issue which was that refs from externalRef were lost in the gramma compisition (leading to null references). paphio:~/XML -> xmllint --relaxng t.rng t.xml <?xml version="1.0"?> <t v="a"/> t.xml validates paphio:~/XML -> xmllint --stream --relaxng t.rng t.xml t.xml validates paphio:~/XML -> so fixed, thanks, Daniel