Prior to the patch the files would cause the pointer into the byte buffer to jump past * the end of the buffer and keep reading. Once it had jumped past it would continue reading * from memory until it hit a check that caused it to stop or caused a SIGSEGV. If a SIGSEGV * was not thrown that lead to spurious and misleading errors being reported. * *
The initial jump was caused because it was not checking to make sure that there were * enough bytes to read a whole UTF-16 character. It kept reading because most of the buffer * range checks used == and != rather than >= and <. The patch fixes the initial jump and then * uses inequalities in the range check to fail fast in the event of another overflow bug. */ private void checkBug28698301(String name, String expectedMessage) throws IOException, SAXException { InputStream is = getClass().getResourceAsStream(name); try { parse(is, Encoding.UTF_16, new TestHandler()); } catch (SAXParseException exception) { String message = exception.getMessage(); if (!message.equals(expectedMessage)) { fail("Expected '" + expectedMessage + "' exception, found: '" + message + "'"); } } } /** * Parses the given xml string and fires events on the given SAX handler. */ private static void parse(String xml, ContentHandler contentHandler) throws SAXException { try { XMLReader reader = new ExpatReader(); reader.setContentHandler(contentHandler); reader.parse(new InputSource(new StringReader(xml))); } catch (IOException e) { throw new AssertionError(e); } } /** * Parses xml from the given reader and fires events on the given SAX * handler. */ private static void parse(Reader in, ContentHandler contentHandler) throws IOException, SAXException { XMLReader reader = new ExpatReader(); reader.setContentHandler(contentHandler); reader.parse(new InputSource(in)); } /** * Parses xml from the given input stream and fires events on the given SAX * handler. */ private static void parse(InputStream in, Encoding encoding, ContentHandler contentHandler) throws IOException, SAXException { try { XMLReader reader = new ExpatReader(); reader.setContentHandler(contentHandler); InputSource source = new InputSource(in); source.setEncoding(encoding.expatName); reader.parse(source); } catch (IOException e) { throw new AssertionError(e); } } /** * Supported character encodings. */ private enum Encoding { US_ASCII("US-ASCII"), UTF_8("UTF-8"), UTF_16("UTF-16"), ISO_8859_1("ISO-8859-1"); final String expatName; Encoding(String expatName) { this.expatName = expatName; } } }