|
1 /* |
|
2 * Copyright (c) 2006, 2018, Oracle and/or its affiliates. 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 6372340 |
|
27 * @summary Checks for infinite loop and OOM bugs dealing with Quad curves. |
|
28 * @run main/timeout=20/othervm QuadCurveOOMBug |
|
29 */ |
|
30 |
|
31 import java.awt.Shape; |
|
32 import java.awt.geom.Area; |
|
33 import java.awt.geom.GeneralPath; |
|
34 import java.awt.geom.PathIterator; |
|
35 import java.io.ByteArrayInputStream; |
|
36 import java.io.ByteArrayOutputStream; |
|
37 import java.io.DataInputStream; |
|
38 import java.io.DataOutputStream; |
|
39 import java.io.IOException; |
|
40 |
|
41 public class QuadCurveOOMBug { |
|
42 public static final String SEG_CLOSE = " SEG_CLOSE"; |
|
43 public static final String SEG_CUBICTO = " SEG_CUBICTO"; |
|
44 public static final String SEG_LINETO = " SEG_LINETO"; |
|
45 public static final String SEG_MOVETO = " SEG_MOVETO"; |
|
46 public static final String SEG_QUADTO = " SEG_QUADTO"; |
|
47 |
|
48 public static final byte[] strokedLineToSubtract = { |
|
49 0, 11, 32, 83, 69, 71, 95, 77, 79, 86, |
|
50 69, 84, 79, 68, 117, 7, -63, 67, 15, 6, |
|
51 87, 0, 11, 32, 83, 69, 71, 95, 76, 73, |
|
52 78, 69, 84, 79, 68, 117, 31, 16, 67, 15, |
|
53 23, 5, 0, 11, 32, 83, 69, 71, 95, 81, |
|
54 85, 65, 68, 84, 79, 68, 117, 68, -12, 67, |
|
55 15, 50, 54, 68, 117, 103, 16, 67, 15, 50, |
|
56 59, 0, 11, 32, 83, 69, 71, 95, 76, 73, |
|
57 78, 69, 84, 79, 68, 117, 110, 14, 67, 15, |
|
58 50, 59, 0, 11, 32, 83, 69, 71, 95, 81, |
|
59 85, 65, 68, 84, 79, 68, 117, -56, 26, 67, |
|
60 15, 48, -15, 68, 118, 22, 75, 67, 14, 112, |
|
61 95, 0, 11, 32, 83, 69, 71, 95, 81, 85, |
|
62 65, 68, 84, 79, 68, 118, 61, 115, 67, 14, |
|
63 15, 10, 68, 118, 94, 93, 67, 13, 127, -74, |
|
64 0, 11, 32, 83, 69, 71, 95, 76, 73, 78, |
|
65 69, 84, 79, 68, 118, 103, -80, 67, 13, 87, |
|
66 15, 0, 11, 32, 83, 69, 71, 95, 81, 85, |
|
67 65, 68, 84, 79, 68, 118, 21, -76, 67, 14, |
|
68 -81, -105, 68, 117, -100, -84, 67, 14, -72, 72, |
|
69 0, 11, 32, 83, 69, 71, 95, 76, 73, 78, |
|
70 69, 84, 79, 68, 117, -88, 84, 67, 14, -72, |
|
71 72, 0, 11, 32, 83, 69, 71, 95, 81, 85, |
|
72 65, 68, 84, 79, 68, 117, 108, 85, 67, 14, |
|
73 -73, 106, 68, 117, 53, 117, 67, 14, 74, |
|
74 -61, 0, 11, 32, 83, 69, 71, 95, 76, 73, 78, |
|
75 69, 84, 79, 68, 117, 72, 27, 67, 14, 112, |
|
76 14, 0, 11, 32, 83, 69, 71, 95, 76, 73, |
|
77 78, 69, 84, 79, 68, 118, 87, -51, 67, 5, |
|
78 -16, 100, 0, 11, 32, 83, 69, 71, 95, 76, |
|
79 73, 78, 69, 84, 79, 68, 118, 69, 39, 67, |
|
80 5, -53, 25, 0, 11, 32, 83, 69, 71, 95, |
|
81 81, 85, 65, 68, 84, 79, 68, 117, -5, -93, |
|
82 67, 5, 57, 38, 68, 117, -88, 84, 67, 5, |
|
83 56, 72, 0, 11, 32, 83, 69, 71, 95, 76, |
|
84 73, 78, 69, 84, 79, 68, 117, -100, -84, 67, |
|
85 5, 56, 72, 0, 11, 32, 83, 69, 71, 95, |
|
86 81, 85, 65, 68, 84, 79, 68, 117, 12, 86, |
|
87 67, 5, 64, -7, 68, 116, -89, -76, 67, |
|
88 6, -22, -51, 0, 11, 32, 83, 69, 71, 95, 76, |
|
89 73, 78, 69, 84, 79, 68, 116, -98, 97, 67, |
|
90 7, 19, 116, 0, 11, 32, 83, 69, 71, 95, |
|
91 81, 85, 65, 68, 84, 79, 68, 116, -75, -100, |
|
92 67, 6, -83, -7, 68, 116, -44, -9, 67, 6, |
|
93 95, -59, 0, 11, 32, 83, 69, 71, 95, 81, |
|
94 85, 65, 68, 84, 79, 68, 117, 26, -119, 67, |
|
95 5, -76, 14, 68, 117, 110, 14, 67, 5, -78, |
|
96 59, 0, 11, 32, 83, 69, 71, 95, 76, 73, |
|
97 78, 69, 84, 79, 68, 117, 103, 16, 67, 5, |
|
98 -78, 59, 0, 11, 32, 83, 69, 71, 95, 81, |
|
99 85, 65, 68, 84, 79, 68, 117, 122, -71, 67, |
|
100 5, -78, 22, 68, 117, -119, -60, 67, 5, -68, |
|
101 -61, 0, 11, 32, 83, 69, 71, 95, 76, 73, |
|
102 78, 69, 84, 79, 68, 117, 114, 117, 67, 5, |
|
103 -84, 21, 0, 11, 32, 83, 69, 71, 95, 76, |
|
104 73, 78, 69, 84, 79, 68, 117, 7, -63, 67, |
|
105 15, 6, 87, 0, 10, 32, 83, 69, 71, 95, |
|
106 67, 76, 79, 83, 69, |
|
107 }; |
|
108 |
|
109 public static final byte[] negSpace = { |
|
110 0, 11, 32, 83, 69, 71, 95, 77, 79, 86, |
|
111 69, 84, 79, 68, 116, -33, -12, 67, 4, 30, |
|
112 -23, 0, 11, 32, 83, 69, 71, 95, 76, 73, |
|
113 78, 69, 84, 79, 68, 118, 59, 73, 67, 6, |
|
114 -43, -109, 0, 11, 32, 83, 69, 71, 95, 76, |
|
115 73, 78, 69, 84, 79, 68, 117, 100, -97, 67, |
|
116 13, -118, -32, 0, 11, 32, 83, 69, 71, 95, |
|
117 76, 73, 78, 69, 84, 79, 68, 116, 9, 75, |
|
118 67, 10, -44, 54, 0, 10, 32, 83, 69, 71, |
|
119 95, 67, 76, 79, 83, 69, |
|
120 }; |
|
121 |
|
122 public static final byte[] strokedLineToAdd = { |
|
123 0, 11, 32, 83, 69, 71, 95, 77, 79, 86, |
|
124 69, 84, 79, 68, 98, -100, -76, 67, -85, -36, |
|
125 6, 0, 11, 32, 83, 69, 71, 95, 76, 73, |
|
126 78, 69, 84, 79, 68, 98, -76, 4, 67, -85, |
|
127 -48, 21, 0, 11, 32, 83, 69, 71, 95, 81, |
|
128 85, 65, 68, 84, 79, 68, 98, -102, -29, 67, |
|
129 -85, -36, -5, 68, 98, -112, 107, 67, -85, |
|
130 -35, 5, 0, 11, 32, 83, 69, 71, 95, 76, 73, |
|
131 78, 69, 84, 79, 68, 98, -84, 99, 67, -85, |
|
132 -35, 5, 0, 11, 32, 83, 69, 71, 95, 81, |
|
133 85, 65, 68, 84, 79, 68, 98, -87, 1, 67, |
|
134 -85, -35, 1, 68, 98, -107, -10, 67, -85, -43, |
|
135 23, 0, 11, 32, 83, 69, 71, 95, 76, 73, |
|
136 78, 69, 84, 79, 68, 98, -95, -98, 67, -85, |
|
137 -39, -11, 0, 11, 32, 83, 69, 71, 95, 81, |
|
138 85, 65, 68, 84, 79, 68, 98, -53, -8, 67, |
|
139 -85, -21, -99, 68, 98, -10, -6, 67, -85, |
|
140 -21, -95, 0, 11, 32, 83, 69, 71, 95, 76, 73, |
|
141 78, 69, 84, 79, 68, 99, 2, -94, 67, -85, |
|
142 -21, -95, 0, 11, 32, 83, 69, 71, 95, 81, |
|
143 85, 65, 68, 84, 79, 68, 98, -56, -104, 67, |
|
144 -85, -21, 61, 68, 98, -109, 28, 67, -85, -73, |
|
145 -35, 0, 11, 32, 83, 69, 71, 95, 76, 73, |
|
146 78, 69, 84, 79, 68, 98, -91, -62, 67, -85, |
|
147 -55, -22, 0, 11, 32, 83, 69, 71, 95, 76, |
|
148 73, 78, 69, 84, 79, 68, 99, -82, -62, 67, |
|
149 -89, -125, 126, 0, 11, 32, 83, 69, 71, 95, |
|
150 76, 73, 78, 69, 84, 79, 68, 99, -100, 28, |
|
151 67, -89, 113, 113, 0, 11, 32, 83, 69, 71, |
|
152 95, 81, 85, 65, 68, 84, 79, 68, 99, 83, |
|
153 -6, 67, -89, 44, 5, 68, 99, 2, -94, 67, |
|
154 -89, 43, -95, 0, 11, 32, 83, 69, 71, 95, |
|
155 76, 73, 78, 69, 84, 79, 68, 98, -10, -6, |
|
156 67, -89, 43, -95, 0, 11, 32, 83, 69, 71, |
|
157 95, 81, 85, 65, 68, 84, 79, 68, 99, 10, |
|
158 -82, 67, -89, 43, -91, 68, 99, 29, -72, 67, |
|
159 -89, 51, -113, 0, 11, 32, 83, 69, 71, 95, |
|
160 76, 73, 78, 69, 84, 79, 68, 99, 18, 16, |
|
161 67, -89, 46, -79, 0, 11, 32, 83, 69, 71, |
|
162 95, 81, 85, 65, 68, 84, 79, 68, 98, -25, |
|
163 -73, 67, -89, 29, 9, 68, 98, -84, 99, 67, |
|
164 -89, 29, 5, 0, 11, 32, 83, 69, 71, 95, |
|
165 76, 73, 78, 69, 84, 79, 68, 98, -112, 107, |
|
166 67, -89, 29, 5, 0, 11, 32, 83, 69, 71, |
|
167 95, 81, 85, 65, 68, 84, 79, 68, 98, 78, |
|
168 121, 67, -89, 28, -15, 68, 98, 29, -110, 67, |
|
169 -89, 53, -27, 0, 11, 32, 83, 69, 71, 95, |
|
170 76, 73, 78, 69, 84, 79, 68, 98, 6, 66, |
|
171 67, -89, 65, -42, 0, 11, 32, 83, 69, 71, |
|
172 95, 76, 73, 78, 69, 84, 79, 68, 98, -100, |
|
173 -76, 67, -85, -36, 6, 0, 10, 32, 83, 69, |
|
174 71, 95, 67, 76, 79, 83, 69, |
|
175 }; |
|
176 |
|
177 public static final byte[] shapeAdded = { |
|
178 0, 11, 32, 83, 69, 71, 95, 77, 79, 86, |
|
179 69, 84, 79, 68, 102, 54, -63, 67, -84, -102, |
|
180 29, 0, 11, 32, 83, 69, 71, 95, 76, 73, 78, |
|
181 69, 84, 79, 68, 96, -120, 114, 67, -94, |
|
182 2, 48, 0, 11, 32, 83, 69, 71, 95, 76, 73, |
|
183 78, 69, 84, 79, 68, 94, -119, 0, 67, |
|
184 -86, 67, -25, 0, 10, 32, 83, 69, 71, 95, |
|
185 67, 76, 79, 83, 69, |
|
186 }; |
|
187 |
|
188 public static void main(String[] args) { |
|
189 // Reversing the order of these try blocks has no effect. |
|
190 try { |
|
191 testAdd(); |
|
192 } catch (IOException ioe) { |
|
193 ioe.printStackTrace(); |
|
194 } |
|
195 |
|
196 try { |
|
197 testSubtract(); |
|
198 } catch (IOException e) { |
|
199 e.printStackTrace(); |
|
200 } |
|
201 } |
|
202 |
|
203 private static void testSubtract() throws IOException |
|
204 { |
|
205 Shape lineShape = loadShape(strokedLineToSubtract, "Line"); |
|
206 Shape negShape = loadShape(negSpace, "Space"); |
|
207 Area lineArea = new Area(lineShape); |
|
208 Area negArea = new Area(negShape); |
|
209 System.err.println("Attempting to subtract ... "); |
|
210 lineArea.subtract(negArea); // This is what throws the OutOfMemoryError |
|
211 System.err.println("Subtraction succeeded."); |
|
212 } |
|
213 |
|
214 private static void testAdd() throws IOException |
|
215 { |
|
216 Shape lineShape = loadShape(strokedLineToAdd, "Line"); |
|
217 Shape negShape = loadShape(shapeAdded, "Space"); |
|
218 Area lineArea = new Area(lineShape); |
|
219 Area negArea = new Area(negShape); |
|
220 System.err.println("Attempting to add ... "); |
|
221 lineArea.add(negArea); // This is what throws the OutOfMemoryError |
|
222 System.err.println("Addition succeeded."); |
|
223 } |
|
224 |
|
225 /** |
|
226 * Although this method isn't used by this test case, this is the method |
|
227 * used to create the two data sets that the test case uses. |
|
228 * @param name The name to give to the variable |
|
229 * @param shape |
|
230 */ |
|
231 public static void saveShapeData(Shape shape, String name) |
|
232 { |
|
233 ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); |
|
234 DataOutputStream os = new DataOutputStream(byteStream); |
|
235 try { |
|
236 saveShapeToStream(shape, os); |
|
237 System.out.println("\npublic static final byte[] " + |
|
238 name + " = {\n"); |
|
239 byte[] data = byteStream.toByteArray(); |
|
240 int ii=0; |
|
241 for (byte bt : data) |
|
242 System.out.print(" " + Byte.toString(bt) + "," + |
|
243 ((++ii)%20==0? "\n":"")); |
|
244 System.out.println("};"); |
|
245 } catch (IOException e) { |
|
246 e.printStackTrace(); |
|
247 } |
|
248 } |
|
249 |
|
250 private static void saveShapeToStream(Shape shape, DataOutputStream pOs) |
|
251 throws IOException |
|
252 { |
|
253 PathIterator iter = shape.getPathIterator(null); |
|
254 float[] coords = new float[6]; |
|
255 while(!iter.isDone()) { |
|
256 int type = iter.currentSegment(coords); |
|
257 switch(type) { |
|
258 case PathIterator.SEG_CLOSE: |
|
259 pOs.writeUTF(SEG_CLOSE); |
|
260 break; |
|
261 case PathIterator.SEG_CUBICTO: |
|
262 pOs.writeUTF(SEG_CUBICTO); |
|
263 for (float coord : coords) |
|
264 pOs.writeFloat(coord); |
|
265 break; |
|
266 case PathIterator.SEG_LINETO: |
|
267 pOs.writeUTF(SEG_LINETO); |
|
268 pOs.writeFloat(coords[0]); |
|
269 pOs.writeFloat(coords[1]); |
|
270 break; |
|
271 case PathIterator.SEG_MOVETO: |
|
272 pOs.writeUTF(SEG_MOVETO); |
|
273 pOs.writeFloat(coords[0]); |
|
274 pOs.writeFloat(coords[1]); |
|
275 break; |
|
276 case PathIterator.SEG_QUADTO: |
|
277 pOs.writeUTF(SEG_QUADTO); |
|
278 for (int ii=0; ii<4; ++ii) |
|
279 pOs.writeFloat(coords[ii]); |
|
280 break; |
|
281 default: |
|
282 System.err.print(" UNKNOWN:" + type); |
|
283 break; |
|
284 } |
|
285 iter.next(); |
|
286 } |
|
287 } |
|
288 |
|
289 |
|
290 public static Shape loadShape(byte[] fileData, String name) |
|
291 throws IOException |
|
292 { |
|
293 System.out.println("\n\n" + name + ":"); |
|
294 GeneralPath path = new GeneralPath(); |
|
295 path.setWindingRule(GeneralPath.WIND_NON_ZERO); |
|
296 DataInputStream is=null; |
|
297 is = new DataInputStream(new ByteArrayInputStream(fileData)); |
|
298 float[] coords = new float[6]; |
|
299 while (is.available()>0) |
|
300 { |
|
301 String type = is.readUTF(); |
|
302 System.out.print("\n" + type + "\n "); |
|
303 if (type.equals(SEG_CLOSE)) { |
|
304 path.closePath(); |
|
305 } else if (type.equals(SEG_CUBICTO)) { |
|
306 for (int ii=0; ii<6; ++ii) |
|
307 coords[ii] = readFloat(is); |
|
308 path.curveTo(coords[0], coords[1], |
|
309 coords[2], coords[3], |
|
310 coords[4], coords[5]); |
|
311 } else if (type.equals(SEG_LINETO)) { |
|
312 for (int ii=0; ii<2; ++ii) |
|
313 coords[ii] = readFloat(is); |
|
314 path.lineTo(coords[0], coords[1]); |
|
315 } else if (type.equals(SEG_MOVETO)) { |
|
316 for (int ii=0; ii<2; ++ii) |
|
317 coords[ii] = readFloat(is); |
|
318 path.moveTo(coords[0], coords[1]); |
|
319 } else if (type.equals(SEG_QUADTO)) { |
|
320 for (int ii=0; ii<4; ++ii) |
|
321 coords[ii] = readFloat(is); |
|
322 path.quadTo(coords[0], coords[1], coords[2], coords[3]); |
|
323 } |
|
324 } |
|
325 return path; |
|
326 } |
|
327 |
|
328 /** |
|
329 * This call reads all the float values and prints them out. |
|
330 * @param is |
|
331 * @return |
|
332 * @throws IOException |
|
333 */ |
|
334 private static float readFloat(DataInputStream is) throws IOException |
|
335 { |
|
336 float ft = is.readFloat(); |
|
337 System.out.print("" + ft + ", "); |
|
338 return ft; |
|
339 } |
|
340 } |