11/*
2- * Copyright (c) 2018, 2024 , Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 2018, 2025 , Oracle and/or its affiliates. All rights reserved.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * This code is free software; you can redistribute it and/or modify it
@@ -93,6 +93,14 @@ public class JDK8207760 {
9393 "\n " +
9494 "</xsl:stylesheet>" ;
9595
96+ final String xsl8349699 = """
97+ <?xml version="1.0" encoding="UTF-8"?>
98+ <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
99+ <xsl:output encoding="UTF-8" method="text" />
100+ <xsl:template match="/"><xsl:apply-templates select="node()" /></xsl:template>
101+ </xsl:stylesheet>
102+ """ ;
103+
96104 @ DataProvider (name = "xsls" )
97105 public Object [][] getDataBug8207760_cdata () {
98106 return new Object [][]{
@@ -101,32 +109,117 @@ public Object[][] getDataBug8207760_cdata() {
101109 };
102110 }
103111
112+ /*
113+ * Data for verifying the patch for JDK8349699
114+ * @see testBug8349699
115+ */
116+ @ DataProvider (name = "surrogatePair" )
117+ public Object [][] getDataFor8349699 () {
118+ return new Object [][]{
119+ // a surrogate pair in an XML element placed anywhere in a string
120+ {getXML (1024 , 1024 , "<b>\uD835 \uDF00 </b>" ), getString (1024 , 1024 , "\uD835 \uDF00 " )},
121+ {getXML (1023 , 1023 , "<b>\uD835 \uDF00 </b>" ), getString (1023 , 1023 , "\uD835 \uDF00 " )},
122+ {getXML (1023 ,0 , "<b>\uD835 \uDF00 </b>" ), getString (1023 ,0 , "\uD835 \uDF00 " )},
123+ {getXML (1023 ,120 , "<b>\uD835 \uDF00 </b>" ), getString (1023 ,120 , "\uD835 \uDF00 " )},
124+ // this is the original test as demonstrated in the bug report
125+ {getXML (1017 ,1017 , "\uD835 \uDF03 \uD835 \uDF00 \uD835 \uDF00 <b>\uD835 \uDF00 </b>\uD835 \uDF00 " ),
126+ getString (1017 ,1017 , "\uD835 \uDF03 \uD835 \uDF00 \uD835 \uDF00 \uD835 \uDF00 \uD835 \uDF00 " )},
127+ {getXML (1017 ,0 , "\uD835 \uDF03 \uD835 \uDF00 \uD835 \uDF00 <b>\uD835 \uDF00 </b>\uD835 \uDF00 " ),
128+ getString (1017 ,0 , "\uD835 \uDF03 \uD835 \uDF00 \uD835 \uDF00 \uD835 \uDF00 \uD835 \uDF00 " )},
129+ {getXML (1017 ,120 , "\uD835 \uDF03 \uD835 \uDF00 \uD835 \uDF00 <b>\uD835 \uDF00 </b>\uD835 \uDF00 " ),
130+ getString (1017 ,120 , "\uD835 \uDF03 \uD835 \uDF00 \uD835 \uDF00 \uD835 \uDF00 \uD835 \uDF00 " )},
131+ };
132+ }
133+
134+ /*
135+ * Data for verifying the patch for JDK8349699
136+ * @see testBug8349699N
137+ */
138+ @ DataProvider (name = "invalidSurrogatePair" )
139+ public Object [][] getDataFor8349699N () {
140+ return new Object [][]{
141+ // invalid pair: high/high
142+ {getXML (1024 , 1024 , "<b>\uD835 \uD835 </b>" )},
143+ {getXML (1023 , 1023 , "<b>\uD835 \uD835 </b>" )},
144+ {getXML (1023 ,0 , "<b>\uD835 \uD835 </b>" )},
145+ {getXML (1023 ,120 , "<b>\uD835 \uD835 </b>" )},
146+ // invalid pair: low/low
147+ {getXML (1024 , 1024 , "<b>\uDF00 \uDF00 </b>" )},
148+ {getXML (1023 , 1023 , "<b>\uDF00 \uDF00 </b>" )},
149+ {getXML (1023 ,0 , "<b>\uDF00 \uDF00 </b>" )},
150+ {getXML (1023 ,120 , "<b>\uDF00 \uDF00 </b>" )},
151+ // invalid pair in the original test string
152+ {getXML (1017 ,1017 , "\uD835 \uDF03 \uD835 \uDF00 \uD835 \uDF00 <b>\uD835 \uD835 </b>\uD835 \uDF00 " )},
153+ {getXML (1017 ,0 , "\uD835 \uDF03 \uD835 \uDF00 \uD835 \uDF00 <b>\uD835 \uD835 </b>\uD835 \uDF00 " )},
154+ {getXML (1017 ,120 , "\uD835 \uDF03 \uD835 \uDF00 \uD835 \uDF00 <b>\uD835 \uD835 </b>\uD835 \uDF00 " )},
155+ {getXML (1017 ,1017 , "\uD835 \uDF03 \uD835 \uDF00 \uD835 \uDF00 <b>\uDF00 \uDF00 </b>\uD835 \uDF00 " )},
156+ {getXML (1017 ,0 , "\uD835 \uDF03 \uD835 \uDF00 \uD835 \uDF00 <b>\uDF00 \uDF00 </b>\uD835 \uDF00 " )},
157+ {getXML (1017 ,120 , "\uD835 \uDF03 \uD835 \uDF00 \uD835 \uDF00 <b>\uDF00 \uDF00 </b>\uD835 \uDF00 " )},
158+ };
159+ }
160+
104161 /*
105162 * @bug 8349699
106163 * Verifies that a surrogate pair at the edge of a buffer is properly handled
107164 * when serializing into a Character section.
108165 */
109- @ Test
110- public final void testBug8349699 () throws Exception {
111- String xs = "x" .repeat (1017 );
112- String expected = xs + "\uD835 \uDF03 \uD835 \uDF00 \uD835 \uDF00 \uD835 \uDF00 \uD835 \uDF00 " ;
113- String xml = "<?xml version=\" 1.0\" ?><a>{1017x}\uD835 \uDF03 \uD835 \uDF00 \uD835 \uDF00 <b>\uD835 \uDF00 </b>\uD835 \uDF00 </a> "
114- .replace ("{1017x}" , xs );
115- String xsl = """
116- <?xml version="1.0" encoding="UTF-8"?>
117- <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
118- <xsl:output encoding="UTF-8" method="text" />
119- <xsl:template match="/"><xsl:apply-templates select="node()" /></xsl:template>
120- </xsl:stylesheet>
121- """ ;
122-
166+ @ Test (dataProvider = "surrogatePair" )
167+ public final void testBug8349699 (String xml , String expected ) throws Exception {
123168 Transformer t = createTransformerFromInputstream (
124- new ByteArrayInputStream (xsl .getBytes (StandardCharsets .UTF_8 )));
169+ new ByteArrayInputStream (xsl8349699 .getBytes (StandardCharsets .UTF_8 )));
125170 StringWriter sw = new StringWriter ();
126171 t .transform (new StreamSource (new StringReader (xml )), new StreamResult (sw ));
127172 Assert .assertEquals (sw .toString (), expected );
128173 }
129174
175+ /*
176+ * @bug 8349699
177+ * Verifies that invalid surrogate pairs are caught.
178+ */
179+ @ Test (dataProvider = "invalidSurrogatePair" )
180+ public final void testBug8349699N (String xml ) throws Exception {
181+ Assert .assertThrows (TransformerException .class , () -> {
182+ Transformer t = createTransformerFromInputstream (
183+ new ByteArrayInputStream (xsl8349699 .getBytes (StandardCharsets .UTF_8 )));
184+ StringWriter sw = new StringWriter ();
185+ t .transform (new StreamSource (new StringReader (xml )), new StreamResult (sw ));
186+ });
187+ }
188+
189+ /**
190+ * Returns an XML with the input string inserted in a text of length 'len' at
191+ * the position 'pos'.
192+ * @param len the length of the text to be placed in the XML
193+ * @param pos the position at which the input string will be inserted into the text
194+ * @param input the input string
195+ * @return an XML
196+ */
197+ private String getXML (int len , int pos , String input ) {
198+ StringBuilder sb = new StringBuilder ("<?xml version=\" 1.0\" ?><a>" );
199+ sb .append (getString (len , pos , input ));
200+ sb .append ("</a>" );
201+ return sb .toString ();
202+ }
203+
204+ /**
205+ * Returns a text string with the input string inserted at the specified position.
206+ * @param len the length of the text to be returned
207+ * @param pos the position at which the input string will be inserted into the text
208+ * @param input the input string
209+ * @return a text string
210+ */
211+ private String getString (int len , int pos , String input ) {
212+ StringBuilder sb = new StringBuilder ();
213+ if (pos == 0 ) {
214+ sb .append (input ).append ("x" .repeat (len ));
215+ } else if (pos == len ) {
216+ sb .append ("x" .repeat (len )).append (input );
217+ } else {
218+ sb .append ("x" .repeat (pos )).append (input ).append ("x" .repeat (len - pos ));
219+ }
220+ return sb .toString ();
221+ }
222+
130223 /*
131224 * @bug 8207760
132225 * Verifies that a surrogate pair at the edge of a buffer is properly handled
0 commit comments