--- a/jdk/test/java/io/Serializable/6559775/README Tue Sep 28 01:13:22 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-The testcase works well on dual core machines.
-The below output indicates a successful fix:
-
-Exception in thread "Thread-0" java.lang.NullPointerException
- at java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:476)
- at SerialRace$1.run(SerialRace.java:33)
- at java.lang.Thread.run(Thread.java:595)
-
-
-When the vulnerability exists, the output of the tescase is something like this:
-Available processors: 2
-Iteration 1
-java.io.NotActiveException: not in readObject invocation or fields already read
- at java.io.ObjectInputStream$CallbackContext.checkAndSetUsed(ObjectInputStream.java:3437)
- at java.io.ObjectInputStream$CallbackContext.getObj(ObjectInputStream.java:3427)
- at java.io.ObjectInputStream.readFields(ObjectInputStream.java:514)
- at SerialVictim.readObject(SerialVictim.java:19)
- at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
- at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
- at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
- at java.lang.reflect.Method.invoke(Method.java:585)
- at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:946)
- at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1809)
- at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1719)
- at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1305)
- at java.io.ObjectInputStream.readObject(ObjectInputStream.java:348)
- at SerialRace.main(SerialRace.java:65)
-Victim: ?
-Victim: $
--- a/jdk/test/java/io/Serializable/6559775/SerialRace.java Tue Sep 28 01:13:22 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/*
- * @test %W% %E%
- * @bug 6559775
- * @summary Race allows defaultReadObject to be invoked instead of readFields during deserialization
- * @run shell Test6559775.sh
-*/
-
-import java.io.*;
-
-public class SerialRace {
- public static void main(String[] args) throws Exception {
- System.err.println(
- "Available processors: "+
- Runtime.getRuntime().availableProcessors()
- );
-
- final int perStream = 10000;
-
- // Construct attack data.
- ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
- {
- ObjectOutputStream out = new ObjectOutputStream(byteOut);
- char[] value = new char[] { '?' };
- out.writeObject(value);
- for (int i=0; i<perStream; ++i) {
- SerialVictim orig = new SerialVictim(value);
- out.writeObject(orig);
- }
- out.flush();
- }
- byte[] data = byteOut.toByteArray();
-
- ByteArrayInputStream byteIn = new ByteArrayInputStream(data);
- final ObjectInputStream in = new ObjectInputStream(byteIn);
- final char[] value = (char[])in.readObject();
- Thread thread = new Thread(new Runnable() { public void run() {
- for (;;) {
- try {
- // Attempt to interlope on other thread.
- in.defaultReadObject();
- // Got it.
-
- // Let other thread reach known state.
- Thread.sleep(1000);
- // This is the reference usually
- // read in extended data.
- SerialVictim victim = (SerialVictim)
- in.readObject();
- System.err.println("Victim: "+victim);
- value[0] = '$';
- System.err.println("Victim: "+victim);
- return;
- } catch (java.io.NotActiveException exc) {
- // Not ready yet...
- } catch (java.lang.InterruptedException exc) {
- throw new Error(exc);
- } catch (IOException exc) {
- throw new Error(exc);
- } catch (ClassNotFoundException exc) {
- throw new Error(exc);
- }
- }
- }});
- thread.start();
- Thread.yield();
- // Normal reading from object stream.
- // We hope the other thread catches us out between
- // setting up the call to SerialVictim.readObject and
- // the AtomicBoolean acquisition in readFields.
- for (int i=0; i<perStream; ++i) {
- try {
- SerialVictim victim = (SerialVictim)in.readObject();
- } catch (Exception exc) {
- synchronized (System.err) {
- System.err.println("Iteration "+i);
- exc.printStackTrace();
- }
- // Allow atack thread to do it's business before close.
- Thread.sleep(2000);
- break;
- }
- }
- // Stop the other thread.
- in.close();
- }
-}
--- a/jdk/test/java/io/Serializable/6559775/SerialVictim.java Tue Sep 28 01:13:22 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/**
- * Instances of this class created through deserialization
- * should, in theory, be immutable.
- * Instances created through the public constructor
- * are only to ease creation of the binary attack data.
- */
-
-public class SerialVictim implements java.io.Serializable {
- private char[] value;
- public SerialVictim(char[] value) {
- this.value = value;
- }
- //@Override
- public String toString() {
- return new String(value);
- }
- private void readObject(
- java.io.ObjectInputStream in
- ) throws java.io.IOException, java.lang.ClassNotFoundException {
- java.io.ObjectInputStream.GetField fields = in.readFields();
- // Clone before write should, in theory, make instance safe.
- this.value = (char[])((char[])fields.get("value", null)).clone();
- in.readObject();
- }
- private void writeObject(
- java.io.ObjectOutputStream out
- ) throws java.io.IOException {
- out.defaultWriteObject();
- out.writeObject(this);
- }
-}
--- a/jdk/test/java/io/Serializable/6559775/Test6559775.sh Tue Sep 28 01:13:22 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-#!/bin/sh
-
-if [ "${TESTSRC}" = "" ]
-then TESTSRC=.
-fi
-
-if [ "${TESTJAVA}" = "" ]
-then
- PARENT=`dirname \`which java\``
- TESTJAVA=`dirname ${PARENT}`
- echo "TESTJAVA not set, selecting " ${TESTJAVA}
- echo "If this is incorrect, try setting the variable manually."
-fi
-
-if [ "${TESTCLASSES}" = "" ]
-then
- echo "TESTCLASSES not set. Test cannot execute. Failed."
- exit 1
-fi
-
-BIT_FLAG=""
-
-# set platform-dependent variables
-OS=`uname -s`
-case "$OS" in
- SunOS | Linux )
- NULL=/dev/null
- PS=":"
- FS="/"
- ## for solaris, linux it's HOME
- FILE_LOCATION=$HOME
- if [ -f ${FILE_LOCATION}${FS}JDK64BIT -a ${OS} = "SunOS" ]
- then
- BIT_FLAG=`cat ${FILE_LOCATION}${FS}JDK64BIT | grep -v '^#'`
- fi
- ;;
- Windows_* )
- NULL=NUL
- PS=";"
- FS="\\"
- ;;
- * )
- echo "Unrecognized system!"
- exit 1;
- ;;
-esac
-
-JEMMYPATH=${CPAPPEND}
-CLASSPATH=.${PS}${TESTCLASSES}${PS}${JEMMYPATH} ; export CLASSPATH
-
-THIS_DIR=`pwd`
-
-${TESTJAVA}${FS}bin${FS}java ${BIT_FLAG} -version
-
-cp ${TESTSRC}${FS}*.java .
-chmod 777 *.java
-
-${TESTJAVA}${FS}bin${FS}javac SerialRace.java
-
-${TESTJAVA}${FS}bin${FS}java ${BIT_FLAG} SerialRace > test.out 2>&1
-
-cat test.out
-
-STATUS=0
-
-egrep "java.io.NotActiveException|not in readObject invocation or fields already read|^Victim" test.out
-
-if [ $? = 0 ]
-then
- STATUS=1
-else
- grep "java.lang.NullPointerException" test.out
-
- if [ $? != 0 ]; then
- STATUS=1
- fi
-fi
-
-exit $STATUS
--- a/jdk/test/java/io/Serializable/6966692/Attack.java Tue Sep 28 01:13:22 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * @test
- * @bug 6966692
- * @summary defaultReadObject can set a field multiple times
- * @run shell Test6966692.sh
-*/
-
-import java.io.*;
-
-public class Attack {
- public static void main(String[] args) throws Exception {
- attack(setup());
- }
- /** Returned data has Victim with two aaaa fields. */
- private static byte[] setup() throws Exception {
- Victim victim = new Victim();
- ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
- ObjectOutputStream out = new ObjectOutputStream(byteOut);
- out.writeObject(victim);
- out.close();
- byte[] data = byteOut.toByteArray();
- String str = new String(data, 0); // hibyte is 0
- str = str.replaceAll("bbbb", "aaaa");
- str.getBytes(0, data.length, data, 0); // ignore hibyte
- return data;
- }
- private static void attack(byte[] data) throws Exception {
- ObjectInputStream in = new ObjectInputStream(
- new ByteArrayInputStream(data)
- );
- Victim victim = (Victim)in.readObject();
- System.out.println(victim+" "+victim.aaaa);
- }
-}
--- a/jdk/test/java/io/Serializable/6966692/README Tue Sep 28 01:13:22 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-Testcase shows default deserialisation of the Victim having two values for the same field.
-
-Probably requires dual core to run successfully.
-
-Reading thread is warmed up so that it can easily win the race for the demonstration, but this means we need to make the field volatile.
-
-Typical output:
-
-Victim@1551f60 BBBB
-Victim@1551f60 AAAA
-
-The output when its fixed is,
-Victim@1975b59 AAAA
-Victim@1975b59 AAAA - The value is retained
-
-and when it is not fixed, it shows something like
-Victim@173a10f AAAA
-Victim@173a10f BBBB - the value of the object gets set again and hence is different. This is a bug
-
-Look at the
-AAAA AAAA
-and
-AAAA BBBB
--- a/jdk/test/java/io/Serializable/6966692/Test6966692.sh Tue Sep 28 01:13:22 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-#!/bin/sh
-
-if [ "${TESTSRC}" = "" ]
-then TESTSRC=.
-fi
-
-if [ "${TESTJAVA}" = "" ]
-then
- PARENT=`dirname \`which java\``
- TESTJAVA=`dirname ${PARENT}`
- echo "TESTJAVA not set, selecting " ${TESTJAVA}
- echo "If this is incorrect, try setting the variable manually."
-fi
-
-if [ "${TESTCLASSES}" = "" ]
-then
- echo "TESTCLASSES not set. Test cannot execute. Failed."
- exit 1
-fi
-
-BIT_FLAG=""
-
-# set platform-dependent variables
-OS=`uname -s`
-case "$OS" in
- SunOS | Linux )
- NULL=/dev/null
- PS=":"
- FS="/"
- ## for solaris, linux it's HOME
- FILE_LOCATION=$HOME
- if [ -f ${FILE_LOCATION}${FS}JDK64BIT -a ${OS} = "SunOS" ]
- then
- BIT_FLAG=`cat ${FILE_LOCATION}${FS}JDK64BIT | grep -v '^#'`
- fi
- ;;
- Windows_* )
- NULL=NUL
- PS=";"
- FS="\\"
- ;;
- * )
- echo "Unrecognized system!"
- exit 1;
- ;;
-esac
-
-JEMMYPATH=${CPAPPEND}
-CLASSPATH=.${PS}${TESTCLASSES}${PS}${JEMMYPATH} ; export CLASSPATH
-
-THIS_DIR=`pwd`
-
-${TESTJAVA}${FS}bin${FS}java ${BIT_FLAG} -version
-
-cp ${TESTSRC}${FS}*.java .
-chmod 777 *.java
-
-${TESTJAVA}${FS}bin${FS}javac *.java
-
-${TESTJAVA}${FS}bin${FS}java ${BIT_FLAG} Attack > test.out 2>&1
-
-cat test.out
-
-STATUS=0
-
-egrep "^Victim.*BBBB.*AAAA|^Victim.*AAAA.*BBBB" test.out
-
-if [ $? = 0 ]
-then
- STATUS=1
-else
- egrep "^Victim.*BBBB.*BBBB|^Victim.*AAAA.*AAAA" test.out
-
- if [ $? != 0 ]; then
- STATUS=1
- fi
-fi
-
-exit $STATUS
--- a/jdk/test/java/io/Serializable/6966692/Victim.java Tue Sep 28 01:13:22 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-import java.io.*;
-
-public class Victim implements Serializable {
- public volatile Object aaaa = "AAAA"; // must be volatile...
- private final Object aabb = new Show(this);
- public Object bbbb = "BBBB";
-}
-class Show implements Serializable {
- private final Victim victim;
- public Show(Victim victim) {
- this.victim = victim;
- }
- private void readObject(java.io.ObjectInputStream in)
- throws IOException, ClassNotFoundException
- {
- in.defaultReadObject();
- Thread thread = new Thread(new Runnable() { public void run() {
- for (;;) {
- Object a = victim.aaaa;
- if (a != null) {
- System.err.println(victim+" "+a);
- break;
- }
- }
- }});
- thread.start();
-
- // Make sure we are running compiled whilst serialisation is done interpreted.
- try {
- Thread.sleep(1000);
- } catch (java.lang.InterruptedException exc) {
- Thread.currentThread().interrupt();
- }
- }
-}