1
1
/*
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.
3
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
4
*
5
5
* This code is free software; you can redistribute it and/or modify it
41
41
42
42
/*
43
43
* @test
44
+ * @bug 8207760 8349699
45
+ * @summary Verifies that a surrogate pair at the edge of a buffer is properly handled
44
46
* @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
45
47
* @run testng/othervm transform.JDK8207760
46
- * @summary Verifies that a surrogate pair at the edge of a buffer is properly handled
47
- * @bug 8207760
48
48
*/
49
49
public class JDK8207760 {
50
50
final String xsl8207760 =
@@ -93,6 +93,14 @@ public class JDK8207760 {
93
93
"\n " +
94
94
"</xsl:stylesheet>" ;
95
95
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
+
96
104
@ DataProvider (name = "xsls" )
97
105
public Object [][] getDataBug8207760_cdata () {
98
106
return new Object [][]{
@@ -101,6 +109,117 @@ public Object[][] getDataBug8207760_cdata() {
101
109
};
102
110
}
103
111
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
+
161
+ /*
162
+ * @bug 8349699
163
+ * Verifies that a surrogate pair at the edge of a buffer is properly handled
164
+ * when serializing into a Character section.
165
+ */
166
+ @ Test (dataProvider = "surrogatePair" )
167
+ public final void testBug8349699 (String xml , String expected ) throws Exception {
168
+ Transformer t = createTransformerFromInputstream (
169
+ new ByteArrayInputStream (xsl8349699 .getBytes (StandardCharsets .UTF_8 )));
170
+ StringWriter sw = new StringWriter ();
171
+ t .transform (new StreamSource (new StringReader (xml )), new StreamResult (sw ));
172
+ Assert .assertEquals (sw .toString (), expected );
173
+ }
174
+
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
+
104
223
/*
105
224
* @bug 8207760
106
225
* Verifies that a surrogate pair at the edge of a buffer is properly handled
0 commit comments