1 /* 2 * Copyright 2014, SAP AG. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /** 25 * @test 26 * @bug 8034087 8027359 27 * @summary XML parser may overwrite element content if that content falls onto the border of an entity scanner buffer 28 * @run main FragmentScannerBufferLimitTest 29 */ 30 import java.io.*; 31 32 import javax.xml.parsers.*; 33 import javax.xml.transform.*; 34 import org.w3c.dom.*; 35 import org.xml.sax.*; 36 37 /** 38 * Test for overwriting of XML element content by the XML parser when reading over buffer 39 * limits. 40 * 41 * We create a simple XML document of the form: 42 * 43 * <?xml version=\"1.1\"?> 44 * <ROOT> 45 * <FILLER>ffffffff...fffff</FILLER> 46 * <TEST>content</TEST><TEST2>content2</TEST2> 47 * <FILLER>ffffffff...fffffffff</FILLER> 48 * </ROOT> 49 * 50 * What's important here is, that the test content is at the border of an entity scanner 51 * buffer (XMLEntityScanner uses 8192 byte buffers). That's why there are filler elements 52 * of sufficient length that ensure there is a buffer break inside the test content 53 * and there is enough to read to require another buffer read after the content has been 54 * read. 55 * 56 * With the faulty implementation, the test content gets overwritten with characters 57 * read from the next buffer, i.e. 'f's. 58 * 59 * @author steffen.schreiber@sap.com 60 */ 61 public class FragmentScannerBufferLimitTest { 62 63 static int errCount = 0; 64 65 /** 66 * Check the test content. 67 */ 68 public static void main(String[] args) throws ParserConfigurationException, 69 SAXException, IOException, TransformerConfigurationException, 70 TransformerException, TransformerFactoryConfigurationError { 71 72 String testString = "<TEST>content</TEST><TEST2>content2</TEST2>"; 73 74 for (int i = 0; i < testString.length(); i++) { 75 test(createDocument(testString.toString(), i), ""+ i); 76 } 77 78 if (errCount == 0) { 79 System.out.println("OK"); 80 } 81 else { 82 System.out.println("ERROR"); 83 throw new RuntimeException("Parsing error: element content has been overwritten"); 84 } 85 } 86 87 /** 88 * Create the test XML document. 89 * @param testString the test content string 90 * @param bufferLimitPosition the position in the string where the buffer should break 91 * @return the document 92 */ 93 private static String createDocument(String testString, int bufferLimitPosition) throws UnsupportedEncodingException { 94 StringBuilder result = new StringBuilder(); 95 result.append("<?xml version=\"1.1\"?>"); 96 result.append("<ROOT>"); 97 98 int fillerLength = 8192 - bufferLimitPosition; 99 createFiller(result, fillerLength); 100 101 result.append(testString); 102 103 createFiller(result, 9000); 104 result.append("</ROOT>"); 105 return result.toString(); 106 } 107 108 /** 109 * Create the filler element of the given length. 110 * @param buffer the output buffer 111 * @param length the required length of the element, including the element tags 112 */ 113 private static void createFiller(StringBuilder buffer, int length) { 114 buffer.append("<FILLER>"); 115 int fillLength = length - "<FILLER></FILLER>".length(); 116 for (int i=0; i<fillLength; i++) { 117 buffer.append('f'); 118 } 119 buffer.append("</FILLER>"); 120 } 121 122 123 private static void test(String document, String testName) throws SAXException, IOException, ParserConfigurationException { 124 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 125 DocumentBuilder builder = factory.newDocumentBuilder(); 126 127 Document doc = builder.parse(new ByteArrayInputStream(document.getBytes("UTF-8"))); 128 129 // check that there is the root node 130 NodeList roots = doc.getElementsByTagName("ROOT"); 131 assert roots.getLength() == 1; 132 Node root = roots.item(0); 133 134 // check that root has children "FILLER" and "TEST" 135 NodeList children = root.getChildNodes(); 136 assert children.getLength() == 4; 137 assert children.item(0).getNodeName().equals("FILLER"); 138 assert children.item(1).getNodeName().equals("TEST"); 139 assert children.item(2).getNodeName().equals("TEST2"); 140 assert children.item(3).getNodeName().equals("FILLER"); 141 142 // check that the test node has content "content" 143 checkContent(children.item(1).getTextContent(), "content", document); 144 checkContent(children.item(2).getTextContent(), "content2", document); 145 } 146 147 private static void checkContent(String found, String expected, String document) { 148 if (! (found.equals(expected))) { 149 errCount++; 150 int bufferStart = "<?xml version=\"1.1\"?><ROOT>".length() +1; 151 int bufferStart2 = bufferStart + 8192; 152 System.err.println("\nError:: expected \"" + expected 153 + "\", but found \"" + found + "\"!"); 154 System.err.println("Buffer was (probably): [ ... " 155 + document.substring(bufferStart2 - 20, bufferStart2) + "] [" 156 + document.substring(bufferStart2, bufferStart2 + 30) + " ... ]"); 157 } 158 } 159 }