GNOME Bugzilla – Bug 527297
xsltproc crashes when applying a transform to an xml document
Last modified: 2008-04-14 09:22:25 UTC
Steps to reproduce: I ran the following command: xsltproc --novalid --html run.xsl xml/MS06-009.xml 2>/dev/null >output with the following run.xsl: <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="xml"/> <xsl:template match="html/body/table/tr/td/div/div/div/div/div/div/div/div/table/tr/td/table/tr/td/p/b"> <xsl:if test="contains(text(), 'published')"> <found/> </xsl:if> </xsl:template> </xsl:stylesheet> The document named MS06-009.xml can be obtained at http://www.microsoft.com/technet/security/Bulletin/MS06-009.mspx. I pre-processed it using the following command: xmllint --html --recover --loaddtd --xmlout MS06-009.mspx | $(XMLLINT) --format - > MS06-009.xml Stack trace: guerrilla@delta64:/tmp/xmlsearch (0) % gdb `which xsltproc` /cores/xsltproc.9073.1000.1207814422 GNU gdb 6.6 Copyright (C) 2006 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "x86_64-slackware-linux"... (no debugging symbols found) Using host libthread_db library "/lib/libthread_db.so.1". warning: Can't read pathname for load map: Input/output error. Reading symbols from /usr/lib/libxslt.so.1...(no debugging symbols found)...done. Loaded symbols for /usr/lib/libxslt.so.1 Reading symbols from /usr/lib/libexslt.so.0...(no debugging symbols found)...done. Loaded symbols for /usr/lib/libexslt.so.0 Reading symbols from /usr/lib/libgcrypt.so.11...(no debugging symbols found)...done. Loaded symbols for /usr/lib/libgcrypt.so.11 Reading symbols from /lib/libnsl.so.1...(no debugging symbols found)...done. Loaded symbols for /lib/libnsl.so.1 Reading symbols from /usr/lib/libgpg-error.so.0...(no debugging symbols found)...done. Loaded symbols for /usr/lib/libgpg-error.so.0 Reading symbols from /usr/lib/libxml2.so.2...done. Loaded symbols for /usr/lib/libxml2.so.2 Reading symbols from /lib/libdl.so.2...done. Loaded symbols for /lib/libdl.so.2 Reading symbols from /usr/lib/libz.so.1...done. Loaded symbols for /usr/lib/libz.so.1 Reading symbols from /lib/libm.so.6...done. Loaded symbols for /lib/libm.so.6 Reading symbols from /lib/libc.so.6...done. Loaded symbols for /lib/libc.so.6 Reading symbols from /lib/ld-linux-x86-64.so.2...done. Loaded symbols for /lib/ld-linux-x86-64.so.2 warning: no loadable sections found in added symbol-file system-supplied DSO at 0x7fff1cbfd000 Core was generated by `xsltproc --novalid --html run.xsl xml/MS06-009.xml'. Program terminated with signal 11, Segmentation fault.
+ Trace 194809
Other information: guerrilla@delta64:/tmp/xmlsearch (0) % ldd `which xsltproc` linux-vdso.so.1 => (0x00007fff2d3fd000) libxslt.so.1 => /usr/lib/libxslt.so.1 (0x00002b4b7da61000) libexslt.so.0 => /usr/lib/libexslt.so.0 (0x00002b4b7dc98000) libgcrypt.so.11 => /usr/lib/libgcrypt.so.11 (0x00002b4b7deaa000) libnsl.so.1 => /lib/libnsl.so.1 (0x00002b4b7e114000) libgpg-error.so.0 => /usr/lib/libgpg-error.so.0 (0x00002b4b7e32b000) libxml2.so.2 => /usr/lib/libxml2.so.2 (0x00002b4b7e52e000) libdl.so.2 => /lib/libdl.so.2 (0x00002b4b7e8d6000) libz.so.1 => /usr/lib/libz.so.1 (0x00002b4b7eada000) libm.so.6 => /lib/libm.so.6 (0x00002b4b7ecf0000) libc.so.6 => /lib/libc.so.6 (0x00002b4b7ef74000) /lib/ld-linux-x86-64.so.2 (0x00002b4b7d844000) guerrilla@delta64:/tmp/xmlsearch (0) % ldd /usr/lib/libxslt.so.1 linux-vdso.so.1 => (0x00007fff1b9fd000) libxml2.so.2 => /usr/lib/libxml2.so.2 (0x00002b898f399000) libz.so.1 => /usr/lib/libz.so.1 (0x00002b898f740000) libm.so.6 => /lib/libm.so.6 (0x00002b898f973000) libc.so.6 => /lib/libc.so.6 (0x00002b898fbf7000) libdl.so.2 => /lib/libdl.so.2 (0x00002b898ff46000) /lib/ld-linux-x86-64.so.2 (0x0000555555554000) guerrilla@delta64:/tmp/xmlsearch (0) % ldd /usr/lib/libexslt.so.0 linux-vdso.so.1 => (0x00007fff39dfd000) libgcrypt.so.11 => /usr/lib/libgcrypt.so.11 (0x00002aea70eec000) libgpg-error.so.0 => /usr/lib/libgpg-error.so.0 (0x00002aea71138000) libxslt.so.1 => /usr/lib/libxslt.so.1 (0x00002aea7133b000) libxml2.so.2 => /usr/lib/libxml2.so.2 (0x00002aea71573000) libz.so.1 => /usr/lib/libz.so.1 (0x00002aea7191a000) libm.so.6 => /lib/libm.so.6 (0x00002aea71b4d000) libc.so.6 => /lib/libc.so.6 (0x00002aea71dd1000) libnsl.so.1 => /lib/libnsl.so.1 (0x00002aea72120000) libdl.so.2 => /lib/libdl.so.2 (0x00002aea72337000) /lib/ld-linux-x86-64.so.2 (0x0000555555554000) guerrilla@delta64:/tmp/xmlsearch (0) % ldd /usr/lib/libxml2.so.2 linux-vdso.so.1 => (0x00007fff4a1fd000) libdl.so.2 => /lib/libdl.so.2 (0x00002abd60d21000) libz.so.1 => /usr/lib/libz.so.1 (0x00002abd60f25000) libm.so.6 => /lib/libm.so.6 (0x00002abd6113b000) libc.so.6 => /lib/libc.so.6 (0x00002abd613bf000) /lib/ld-linux-x86-64.so.2 (0x0000555555554000) guerrilla@delta64:/tmp/xmlsearch (0) % xml2-config --version 2.6.32 guerrilla@delta64:/tmp/xmlsearch (0) % xslt-config --version 1.1.20 guerrilla@delta64:/tmp/xmlsearch (0) % xsltproc --version Using libxml 20632, libxslt 10120 and libexslt 813 xsltproc was compiled against libxml 20627, libxslt 10120 and libexslt 813 libxslt 10120 was compiled against libxml 20627 libexslt 813 was compiled against libxml 20627 guerrilla@delta64:/tmp/xmlsearch (0) % xmllint --version xmllint: using libxml version 20632 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
Created attachment 108977 [details] The XML document that I tried to transform This content may be copyrighted. I simply added it for consistency and convenience.
Created attachment 108978 [details] This is the transform that I tried to use
I just updated libxslt to 1.1.23 and I still have this problem: guerrilla@delta64:/tmp/xmlsearch (0) % xsltproc --version Using libxml 20632, libxslt 10123 and libexslt 813 xsltproc was compiled against libxml 20632, libxslt 10123 and libexslt 813 libxslt 10123 was compiled against libxml 20632 libexslt 813 was compiled against libxml 20632 guerrilla@delta64:/tmp/xmlsearch (0) % xslt-config --version 1.1.23
I've just recompiled libxslt 1.1.23 with debugging symbols. The backtrace and a few gdb prints follow. guerrilla@delta64:/tmp/xmlsearch (0) % gdb `which xsltproc` /cores/xsltproc.19884.1000.1207815360 GNU gdb 6.6 Copyright (C) 2006 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "x86_64-slackware-linux"... Using host libthread_db library "/lib/libthread_db.so.1". warning: Can't read pathname for load map: Input/output error. Reading symbols from /usr/lib/libxslt.so.1...done. Loaded symbols for /usr/lib/libxslt.so.1 Reading symbols from /usr/lib/libexslt.so.0...done. Loaded symbols for /usr/lib/libexslt.so.0 Reading symbols from /usr/lib/libgcrypt.so.11...done. Loaded symbols for /usr/lib/libgcrypt.so.11 Reading symbols from /usr/lib/libgpg-error.so.0...done. Loaded symbols for /usr/lib/libgpg-error.so.0 Reading symbols from /usr/lib/libxml2.so.2...done. Loaded symbols for /usr/lib/libxml2.so.2 Reading symbols from /lib/libdl.so.2...done. Loaded symbols for /lib/libdl.so.2 Reading symbols from /usr/lib/libz.so.1...done. Loaded symbols for /usr/lib/libz.so.1 Reading symbols from /lib/libm.so.6...done. Loaded symbols for /lib/libm.so.6 Reading symbols from /lib/libc.so.6...done. Loaded symbols for /lib/libc.so.6 Reading symbols from /lib/libnsl.so.1...done. Loaded symbols for /lib/libnsl.so.1 Reading symbols from /lib/ld-linux-x86-64.so.2...done. Loaded symbols for /lib64/ld-linux-x86-64.so.2 warning: no loadable sections found in added symbol-file system-supplied DSO at 0x7fff7dbfd000 Core was generated by `xsltproc --novalid --html run.xsl xml/MS06-009.xml'. Program terminated with signal 11, Segmentation fault.
+ Trace 194811
(gdb) list 171 if (comp->nsList != NULL) 172 xmlFree(comp->nsList); 173 for (i = 0;i < comp->nbStep;i++) { 174 op = &comp->steps[i]; 175 if (op->value != NULL) 176 xmlFree(op->value); 177 if (op->value2 != NULL) 178 xmlFree(op->value2); 179 if (op->value3 != NULL) 180 xmlFree(op->value3); (gdb) p comp $1 = (xsltCompMatchPtr) 0x611660 (gdb) p *comp $2 = {next = 0x0, priority = 0.5, pattern = 0x613f50 "p\037a", mode = 0x0, modeURI = 0x0, template = 0x613920, direct = 0, nbStep = 41, maxStep = 40, nsList = 0x613d00, nsNr = 1, steps = {{op = XSLT_OP_PARENT, value = 0x0, value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 0, indexExtra = 1, lenExtra = 2}, {op = XSLT_OP_ELEM, value = 0x6110f0 "`Qa", value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 3, indexExtra = 4, lenExtra = 5}, {op = XSLT_OP_PARENT, value = 0x0, value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 6, indexExtra = 7, lenExtra = 8}, {op = XSLT_OP_ELEM, value = 0x6110d0 "à\020a", value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 9, indexExtra = 10, lenExtra = 11}, {op = XSLT_OP_PARENT, value = 0x0, value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 12, indexExtra = 13, lenExtra = 14}, {op = XSLT_OP_ELEM, value = 0x6110b0 "À\020a", value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 15, indexExtra = 16, lenExtra = 17}, {op = XSLT_OP_PARENT, value = 0x0, value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 18, indexExtra = 19, lenExtra = 20}, {op = XSLT_OP_ELEM, value = 0x611090 " \020a", value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 21, indexExtra = 22, lenExtra = 23}, {op = XSLT_OP_PARENT, value = 0x0, value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 24, indexExtra = 25, lenExtra = 26}, {op = XSLT_OP_ELEM, value = 0x611070 "\200\020a", value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 27, indexExtra = 28, lenExtra = 29}, {op = XSLT_OP_PARENT, value = 0x0, value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 30, indexExtra = 31, lenExtra = 32}, {op = XSLT_OP_ELEM, value = 0x611050 "`\020a", value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 33, indexExtra = 34, lenExtra = 35}, {op = XSLT_OP_PARENT, value = 0x0, value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 36, indexExtra = 37, lenExtra = 38}, {op = XSLT_OP_ELEM, value = 0x611030 "@\020a", value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 39, indexExtra = 40, lenExtra = 41}, {op = XSLT_OP_PARENT, value = 0x0, value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 42, indexExtra = 43, lenExtra = 44}, {op = XSLT_OP_ELEM, value = 0x611010 " \020a", value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 45, indexExtra = 46, lenExtra = 47}, {op = XSLT_OP_PARENT, value = 0x0, value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 48, indexExtra = 49, lenExtra = 50}, {op = XSLT_OP_ELEM, value = 0x610ff0 "", value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 51, indexExtra = 52, lenExtra = 53}, {op = XSLT_OP_PARENT, value = 0x0, value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 54, indexExtra = 55, lenExtra = 56}, {op = XSLT_OP_ELEM, value = 0x613fd0 "", value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 57, indexExtra = 58, lenExtra = 59}, {op = XSLT_OP_PARENT, value = 0x0, value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 60, indexExtra = 61, lenExtra = 62}, {op = XSLT_OP_ELEM, value = 0x613fb0 "à\017a", value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 63, indexExtra = 64, lenExtra = 65}, {op = XSLT_OP_PARENT, value = 0x0, value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 66, indexExtra = 67, lenExtra = 68}, {op = XSLT_OP_ELEM, value = 0x613dc0 " ?a", value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 69, indexExtra = 70, lenExtra = 71}, {op = XSLT_OP_PARENT, value = 0x0, value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 72, indexExtra = 73, lenExtra = 74}, {op = XSLT_OP_ELEM, value = 0x613da0 "°=a", value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 75, indexExtra = 76, lenExtra = 77}, {op = XSLT_OP_PARENT, value = 0x0, value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 78, indexExtra = 79, lenExtra = 80}, {op = XSLT_OP_ELEM, value = 0x6115d0 "\220=a", value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 81, indexExtra = 82, lenExtra = 83}, {op = XSLT_OP_PARENT, value = 0x0, value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 84, indexExtra = 85, lenExtra = 86}, {op = XSLT_OP_ELEM, value = 0x6115b0 "À\025a", value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 87, indexExtra = 88, lenExtra = 89}, {op = XSLT_OP_PARENT, value = 0x0, value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 90, indexExtra = 91, lenExtra = 92}, {op = XSLT_OP_ELEM, value = 0x6112b0 "À?a", value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 93, indexExtra = 94, lenExtra = 95}, {op = XSLT_OP_PARENT, value = 0x0, value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 96, indexExtra = 97, lenExtra = 98}, {op = XSLT_OP_ELEM, value = 0x613b60 " \022a", value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 99, indexExtra = 100, lenExtra = 101}, {op = XSLT_OP_PARENT, value = 0x0, value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 102, indexExtra = 103, lenExtra = 104}, {op = XSLT_OP_ELEM, value = 0x613d80 " \025a", value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 105, indexExtra = 106, lenExtra = 107}, {op = XSLT_OP_PARENT, value = 0x0, value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 108, indexExtra = 109, lenExtra = 110}, {op = XSLT_OP_ELEM, value = 0x613d60 "p=a", value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 111, indexExtra = 112, lenExtra = 113}, {op = XSLT_OP_PARENT, value = 0x0, value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 114, indexExtra = 115, lenExtra = 116}, {op = XSLT_OP_ELEM, value = 0x609630 "P=a", value2 = 0x0, value3 = 0x0, comp = 0x0, previousExtra = 117, indexExtra = 118, lenExtra = 119}}} (gdb) p op $6 = (xsltStepOpPtr) 0x611f70 (gdb) p *op $4 = {op = XSLT_OP_END, value = 0xf51 <Address 0xf51 out of bounds>, value2 = 0x614070 "\006", value3 = 0x613f40 "", comp = 0x0, previousExtra = 0, indexExtra = 0, lenExtra = 0}
Created attachment 108979 [details] The output from stderr
Created attachment 108980 [details] Output from stdout Posting this may infringe on MS intellectual property, but I don't know, so remove if necessary.
I believe the problem is in libxslt/pattern.c. The 'steps' member (xsltStepOp array) in the '_xsltCompMatch' structure is statically allocated: /* TODO fix the statically allocated size steps[] */ xsltStepOp steps[40]; /* ops for computation */ This is checked for and handled in 'xsltCompMatchAdd' if (comp->nbStep >= 40) { xsltTransformError(NULL, NULL, NULL, "xsltCompMatchAdd: overflow\n"); return (-1); } However, the application does not terminate at this point. When it calls 'xsltFreeCompMatchList', 'xsltFreeCompMatch' is called as a consequence. This leads to the overflowed variable (nbSteps) being taken into account when freeing the 'steps' array. for (i = 0;i < comp->nbStep;i++) { op = &comp->steps[i]; This causes op->value (uninitialized memory, possibly part of the structure of the heap) to be freed, which is of course why it crashes. I want to point out that this is the cause of my crash but is not the only out of bounds read or write and that this may in fact be a security vulnerability. It is at the very least a Denial of Service. I will attach some valgrind output to support this. Note: I have patched my libxslt to support more than 40 elements in the array as a temporary fix, but this is certainly not a sufficient solution which fixes nothing really.
Created attachment 108982 [details] Valgrind output
Created attachment 108983 [details] [review] A trivial temporary fix for my specific usage This does not fix the problem at all, it is simply a workaround so I may continue what I am doing until the bug is fixed. The patch is for libxslt-1.1.23.
Comment on attachment 108983 [details] [review] A trivial temporary fix for my specific usage inadequate patch
Created attachment 109216 [details] [review] Proper fix for this problem and a couple of others
Bug fixed in SVN, thanks for the description of the bug, Daniel