1 /* |
|
2 * @test %W% %E% |
|
3 * @bug 6559775 |
|
4 * @summary Race allows defaultReadObject to be invoked instead of readFields during deserialization |
|
5 * @run shell Test6559775.sh |
|
6 */ |
|
7 |
|
8 import java.io.*; |
|
9 |
|
10 public class SerialRace { |
|
11 public static void main(String[] args) throws Exception { |
|
12 System.err.println( |
|
13 "Available processors: "+ |
|
14 Runtime.getRuntime().availableProcessors() |
|
15 ); |
|
16 |
|
17 final int perStream = 10000; |
|
18 |
|
19 // Construct attack data. |
|
20 ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); |
|
21 { |
|
22 ObjectOutputStream out = new ObjectOutputStream(byteOut); |
|
23 char[] value = new char[] { '?' }; |
|
24 out.writeObject(value); |
|
25 for (int i=0; i<perStream; ++i) { |
|
26 SerialVictim orig = new SerialVictim(value); |
|
27 out.writeObject(orig); |
|
28 } |
|
29 out.flush(); |
|
30 } |
|
31 byte[] data = byteOut.toByteArray(); |
|
32 |
|
33 ByteArrayInputStream byteIn = new ByteArrayInputStream(data); |
|
34 final ObjectInputStream in = new ObjectInputStream(byteIn); |
|
35 final char[] value = (char[])in.readObject(); |
|
36 Thread thread = new Thread(new Runnable() { public void run() { |
|
37 for (;;) { |
|
38 try { |
|
39 // Attempt to interlope on other thread. |
|
40 in.defaultReadObject(); |
|
41 // Got it. |
|
42 |
|
43 // Let other thread reach known state. |
|
44 Thread.sleep(1000); |
|
45 // This is the reference usually |
|
46 // read in extended data. |
|
47 SerialVictim victim = (SerialVictim) |
|
48 in.readObject(); |
|
49 System.err.println("Victim: "+victim); |
|
50 value[0] = '$'; |
|
51 System.err.println("Victim: "+victim); |
|
52 return; |
|
53 } catch (java.io.NotActiveException exc) { |
|
54 // Not ready yet... |
|
55 } catch (java.lang.InterruptedException exc) { |
|
56 throw new Error(exc); |
|
57 } catch (IOException exc) { |
|
58 throw new Error(exc); |
|
59 } catch (ClassNotFoundException exc) { |
|
60 throw new Error(exc); |
|
61 } |
|
62 } |
|
63 }}); |
|
64 thread.start(); |
|
65 Thread.yield(); |
|
66 // Normal reading from object stream. |
|
67 // We hope the other thread catches us out between |
|
68 // setting up the call to SerialVictim.readObject and |
|
69 // the AtomicBoolean acquisition in readFields. |
|
70 for (int i=0; i<perStream; ++i) { |
|
71 try { |
|
72 SerialVictim victim = (SerialVictim)in.readObject(); |
|
73 } catch (Exception exc) { |
|
74 synchronized (System.err) { |
|
75 System.err.println("Iteration "+i); |
|
76 exc.printStackTrace(); |
|
77 } |
|
78 // Allow atack thread to do it's business before close. |
|
79 Thread.sleep(2000); |
|
80 break; |
|
81 } |
|
82 } |
|
83 // Stop the other thread. |
|
84 in.close(); |
|
85 } |
|
86 } |
|